Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4436241976 | |||
| f2de879737 | |||
| 018f038c78 | |||
| c66cbcd223 | |||
| 17929b09fb | |||
| 5e48823237 | |||
| 221e1f13f7 | |||
| 5abb3e6463 | |||
| 906e6f17c0 | |||
| 2191deef54 | |||
| 8abfa3c66c | |||
| 09187e4d4d | |||
| b0728419fb | |||
| 7f341d7ffb | |||
| e7b2be7ee0 | |||
| 3fd58f2cf8 | |||
| 1e429fd50d | |||
| 703edfcb31 | |||
| 80aeb2093d | |||
| 0d3eca1c33 | |||
| 3e30934a55 | |||
| a9c5918445 | |||
| d54f0b3ef1 |
@@ -1,3 +1,4 @@
|
||||
# Preserve historical source bytes and SHA-256 across platforms. No EOL conversion.
|
||||
* -text
|
||||
*.jsonl.gz binary
|
||||
artifacts/acceleration-20261001/*.tar.zst filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
@@ -34,3 +34,5 @@ id_ed25519*
|
||||
/registry/verification-runs/
|
||||
# Historical learned deltas/checkpoints are not source files.
|
||||
/models/learned/
|
||||
# Explicit, audited experiment exports only; original data stay ignored.
|
||||
!/artifacts/acceleration-20261001/*.tar.zst
|
||||
|
||||
+39
-1
@@ -1,6 +1,44 @@
|
||||
# Digital Drosophila — 当前状态
|
||||
|
||||
更新:2026-09-30。独立分支:`codex/lif-author-semantics-lab`。
|
||||
更新:2026-10-01。成果保存分支:`codex/v100-conditioning-acceleration`。
|
||||
|
||||
## 最新状态:暂停研究,CPU/GPU 两套方案保留
|
||||
|
||||
用户要求保存并上传现有成果,以后再继续。没有恢复训练、没有启动新实验,没有切换正式科学实现。
|
||||
|
||||
- Phase 4AR 按真实已提交账本停在 **1,033/30,000 轮训练及 CPU 校验、138/3,920 probes**;末个未完成提交不算完成,也不自动重试。
|
||||
- 原科学登记 SHA 为 `b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740`,注册源码为 `80aeb2093db655329774eff7b32fb6e417b8b40b`。
|
||||
- CPU 原方案、独立 CPU 校验和常驻进程方案全部保留;GPU eligibility/update 原型在两张 V100 与 4090 的固定回放上通过逐位比较,没有替换原 CPU 代码。
|
||||
- 全脑常驻回放保持原 4090 环境、原始数学与 fresh state,42/42 次逐位一致。13 组稳态配对:原运行函数中位 5.9825 → 3.7222 秒,配对倍率中位 1.6201×;不是整轮训练加速,也不是学习成功。
|
||||
- 原实验 64,034 文件/16 源码、前一轮 659 产物/13 源码均保持一致。完整历史 Phase 1–4AQ 没有重跑。
|
||||
- 公开原始/参考数据已在独立 LFS 发布分支保存;本次另保存 CPU/GPU 科学回放结果,不包含环境、编译缓存或未确认许可的软件包。
|
||||
|
||||
[CPU/GPU 方案、结果、恢复与限制](registry/acceleration-20261001/README.md) · [为什么有多个分支](docs/40-operations/branches-20261001.md)
|
||||
|
||||
以下全部是历史状态,不能据此恢复任务或认为仍在运行。
|
||||
|
||||
## 2026-10-01 00:09 的历史快照(已被上文停止状态取代)
|
||||
|
||||
Phase 4AQ 已封存为 **PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING**。Phase 4AR 的普通嗅觉 acquisition 已登记并启动,仍在执行;学习成功尚未判定,没有新 learned candidate。
|
||||
|
||||
2026-10-01 00:09:04(Asia/Shanghai)的只读账本观察:
|
||||
|
||||
- 已提交 **411/30,000** 轮训练(包含每轮更新和独立 CPU 校验)。
|
||||
- 已提交 **62/3,920** 次独立 probe。
|
||||
- 实际进程检查确认监督器、协调器和一个子进程存在;该未提交子进程不计入上述完成量。
|
||||
- 无 stopped、最终退出或 execution-complete 记录。登记 SHA 和 16 个登记源码 SHA 全部匹配;没有执行全量输入或历史产物完整性审计。
|
||||
|
||||
登记 SHA-256:`b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740`。登记科学源码提交:`80aeb2093db655329774eff7b32fb6e417b8b40b`。这与当前仓库文档提交是不同概念;后续文档提交不会替换已登记源码版本。
|
||||
|
||||
CPU 常驻原型的小范围工程验证已完成,原型未接入当前实验,也不据此更改当前运行速度或完成时间估计。
|
||||
|
||||
下一步保持原登记执行,不自动重试、不调参或读取中途学习指标。真实完整退出后,再独立进行科学 gate 和最终完整性审计。普通 acquisition 本身不自动授权后续 assay、游戏、RL、decoder 或 Web/3D。
|
||||
|
||||
[AR 登记范围](docs/progress/phase4ar-normal-acquisition.md) · [AQ 封存结果](docs/progress/phase4aq-execution-boundary.md) · [最新运行快照](registry/phase4ar-runtime-observation-20261001T000904/snapshot.json) · [本次同步说明](docs/progress/repository-sync-20261001.md) · [CPU 原型边界](docs/progress/conditioning-cpu-residency-probe-20260930.md)
|
||||
|
||||
Git 仍仅同步代码、文档和小证据。本次没有上传大型原始数据或完整运行轨迹,也没有启用 Git LFS;不代表完成全量异机备份。下方截至 Phase 4AP 的原文作为历史摘要保留,其中“尚未启动条件化”等状态已经由本节取代。
|
||||
|
||||
## 以下为截至 Phase 4AP 的历史摘要
|
||||
|
||||
## 最近已封存结果
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
面向 MaleCNS v1.0 的可审计连接组、LIF 模型、感觉接口与局部可塑性机制研究。
|
||||
**这是研究工程仓库,不是已经实现自主学习或游戏控制的果蝇。**
|
||||
|
||||
截至 2026-09-29,最新封存阶段是 **Phase 4Z:COMPLETE-EVENT-RESOLVED-PN-AUDIT**。
|
||||
截至 2026-10-01,最新正式封存科学阶段仍是 **Phase 4AQ:PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING**。
|
||||
**Phase 4AR 已按用户要求停止,暂不恢复**:已提交 1,033/30,000 轮训练及 CPU 校验、138/3,920 次独立 probe;执行尚未完成,学习成功未判定。
|
||||
本分支 `codex/v100-conditioning-acceleration` 同时保留 CPU 与 GPU 方案及两轮独立性能回放。它不是已升级的生产运行时;原登记实验和权重没有改动。远端默认分支仍为初始化分支,见[分支说明](docs/40-operations/branches-20261001.md)。
|
||||
项目顶层验收口径为 **5/10(50%)**;这不是生物学逼真度、工作量完成率或剩余工期。
|
||||
最新正式候选运行时为 `MaleCNS-LIF-runtime-v2-deterministic-candidate`。
|
||||
`MaleCNS-TemporalEligibility-v2-candidate` 与 `MaleCNS-OlfactoryEncoder-v1-candidate` 保留。
|
||||
@@ -13,7 +15,8 @@
|
||||
|
||||
| 主题 | 文档 |
|
||||
|---|---|
|
||||
| 当前状态、验收比例、下一步 | [项目状态](docs/00-overview/status.md) |
|
||||
| 最新运行状态、证据与下一步 | [当前状态](CURRENT.md)、[CPU/GPU 保存说明](registry/acceleration-20261001/README.md) |
|
||||
| 顶层验收比例与历史基线 | [项目状态](docs/00-overview/status.md) |
|
||||
| 目录和数据流 | [架构与目录](docs/00-overview/architecture.md) |
|
||||
| 科学数据定义和来源 | [数据契约](docs/10-data/data-contract.md)、[来源登记](docs/10-data/provenance.md) |
|
||||
| 模型边界 | [模型与冻结契约](docs/20-model/baseline.md) |
|
||||
@@ -35,17 +38,17 @@
|
||||
|
||||
服务器项目根目录:`/data/digital-drosophila/`。
|
||||
远程:`ssh://git@192.168.10.31:2222/qishizhe/digital-drosophila.git`。
|
||||
初始化分支:`codex/project-bootstrap`。
|
||||
初始化/当前远端默认分支:`codex/project-bootstrap`;注册科学源码分支:`codex/lif-author-semantics-lab`;最新独立加速成果:`codex/v100-conditioning-acceleration`。
|
||||
|
||||
Git 保存源代码、配置、文档、书目、阶段证据副本和逐文件哈希清单。
|
||||
**Git 不保存原始 SWC/Feather、CSR、完整事件/状态、模型 checkpoint、虚拟环境或大型压缩包。**
|
||||
普通 Git 不直接保存大型科学二进制。获准公开再分发的原始/参考数据已在 `codex/lfs-public-resources` 通过 **Git LFS** 归档;本分支另通过 LFS 保存本次 CPU/GPU 回放的科学结果。没有上传虚拟环境、SDK 编译缓存、凭据或其他服务的数据。
|
||||
原项目实占约 29.72 GB(十进制、初始化前统计),不会因为初始化 Git 被删除、搬移或重写。
|
||||
仅 clone 本仓库不能恢复全数据;按[恢复说明](docs/30-reproducibility/restore.md)配置单独的数据副本。
|
||||
只取得 Git pointer 不能恢复全数据;需下载对应分支的 LFS 对象并验证内部成员。本次恢复说明见 [CPU/GPU 发布入口](registry/acceleration-20261001/README.md)。这不是全服务器灾备。
|
||||
|
||||
## 安全的首次检查
|
||||
|
||||
```bash
|
||||
git clone --branch codex/project-bootstrap ssh://git@192.168.10.31:2222/qishizhe/digital-drosophila.git
|
||||
GIT_LFS_SKIP_SMUDGE=1 git clone --branch codex/v100-conditioning-acceleration ssh://git@192.168.10.31:2222/qishizhe/digital-drosophila.git
|
||||
cd digital-drosophila
|
||||
python3 -B tools/repo_guard.py
|
||||
```
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,23 @@
|
||||
# 分支用途与当前入口
|
||||
|
||||
2026-10-01 只读审计。此次只保存/推送已存在的加速实验分支,不删除分支、不强推、不合并、不更改默认分支。
|
||||
|
||||
所有名称均带 `codex/` 前缀。
|
||||
|
||||
| 分支 | 用途 |
|
||||
|---|---|
|
||||
| project-bootstrap | 最初项目归档、数据索引、论文与来源;当前远端默认入口 |
|
||||
| apl-pn-scope-audit | APL→PN 实际接触位置审计 |
|
||||
| terminal-scope-diagnostic | PN calyx 接触范围诊断 |
|
||||
| lif-semantics-audit | 冻结 LIF 语义与反馈回路审计 |
|
||||
| lif-author-semantics-lab | 独立模型及正式 Phase 4AR/CPU 实现,当前科学现场的分支 |
|
||||
| lfs-public-resources | 获准公开再分发的大数据、作者资源及实际远端恢复验证 |
|
||||
| v100-conditioning-acceleration | CPU 常驻、独立校验、V100 更新原型、4090 常驻回放;本次最新保存入口 |
|
||||
|
||||
前五个主要是同一条提交历史上的阶段指针,并不是五份独立完整数据。它们线性继承至 `09187e4`,之后分为 LFS 资源发布和加速实验两条路线。Git/LFS 会按内容地址保存对象;多个分支名不意味着同一文件被完整复制多份。
|
||||
|
||||
加速分支原已在本地存在,本次推送后远端共 7 个分支。CPU/GPU 两套实现放在同一加速分支的不同目录,不再各建分支。LFS 资源分支仍独立,不能把这次发布描述为已经合并全部数据。
|
||||
|
||||
默认仍为最早的 bootstrap,所以网页默认看到的内容较旧。这是入口未整理,不是后续工作丢失。
|
||||
|
||||
后续可在用户确认后统一主入口、给历史阶段打保留标签,再整理旧分支。集成 LFS 时需核对属性、状态文档、许可说明和自动下载开销;不得把工程实验分支直接视为通过科学验收的正式运行时。
|
||||
@@ -0,0 +1,77 @@
|
||||
# CPU 常驻原型性能验证(2026-09-30)
|
||||
|
||||
## 结论与边界
|
||||
|
||||
结果:`PASS-CPU-RESIDENCY-PROTOTYPE-ONLY`。这是独立工程原型,不是新的
|
||||
学习候选、GPU runtime 验收或 Phase 4AR 替换授权。原型没有执行脑模拟,
|
||||
没有修改或安装权重,没有读取 AR 中途学习指标,也没有减少任何文件校验。
|
||||
|
||||
当前正式 AR 继续原样执行;不能将此原型热替换到已登记的执行账本中。
|
||||
常驻任务 ACK 与真实进程退出属于不同证据,不能把前者伪装成每轮 OS exit。
|
||||
|
||||
## 方法
|
||||
|
||||
- 使用已封存 AQ 的 `mechanical--fresh-parent` 和
|
||||
`performance--natural-light-fresh` 两个预先指定工程 checkpoint。
|
||||
- 固定 7 组:M、N、M、N_D0、N_frozen、M_D0、M。
|
||||
- M 的 before 为零 overlay;N 使用实际 AP 历史 learned overlay。
|
||||
- D0/frozen 是在独立 authority 中声明的工程命令变体,保留原 sealed events,
|
||||
不修改原文件,不重新运行 conditioning。
|
||||
- 更新器调用原 `E.postprocess_epoch`,只复用同身份的已验证模块。
|
||||
- 原 AQ fresh-process validator 对每组原型输出独立重算并实际退出 0。
|
||||
- 新 resident validator 使用独立 PID;数学和校验主体与原实现 AST 一致,
|
||||
仅调整模块复用与来源声明。所有动态输入、校验和 U 重算仍逐次执行。
|
||||
- CPU 单线程、低优先级、CUDA 不可见且未初始化。两常驻 worker 串行接收任务,
|
||||
更新器和验证器不混载同一个解释器。
|
||||
|
||||
## 真实计时
|
||||
|
||||
首次请求单列为冷启动;下表为后 6 组配对热态均值。fresh 与 resident 的
|
||||
父级请求计时均包括请求/响应保存、输入摘要与输出核验;fresh 另外包含
|
||||
其每次进程启动/ready/退出。resident 生命周期启动与退出另有实际记录。
|
||||
|
||||
| CPU 环节 | fresh 原实现 | resident 原型 |
|
||||
|---|---:|---:|
|
||||
| Epoch 更新 | 4.672 秒 | 2.763 秒 |
|
||||
| 独立校验 | 3.995 秒 | 2.063 秒 |
|
||||
| 合计 | 8.667 秒 | 4.826 秒 |
|
||||
|
||||
- 两阶段均常驻:该 CPU 段加速 **1.796×**,耗时下降约 **44.3%**。
|
||||
- 只常驻更新器、仍保留 fresh 原验证器:该 CPU 段加速 **1.283×**。
|
||||
- 整个有界原型实测约 100.46 秒;服务器 benchmark 父进程实际退出 0。
|
||||
- 这些数值不包括全脑 GPU 模拟、AP 外层包装和 AR ledger 开销,不能据此
|
||||
声称全实验加速 1.8 倍,或将原 9 天预测直接除以 1.8。
|
||||
- 正式 AR 同时运行,且仅测试两个源轨迹、一个 compartment,结果是小样本
|
||||
工程测量,不是所有条件的性能保证。
|
||||
|
||||
## 一致性与完整性
|
||||
|
||||
- 本地和服务器安全/AST 单元测试:12/12 通过。
|
||||
- 7/7 真实全尺寸 CPU 回放:四个更新文件 SHA 完全相同;delta 的 dtype、
|
||||
shape、raw bytes 完全相同;完整 update receipt、trace 摘要相同。
|
||||
- 原始 M/N 同时与已封存 AQ 更新输出比较,完全相同。
|
||||
- D0/frozen 的 before/after delta 逐位不变,包含非零历史 delta 条件。
|
||||
- 两验证器的科学校验字段完全相同;仅白名单列出的 schema/source/cache
|
||||
provenance 字段不同,明确不冒称新验证器为原 frozen verifier。
|
||||
- 14 次 fresh 进程及 2 个 resident 进程均由父级观察实际退出 0。
|
||||
- 170 个新产物的清单、大小、SHA 已独立复核;消费的冻结输入及原型源代码
|
||||
在前后保持原 SHA。这里不声称重新扫描了全部历史 Phase 1–4AQ。
|
||||
- 23:26 北京时间,AR 的 16 个已登记源码仍匹配原 SHA;原 supervisor /
|
||||
controller 441824/441825 活跃,累计 310 个已验证 epoch、50 个 probe,
|
||||
没有 stopped 记录。本段是时间限定快照,不是实时状态或学习结论。
|
||||
|
||||
## 保存位置
|
||||
|
||||
- 代码:`tools/conditioning-perf-lab-v1/`
|
||||
- 执行源码提交:`7f341d7ffbacc4b46bca74e5f570f7f2e8108ac0`
|
||||
- 原始执行目录:`/tmp/malecns-cpu-residency-woqIQa/`(保留,未删除)。
|
||||
- 持久化证据副本:`registry/conditioning-perf-prototype-20260930/`。
|
||||
- 主要结果:该目录的 `report.json`、`benchmark-plan.json`、`manifest.json`。
|
||||
- 副本不重写原回执中的实际执行路径。Git 同步代码及小型 JSON 证据;NPZ
|
||||
按现有仓库策略保留在服务器,不把 Git 同步描述成所有数据异机备份。
|
||||
|
||||
## 下一步
|
||||
|
||||
优先验证静态图/APL 的常驻加载和独立 GPU worker 状态重置,但这需要不与
|
||||
当前正式任务争抢 4090 的测试窗口,以及逐事件、状态和更新的一致性回归。
|
||||
没有进行这一测试前,不升级为正式 runtime,也不终止或改写当前 AR。
|
||||
@@ -0,0 +1,47 @@
|
||||
# Phase 4AQ:更新边界与连续状态验证
|
||||
|
||||
数值审计结果:`PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING`。
|
||||
|
||||
这意味着权重更新、延迟队列、连续神经状态和探测分叉的工程接口通过了本次固定实验;不代表已经实现关联学习、记忆保持或可用游戏控制。本阶段没有产生 learned candidate,没有调学习率、阈值、APL 参数或扩大 plastic mask。
|
||||
|
||||
## 已验证的结果
|
||||
|
||||
- 新代码的服务器 CPU 测试:189/189 通过;证据发布工具另有 11/11 合成测试通过。
|
||||
- 实际执行 23 次全脑运行、7 个 CPU 更新/复核进程、1 个 GPU 输入采样进程,共 31 个独立子进程。
|
||||
- 全脑规模保持 166,700 neurons、25,582,938 edges;新运行合计 125,200 ticks,dt=0.1 ms。
|
||||
- 14 项数值和来源检查均通过。独立连续 oracle 与 reference/light 恢复运行的事件、终态与队列一致;D(t)=0/frozen 对照与旧 continuation 一致。
|
||||
- 固定机械诊断中,1 条真实候选边发生更新,off-compartment 更新为 0。KC neuron_idx=3986 在 tick 1199 发放,经真实 edge_id=2802165 到 neuron_idx=9,在 tick 1217 被接受:精确延迟 18 steps。到达使用更新后权重,而不是重新缩放已经存在的 g。
|
||||
- 实际执行 1 s + 9 s 连续静置,以及 t=0/1/10 s 的 A/B 探测。探测不添加 US,不进行更新,不反馈到静置轨迹。这不是完整 retention 学习实验。
|
||||
- 所有实际运行有限值检查通过。连续静置记录的 peak allocated VRAM 为 518,003,712 bytes(约 494 MiB);这不是整个 GPU 的总占用量。
|
||||
- 有限执行器自身记录用时 842.1341 s;不包含此前准备、此后的独立审计和最终封存时间。
|
||||
|
||||
## 成本与下一步
|
||||
|
||||
固定 fresh/light 训练周期(brain + 原 E 更新 + 独立 CPU 复核)记录为 24.7712 s,新增产物 3,350,283 bytes;无 US 的 fresh/light 探测为 10.3950 s,新增产物 2,797,824 bytes。
|
||||
|
||||
审计补入周期收据和保守的编译缓存费用后,两个周期分别按 5,078,099 / 4,522,528 bytes 计费。以相邻周期开始时间作为尾部完成上界后,训练为 32.9680 s(其中保守重复计入中间约 8.20 s 的输入采样),探测为 10.4098 s。以上均不是整个 normal suite 的工期承诺。
|
||||
|
||||
正式预算报告保持 `INSUFFICIENT-MEASUREMENTS / FUTURE-POLICY-NOT-REGISTERED`:不能把 4 GiB/7200 s 的本次有限诊断限额当作长期训练授权,也不能忽略逐步增长的目录扫描、最终校验和未知活动量。
|
||||
|
||||
下一步是登记并实现正式 normal conditioning 执行器:保留固定 30,000 training/control epochs、3,920 probes、全部种子和对照;使用追加式产物清单避免每轮重扫全部历史目录,并保留最终全量 SHA-256 核验。不得通过减少种子、缩短试验、删除证据或调参来取得 PASS。学习判据仍以刺激特异性的 MBON 与非 MBON 下游响应为准,不能仅凭 delta-weight 改变。
|
||||
|
||||
## 保存位置与完整性边界
|
||||
|
||||
- 新模型代码:`models/male-cns-lif/conditioning-execution-v1/`
|
||||
- 新实验:`experiments/phase4aq-conditioning-execution/`
|
||||
- 小证据归档:`registry/phase4aq-conditioning-execution/`
|
||||
- 正式封存状态与哈希:实验下 `audit/final-status.json`、`manifest.json`、`checksums.sha256`;发布凭证在 registry 下 `publication-receipt.json`。
|
||||
- 原始数据没有写入;登记范围内的旧阶段冻结产物与源文件的独立事后完整性检查通过。旧五组 numerical reference 的 AM 封存证据被保留并核验,**不是本阶段重新执行了那五组试验**。
|
||||
- Git 同步包含代码、文档和小证据。完整数值数组仍在服务器,**Git 不构成全量数据备份**。
|
||||
|
||||
代码提交:`d54f0b3ef13d5b70ffca80ea83a679eb9ab37e20`。
|
||||
|
||||
注册 SHA-256:`dad0ba33ded8c6725662c419525ef4185a6ff169042a402c18d0bd760dad7358`。
|
||||
|
||||
数值报告 SHA-256:`57ed41acf0e3617c2c2c70a43684a0d9b2ea775e9ab3d83ab84a960200e50063`。
|
||||
|
||||
最终报告 SHA-256:`dcbb58f296bd0d51e3c8757f0c45dd5585b3a76f8c2a0b5881f4c14076721882`。
|
||||
|
||||
实验 manifest SHA-256:`2dc0feca75f718f2ee0d7c9240da503221823573fd25f1344d2fd97d97eb2db7`。已封存 790 个 payload 文件、463,441,109 bytes;封存前重新计算数值/预算审计,并在独立进程再次核验旧阶段完整性。
|
||||
|
||||
本次独立工程验证没有证明模型已经能够学习;后续条件化结果必须另行真实执行、审计并报告。
|
||||
@@ -0,0 +1,87 @@
|
||||
# Phase 4AR:独立分支普通嗅觉条件化
|
||||
|
||||
## 当前状态
|
||||
|
||||
2026-09-30:新分支代码已提交并同步远程仓库;服务器整套 CPU 测试
|
||||
73/73 通过,0 失败、0 跳过。旧封存完整性检查通过,实验预注册已锁定。
|
||||
4,080 份固定 CS 输入已生成并由真实进程退出记录及账本确认。
|
||||
独立后台执行器已启动;尚未据此宣称训练完成或学习成功。
|
||||
|
||||
启动后观察到 4 个训练 epoch 已完成原更新及独立 CPU 校验、6 次独立
|
||||
probe 已提交;后续仍在运行。这是有时间边界的启动快照,不是当前实时
|
||||
累计数,也不是科学 gate 结果。首轮实际 CPU 校验确认使用封存 spike events
|
||||
重算原 U 更新,父进程记录退出码为 0。
|
||||
|
||||
- 模型:`/data/digital-drosophila/models/male-cns-lif/normal-conditioning-v1/`
|
||||
- 实验:`/data/digital-drosophila/experiments/phase4ar-normal-conditioning/`
|
||||
- 管理日志:`/data/digital-drosophila/logs/phase4ar-normal-conditioning/`
|
||||
- 源码提交:`80aeb2093db655329774eff7b32fb6e417b8b40b`
|
||||
- 预注册 SHA-256:`b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740`
|
||||
- 仓库分支:`codex/lif-author-semantics-lab`
|
||||
|
||||
## 固定实验与边界
|
||||
|
||||
这是用户授权的独立动力学假设分支,不是替换 reference/runtime,
|
||||
也不是重新解释旧阶段失败。Phase 1–4AQ 封存产物、base graph、原始权重、
|
||||
transmitter sign、14,232-edge mask、eligibility-v2 与 APL 参数保持只读。
|
||||
|
||||
按既有固定计划执行 physiological / matched-energy、PAM15 / PPL103、
|
||||
A+/B− 与 B+/A−、5 个训练重复,共 40 个 block。A 为 4-ethylphenol,
|
||||
B 为 3-hexanone。PAM15/PPL103 功能预测是明确的 compartment-specific
|
||||
模型假设,不能推广成“所有 PAM 为正、所有 PPL 为负”。
|
||||
|
||||
7 组实际执行的实验臂为 paired、D=0、frozen、random reward、unpaired、
|
||||
CS-only、DAN-only,共 30,000 训练/对照 epoch、3,920 次独立 A/B probe。
|
||||
每 epoch 120 ms,CS 为前 100 ms,人工 US 为 90 ms;每轮重置神经状态,
|
||||
仅携带经独立 CPU 验证的 plastic delta。Probe 无 US、无学习更新、无反馈。
|
||||
|
||||
终点固定,不允许根据中间结果改参数、改种子或挑最好条件。普通 acquisition
|
||||
通过也不等于已经获得可用学习模型;不会自动启动 reversal、retention、
|
||||
delayed reward 或任何游戏、动作解码器、RL、视觉、Web/3D。
|
||||
|
||||
## 可审计执行
|
||||
|
||||
当前登记包含 16 份源码、63 项输入身份、33 份准备产物。登记之后不得
|
||||
修改这些文件来修复运行中的实验;失败必须保留证据,不能原地改后续试跑。
|
||||
|
||||
每个子进程先写独占开始记录,再保存真实退出状态、输入/输出 SHA-256、
|
||||
不可变顺序账本。部分失败保留,不自动重试。训练依次运行原 brain、
|
||||
原 E/U 更新和独立 CPU 重算;不能用父进程中自报成功代替真实退出。
|
||||
|
||||
仅使用已登记的 RTX 4090,逐次检查 ComfyUI 队列,不停止其他服务。
|
||||
新输出上限 256 GiB、磁盘保留至少 100 GiB、单子进程上限 1,800 秒,
|
||||
登记期限 21 天。约 9 天仅为少量 AQ 计时的线性规划估算,并非全条件实测。
|
||||
|
||||
完整性核验与 CPU 测试是工程证据,不是新数值回归,更不是学习证据。
|
||||
最终必须另行进行全产物审计、固定学习 gate 分析及旧阶段完整性复核。
|
||||
仓库同步源码/文档/小型证据,不等于大体量实验数据已经异机备份。
|
||||
|
||||
## 后续只读检查
|
||||
|
||||
已安排本线程每小时检查,仅在实质进展、异常、完成或需人工操作时提醒。
|
||||
不自动重试、修补已注册源码、进入后续 assay 或声明学习成功。
|
||||
|
||||
独立只读工具位于 `tools/normal-conditioning-audit/progress_normal.py`,
|
||||
8 项临时数据测试在服务器通过。它读取实际提交账本与最新退出记录,
|
||||
不读取大体量脑输出;其进度结果不是完整性报告或科学结论。
|
||||
正在执行的 child 在没有真实退出记录时明确保持 UNKNOWN,不能由 PID
|
||||
或一个提前写出的 results 文件推定成功。完整 run 完成后仍需最终独立审计。
|
||||
|
||||
## 终审工具准备进展(不改变正在运行的实验)
|
||||
|
||||
独立终审工具已完成服务器联合测试:42/42 通过,0 失败、0 跳过。
|
||||
其中学习结果判定测试通过冻结的原指标代码生成六神经元合成报告,
|
||||
包含正常通过、终点未达 3/5、单一 H 对照来源失败、严格等号不通过等情形。
|
||||
这些不是本次真实学习结果,也没有读取中途学习指标。
|
||||
|
||||
`tools/normal-conditioning-audit/normal_finalize.py check` 已在服务器实测:
|
||||
发现注册进程仍在运行后按设计拒绝终审,未创建终审输出目录。
|
||||
真正的完整审计和固定 gate 分析只能在全部任务结束、实际退出为 0 后进行。
|
||||
终审产物将位于独立的 `phase4ar-normal-conditioning-final-audit/`,
|
||||
不会向已完成的原实验目录追加或替换文件。
|
||||
|
||||
终审保留原账本的全部字段,不改 PASS/FAIL 标志;完成记录在账本检查后
|
||||
才生成这一文件边界由单独的真实文件清单核对。任何额外文件、变更、
|
||||
未完成进程或来源矛盾均不得被当成完整的学习阳性/阴性结论。
|
||||
即便普通 acquisition 通过,delayed/reversal/retention 仍未运行,不能
|
||||
生成候选模型、宣称学习已经可用或自动启动后续实验。
|
||||
@@ -0,0 +1,37 @@
|
||||
# 仓库同步与运行观察 — 2026-10-01
|
||||
|
||||
采样时间:2026-10-01 00:09:04(Asia/Shanghai,UTC+08:00)。本报告是运行状态快照,不是新的科学结论,也不是完整数据备份。
|
||||
|
||||
## 本轮新增内容
|
||||
|
||||
- 发布独立的 [Phase 4AR 运行观察](../../registry/phase4ar-runtime-observation-20261001T000904/snapshot.json)。
|
||||
- 更新仓库 README 和 CURRENT 的入口状态,保留旧阶段报告与历史事实。
|
||||
- 未修改科学源码、配置、输入、权重或 Phase 1–4AQ 封存产物;未重启、重试或停止 Phase 4AR。
|
||||
- 未将 CPU 常驻性能原型接入当前登记实验。
|
||||
|
||||
## 已提交执行账本
|
||||
|
||||
| 项目 | 完成量 | 登记总量 |
|
||||
|---|---:|---:|
|
||||
| 训练轮次(神经运行、更新及独立 CPU 校验均已提交) | 411 | 30,000 |
|
||||
| 独立 probe | 62 | 3,920 |
|
||||
|
||||
采样时操作系统确认监督器、协调器和一个子进程存在。子进程仍未提交,不能加入完成数;PID 或结果文件存在不构成完成证据。无 stopped 记录、无最终退出记录、无 execution-complete 记录。因此仍是运行中,学习成功尚未判断。
|
||||
|
||||
登记 SHA-256:`b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740`。
|
||||
登记科学源码提交:`80aeb2093db655329774eff7b32fb6e417b8b40b`。
|
||||
本次直接核对登记的 16 个源码文件 SHA-256,全部匹配;63 个输入 pin 和 33 个准备文件 pin 仅记录登记数量,没有再次全量读取、哈希或重跑。实验所在文件系统可用约 602.45 GiB,这不是整台服务器总容量。
|
||||
|
||||
## 观察边界
|
||||
|
||||
这是一次非原子的在线元数据观察;读取期间未观察到账本条目增加,但不因此声称取得文件系统原子快照。只读取登记、账本、绑定的少量回执和任务身份,不读取 spike/state/delta 数组,不评估中途学习指标,不挑选条件,不调整策略。
|
||||
|
||||
正式科学 gate 与最终历史完整性审计须在真实完整退出后独立执行。执行完成不等于学习成功;不自动开始反转、延迟奖励、保持或游戏等后续任务。
|
||||
|
||||
## 同步范围和分支
|
||||
|
||||
当前研发分支:`codex/lif-author-semantics-lab`。远端:`ssh://git@192.168.10.31:2222/qishizhe/digital-drosophila.git`。
|
||||
|
||||
采样前本地与该远端分支均为 `b0728419fb4caaef37e41e3989b138c3fc6f754e`,已有代码、报告与小证据并无漏推。远端默认分支仍为 `codex/project-bootstrap`;本轮不合并、不改默认分支。
|
||||
|
||||
本轮只发布本报告、入口文档及元数据快照。raw、SWC、CSR、权重和完整实验轨迹仍未通过 Git 上传,未配置或迁移 Git LFS。完整异机数据备份未因此完成。后续如启用 LFS,需要单独检查服务配置、可用空间与归档方案,不改动冻结数据原件。
|
||||
@@ -0,0 +1,31 @@
|
||||
# Conditioning acceleration v1 — independent engineering benchmark
|
||||
|
||||
Authority: user requested V100 acceleration and algorithm optimization on 2026-10-01. This work DOES NOT resume or change Phase 4AR, and does not authorize a new 30,000-epoch scientific experiment.
|
||||
|
||||
## Frozen scientific semantics
|
||||
|
||||
Preserve original Phase 4J/AM eligibility, compartment mapping, the complete candidate mask, anatomical base weights, float32 update semantics, all time steps and original event ordering. No threshold/gain/eta/tau/sign change, reduced trial count claim, surrogate gradients, skip-time power approximation, new connections or model learning claim. GPU outputs are diagnostic replay products only and are never installed into a brain.
|
||||
|
||||
The oracle is the exact SHA-pinned original Torch CPU update running in the original science environment. Candidate CuPy CUDA code runs in a separate environment with NumPy 2.2.6 and CuPy 13.6.0, using the installed CUDA 12.6 toolkit. Do not modify the original environment, ComfyUI or frozen source files.
|
||||
|
||||
## Fixed validation and measurement plan
|
||||
|
||||
Select the first and last fully ledger-committed training task for each observed arm by deterministic task-ID order, without inspecting learning scores. This is coverage of available saved inputs only, not all registered conditions. Export fixed original inputs and recomputed CPU reference outputs into a new directory; compare them with the saved scientific outputs before use.
|
||||
|
||||
Compare all sampled traces, final traces and local delta arrays byte-for-byte against the original CPU oracle on both physical V100s and the 4090. Add synthetic edge cases: no spikes, non-KC spikes, no US, US at zero/final tick, duplicate/invalid events rejection, multiple US snapshots for trace-only API, saturation, D=0, frozen identity, all compartments, and seeded sparse/random traces. Do not select only passing cases. Any mismatch blocks promotion.
|
||||
|
||||
Use 3 warmups and 20 timed repeats for every real fixture on each GPU, with the same fixture order. Record first-use compilation/context cost separately, CPU preparation, transfer-inclusive host wall time, kernel event time, GPU identity, memory and exact software/source hashes. Repeat within a resident process to expose avoidable per-process overhead. Never present kernel-only speedup as full training speedup.
|
||||
|
||||
Budget: at most 15 minutes of candidate benchmark execution after dependencies/compilation, one process per GPU initially; do not occupy a GPU with a nonempty ComfyUI queue or evict services. No automatic scientific retry. Implementation failures may be diagnosed and corrected in new benchmark attempts, retaining earlier reports. No modification of any frozen experiment. Independent CPU verification remains required before any future production integration.
|
||||
|
||||
## Gate and limits
|
||||
|
||||
Passing this benchmark means only ELIGIBILITY-UPDATE-REPLAY-EQUIVALENCE for the tested inputs. It does not establish full-brain event equivalence, end-to-end acceleration, learning success, resumability, or completion of Phase 4AR. Integration, persistent brain workers and independent-seed multi-GPU scheduling require separately validated execution/audit changes. Stop before installing any update or starting learning.
|
||||
|
||||
Keep source, configuration, environment installation report, fixed input manifest, raw timing samples, comparisons, failures and SHA-256 manifest. Check Phase 4AR registration/source and the prior saved-file inventory before/after; report the exact scope (not a new Phase 1–4AQ numerical regression).
|
||||
|
||||
## Recorded implementation correction (before successful GPU execution)
|
||||
|
||||
The first candidate installation attempted pip's `--report` with the new venv's inherited pip 22.0.2, which does not support it. Only the candidate venv was upgraded to pip 25.2; both logs remain preserved.
|
||||
|
||||
GPU attempt `v100a-01` failed before running kernels because CuPy 13.6's RawKernel cache compiler appends `-ftz=true`, conflicting with the required `--ftz=false`. Do not remove the precision requirement. The corrected candidate compiles the same CUDA recurrence with installed nvcc 12.6, explicit separate rounding and `--ftz=false`, then loads the precompiled module through CuPy. Compiler commands, sources, output and binary hashes are preserved in candidate-only caches. The original scientific recurrence and all predeclared fixtures remain unchanged; failed attempt records are not replaced.
|
||||
@@ -0,0 +1,49 @@
|
||||
"""Read-only rehash of the saved Phase4AR shutdown inventory and registered sources."""
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
INVENTORY = Path('/home/qishizhe/phase4ar-user-shutdown-20260930T203113Z/saved-files.sha256.jsonl')
|
||||
INVENTORY_SHA = 'd7b675b0d0d4647d8fe2fcf9616b9a599e5bc3c15565e604e0d66a046afb835a'
|
||||
REG = Path('/data/digital-drosophila/experiments/phase4ar-normal-conditioning/protocol/preregistered.json')
|
||||
REG_SHA = 'b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740'
|
||||
|
||||
def sha(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as f:
|
||||
for chunk in iter(lambda: f.read(8 << 20), b''): h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('--output', type=Path, required=True)
|
||||
a = p.parse_args()
|
||||
assert not a.output.exists() and a.output.parent.is_dir()
|
||||
start = time.perf_counter()
|
||||
assert sha(INVENTORY) == INVENTORY_SHA and sha(REG) == REG_SHA
|
||||
records = [json.loads(line) for line in INVENTORY.read_text().splitlines()]
|
||||
differences = []
|
||||
for row in records:
|
||||
path = Path(row['path'])
|
||||
if not path.is_file() or path.stat().st_size != row['bytes'] or sha(path) != row['sha256']:
|
||||
differences.append(str(path))
|
||||
reg = json.loads(REG.read_text())
|
||||
source_mismatches = [path for path, expected in reg['source_sha256'].items() if sha(path) != expected]
|
||||
head = subprocess.check_output(['git', '-C', '/data/digital-drosophila', 'rev-parse', 'HEAD'], text=True).strip()
|
||||
status = subprocess.check_output(['git', '-C', '/data/digital-drosophila', 'status', '--porcelain'], text=True)
|
||||
summary = dict(status='PASS' if not differences and not source_mismatches and status == '' else 'FAIL',
|
||||
created_utc=datetime.now(timezone.utc).isoformat(), files_checked=len(records),
|
||||
bytes_checked=sum(r['bytes'] for r in records), inventory_sha256=INVENTORY_SHA,
|
||||
registration_sha256=REG_SHA, registered_science_commit=reg['source_code_commit'],
|
||||
sources_checked=len(reg['source_sha256']), file_mismatches=differences,
|
||||
source_mismatches=source_mismatches, original_git_head=head, original_git_status=status,
|
||||
wall_seconds=time.perf_counter()-start,
|
||||
scope='Saved Phase4AR experiment/control files and registered source files; NOT a new Phase1-4AQ numerical regression',
|
||||
training_epochs_cpu_verified_unchanged=1033, probes_completed_unchanged=138,
|
||||
original_experiment_resumed=False)
|
||||
with a.output.open('x') as f: json.dump(summary, f, indent=2)
|
||||
print(json.dumps(summary), flush=True)
|
||||
raise SystemExit(0 if summary['status'] == 'PASS' else 1)
|
||||
@@ -0,0 +1,257 @@
|
||||
"""Bounded replay benchmark. No brain simulation, training, or weight installation."""
|
||||
from __future__ import annotations
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
from pathlib import Path
|
||||
import statistics
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import urllib.request
|
||||
|
||||
import numpy as np
|
||||
from gpu_backend import CudaEligibility, prepare_events
|
||||
|
||||
REG_SHA = 'b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740'
|
||||
IDENTITY_KEYS = ('kc', 'candidate_edge_id', 'candidate_sources', 'candidate_targets',
|
||||
'candidate_compartments', 'base_candidate')
|
||||
OUTPUTS = ('sampled_trace', 'final_trace', 'snapshots', 'delta_after')
|
||||
|
||||
def sha(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for chunk in iter(lambda: stream.read(8 << 20), b''):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
def save(path, value):
|
||||
with Path(path).open('x', encoding='utf-8') as stream:
|
||||
json.dump(value, stream, indent=2, sort_keys=True, allow_nan=False)
|
||||
stream.write('\n')
|
||||
|
||||
def read(path):
|
||||
return json.loads(Path(path).read_text())
|
||||
|
||||
def evidence(a):
|
||||
return dict(dtype=a.dtype.str, shape=list(a.shape), sha256=hashlib.sha256(a.tobytes()).hexdigest())
|
||||
|
||||
def contained(root, relative):
|
||||
p = root / relative
|
||||
assert not p.is_symlink() and p.resolve().is_relative_to(root.resolve()), 'Escaping fixture path'
|
||||
return p
|
||||
|
||||
def idle_queues():
|
||||
result = {}
|
||||
for port in (8188, 8189, 8190):
|
||||
with urllib.request.urlopen(f'http://192.168.10.51:{port}/queue', timeout=5) as response:
|
||||
q = json.load(response)
|
||||
assert set(('queue_running', 'queue_pending')).issubset(q)
|
||||
result[str(port)] = {key: len(q[key]) for key in ('queue_running', 'queue_pending')}
|
||||
assert not any(result[str(port)].values()), 'ComfyUI has work; benchmark will not compete'
|
||||
return result
|
||||
|
||||
def gpu_snapshot(uuid):
|
||||
text = subprocess.check_output(['nvidia-smi', '--id=' + uuid,
|
||||
'--query-gpu=uuid,name,pci.bus_id,memory.total,memory.used,utilization.gpu,driver_version',
|
||||
'--format=csv,noheader,nounits'], text=True).strip()
|
||||
fields = [s.strip() for s in text.split(',')]
|
||||
assert fields[0] == uuid
|
||||
return dict(zip(('uuid', 'name', 'pci_bus_id', 'memory_total_mib', 'memory_used_mib',
|
||||
'utilization_percent', 'driver_version'), fields))
|
||||
|
||||
def stats(values):
|
||||
return dict(n=len(values), min=min(values), median=statistics.median(values),
|
||||
mean=statistics.mean(values), max=max(values))
|
||||
|
||||
def compare(result, arrays):
|
||||
report = {}
|
||||
for key in OUTPUTS:
|
||||
actual, expected = getattr(result, key), arrays['reference_' + key]
|
||||
exact = actual.dtype == expected.dtype and actual.shape == expected.shape and actual.tobytes() == expected.tobytes()
|
||||
diff = np.abs(actual.astype(np.float64) - expected.astype(np.float64))
|
||||
report[key] = dict(bitwise_exact=exact, actual=evidence(actual), expected=evidence(expected),
|
||||
max_abs_error=float(np.max(diff)) if diff.size else 0.,
|
||||
mean_abs_error=float(np.mean(diff)) if diff.size else 0.)
|
||||
return report
|
||||
|
||||
def load_fixtures(manifests):
|
||||
fixtures = []
|
||||
common_identity = None
|
||||
for manifest_path in manifests:
|
||||
m = read(manifest_path)
|
||||
assert m.get('complete') is True and m['registration_sha256'] == REG_SHA
|
||||
root = manifest_path.parent
|
||||
for f in m['fixtures']:
|
||||
npz = contained(root, f['npz'])
|
||||
command_path = contained(root, f['command'])
|
||||
assert sha(npz) == f['npz_sha256'] and sha(command_path) == f['command_sha256']
|
||||
with np.load(npz, allow_pickle=False) as z:
|
||||
a = {k: z[k].copy() for k in z.files}
|
||||
identity = {k: evidence(a[k]) for k in IDENTITY_KEYS}
|
||||
if common_identity is None:
|
||||
common_identity = identity
|
||||
assert common_identity == identity, 'Full KC/mask/base identity differs across fixtures'
|
||||
assert len(a['kc']) == 4064 and len(a['candidate_edge_id']) == 14232
|
||||
sources_path = npz.parent / 'reference-sources.json'
|
||||
assert sha(sources_path) == m['files'][sources_path.relative_to(root).as_posix()]['sha256']
|
||||
source_pins = read(sources_path)
|
||||
expected_sources = dict(
|
||||
conditioning_update_source='96efff678cff910654eb08e86f1a17789e4e5589e340345f419c7027a7d547e2',
|
||||
eligibility_bridge_source='174fb8d14619189e74b095e77a6db18b14c93046dc431c0b55710a5aa2dd2e61',
|
||||
phase4j_source='abb4574da85f00bd9ef61024c65993ef81d42651ff8d8d63c15dd69c6222471e')
|
||||
assert set(source_pins) == set(expected_sources)
|
||||
for role, info in source_pins.items():
|
||||
assert info['sha256'] == expected_sources[role] and sha(info['path']) == info['sha256'], 'Reference source changed'
|
||||
# Extract constants from the authenticated original bridge, without import/exec.
|
||||
import ast
|
||||
bridge = source_pins['eligibility_bridge_source']
|
||||
assert bridge['sha256'] == '174fb8d14619189e74b095e77a6db18b14c93046dc431c0b55710a5aa2dd2e61'
|
||||
constants = {}
|
||||
for node in ast.parse(Path(bridge['path']).read_text()).body:
|
||||
if isinstance(node, ast.Assign):
|
||||
for target in node.targets:
|
||||
if isinstance(target, ast.Name) and target.id in ('DT_MS', 'TAU_MS', 'ETA_MV', 'FLOOR_FRACTION', 'POLARITY'):
|
||||
constants[target.id] = ast.literal_eval(node.value)
|
||||
assert constants['POLARITY'] == -1
|
||||
rule = dict(eta_mv=constants['ETA_MV'], floor_fraction=constants['FLOOR_FRACTION'],
|
||||
decay=math.exp(-constants['DT_MS'] / constants['TAU_MS']))
|
||||
fixtures.append(dict(group=root.name, record=f, arrays=a, command=read(command_path),
|
||||
rule=rule, input_path=str(npz), manifest_sha256=sha(manifest_path)))
|
||||
assert fixtures
|
||||
return fixtures, common_identity
|
||||
|
||||
def check_rejections(manifests, backend, rule):
|
||||
reports = []
|
||||
for path in manifests:
|
||||
for case in read(path).get('invalid_cases', []):
|
||||
root = path.parent
|
||||
npz, command = contained(root, case['npz']), contained(root, case['command'])
|
||||
assert sha(npz) == case['npz_sha256'] and sha(command) == case['command_sha256']
|
||||
with np.load(npz, allow_pickle=False) as z:
|
||||
a = {k: z[k].copy() for k in z.files}
|
||||
c = read(command)
|
||||
commands = [] if c['us_tick'] is None else [c['us_tick']]
|
||||
stage = 'prepare'
|
||||
try:
|
||||
prepared = prepare_events(a['step'], a['neuron_idx'], a['kc'], c['steps'], commands,
|
||||
n_neurons=c['n_neurons'])
|
||||
stage = 'run'
|
||||
backend.run(prepared, a['candidate_sources'], a['candidate_compartments'],
|
||||
c['compartment'], a['delta_before'], a['base_candidate'],
|
||||
d=c['d_command'], frozen=c['frozen'], **rule)
|
||||
except ValueError as error:
|
||||
assert stage == case['stage'], 'Rejected at a different validation boundary'
|
||||
reports.append(dict(case_name=case['case_name'], rejected=True,
|
||||
stage=stage, expected_exception=case['expected_exception'], message=str(error)))
|
||||
else:
|
||||
raise AssertionError('Candidate accepted invalid case: ' + case['case_name'])
|
||||
return reports
|
||||
|
||||
def main(args):
|
||||
assert os.environ.get('CUDA_VISIBLE_DEVICES') == args.uuid, 'Use one explicit physical UUID per process'
|
||||
assert args.output.is_absolute() and not args.output.exists()
|
||||
args.output.mkdir()
|
||||
started = time.perf_counter()
|
||||
try:
|
||||
queues_before = idle_queues()
|
||||
gpu_before = gpu_snapshot(args.uuid)
|
||||
initial_manifest_pins = {str(p): sha(p) for p in args.manifest}
|
||||
fixtures, common_identity = load_fixtures(args.manifest)
|
||||
backend = CudaEligibility(device_index=0)
|
||||
cp = backend.cp
|
||||
props = cp.cuda.runtime.getDeviceProperties(0)
|
||||
bus = cp.cuda.runtime.deviceGetPCIBusId(0)
|
||||
if isinstance(bus, bytes): bus = bus.decode()
|
||||
assert bus.lower()[-10:] == gpu_before['pci_bus_id'].lower()[-10:], 'Physical GPU binding differs'
|
||||
device = dict(**gpu_before, runtime_pci_bus_id=bus, compute_capability=backend.device.compute_capability,
|
||||
initialization_seconds=backend.initialization_seconds, cupy_version=cp.__version__,
|
||||
numpy_version=np.__version__, python_version=sys.version,
|
||||
runtime_version=cp.cuda.runtime.runtimeGetVersion(), driver_version_runtime=cp.cuda.runtime.driverGetVersion(),
|
||||
runtime_name=props['name'].decode() if isinstance(props['name'], bytes) else props['name'])
|
||||
source = Path(__file__).resolve().parent
|
||||
commit = subprocess.check_output(['git', '-C', str(source), 'rev-parse', 'HEAD'], text=True).strip()
|
||||
assert subprocess.check_output(['git', '-C', str(source), 'status', '--porcelain'], text=True) == '', 'Candidate source worktree dirty'
|
||||
save(args.output / 'authority.json', dict(device=device, queues_before=queues_before,
|
||||
candidate_commit=commit, common_full_mapping_identity=common_identity,
|
||||
fixture_manifests=initial_manifest_pins, repeats=20, warmups=3,
|
||||
all_source_files={p.name: sha(p) for p in sorted(source.iterdir()) if p.is_file()},
|
||||
scope='eligibility/delta replay only; no brain, training, or installation',
|
||||
original_experiment_resumed=False, created_utc=datetime.now(timezone.utc).isoformat()))
|
||||
reports = []
|
||||
peak_reserved = 0
|
||||
for i, fixture in enumerate(fixtures):
|
||||
assert time.perf_counter() - started < 900, 'Benchmark wall budget exhausted'
|
||||
idle_queues()
|
||||
a, c, rule = fixture['arrays'], fixture['command'], fixture['rule']
|
||||
arrays_before = {k: evidence(v) for k, v in a.items()}
|
||||
f_id = fixture['group'] + '--' + fixture['record']['fixture_id']
|
||||
def run_once(resident=False):
|
||||
begin = time.perf_counter()
|
||||
prepared = prepare_events(a['step'], a['neuron_idx'], a['kc'], c['steps'],
|
||||
a['reference_command_steps'], n_neurons=c['n_neurons'])
|
||||
result = backend.run(prepared, a['candidate_sources'], a['candidate_compartments'],
|
||||
c['compartment'], a['delta_before'], a['base_candidate'],
|
||||
d=c['d_command'], frozen=c['frozen'], **rule,
|
||||
kernel_warmup=3 if resident else 0, kernel_repeats=20 if resident else 1)
|
||||
comparison = compare(result, a)
|
||||
elapsed = time.perf_counter() - begin
|
||||
if not all(r['bitwise_exact'] for r in comparison.values()):
|
||||
save(args.output / (f_id + '-mismatch.json'), comparison)
|
||||
raise AssertionError('GPU bitwise mismatch: ' + f_id)
|
||||
return result, comparison, elapsed
|
||||
cold, comp, cold_wall = run_once()
|
||||
for _ in range(3):
|
||||
run_once()
|
||||
samples = []
|
||||
for _ in range(20):
|
||||
result, comp, elapsed = run_once()
|
||||
samples.append(dict(**result.timing, replay_wall_including_preparation_and_comparison_seconds=elapsed))
|
||||
resident, _, resident_wall = run_once(resident=True)
|
||||
peak_reserved = max(peak_reserved, cp.get_default_memory_pool().total_bytes())
|
||||
assert arrays_before == {k: evidence(v) for k, v in a.items()}, 'Input arrays mutated'
|
||||
report = dict(fixture_id=f_id, input_path=fixture['input_path'], fixture_manifest_sha256=fixture['manifest_sha256'],
|
||||
command=c, rule=rule, first_call_timing=cold.timing, first_call_wall_seconds=cold_wall,
|
||||
raw_warm_samples=samples, resident_timing=resident.timing,
|
||||
summaries={key: stats([s[key] for s in samples]) for key in
|
||||
('preparation_seconds', 'kernel_seconds', 'end_to_end_seconds',
|
||||
'replay_wall_including_preparation_and_comparison_seconds')},
|
||||
comparison=comp, input_unchanged=True, all_repeats_bitwise_exact=True,
|
||||
reference_timing=fixture['record'].get('reference_timing'), audit=result.audit)
|
||||
save(args.output / (f_id + '.json'), report)
|
||||
reports.append(report)
|
||||
print(json.dumps(dict(fixture=f_id, exact=True,
|
||||
median_ms=1000 * report['summaries']['replay_wall_including_preparation_and_comparison_seconds']['median'])), flush=True)
|
||||
# Recheck original exported files at the end, not just at read time.
|
||||
assert initial_manifest_pins == {str(p): sha(p) for p in args.manifest}, 'Fixture manifest changed'
|
||||
load_fixtures(args.manifest)
|
||||
rejections = check_rejections(args.manifest, backend, fixtures[0]['rule'])
|
||||
save(args.output / 'invalid-input-rejections.json', rejections)
|
||||
assert commit == subprocess.check_output(['git', '-C', str(source), 'rev-parse', 'HEAD'], text=True).strip()
|
||||
assert subprocess.check_output(['git', '-C', str(source), 'status', '--porcelain'], text=True) == ''
|
||||
result = dict(status='PASS-ELIGIBILITY-UPDATE-REPLAY-EQUIVALENCE', fixtures=len(reports),
|
||||
device=device, candidate_commit=commit, all_fixture_repeats_bitwise_exact=True,
|
||||
observed_cuda_pool_reserved_peak_bytes=peak_reserved, gpu_after=gpu_snapshot(args.uuid),
|
||||
queues_after=idle_queues(), wall_seconds=time.perf_counter()-started,
|
||||
original_experiment_resumed=False, brain_simulation_tested=False,
|
||||
rejected_invalid_cases=len(rejections),
|
||||
full_training_speedup_measured=False, learning_success_claimed=False,
|
||||
coverage_limit='available prefix + fixed synthetic edge cases, not all registered conditions',
|
||||
files={p.name: sha(p) for p in sorted(args.output.iterdir()) if p.is_file()})
|
||||
save(args.output / 'summary.json', result)
|
||||
print(json.dumps(result), flush=True)
|
||||
except Exception:
|
||||
save(args.output / 'failure.json', dict(exit_code=1, traceback=traceback.format_exc(),
|
||||
wall_seconds=time.perf_counter()-started, original_experiment_resumed=False))
|
||||
raise
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--manifest', type=Path, action='append', required=True)
|
||||
parser.add_argument('--output', type=Path, required=True)
|
||||
parser.add_argument('--uuid', required=True)
|
||||
main(parser.parse_args())
|
||||
@@ -0,0 +1,518 @@
|
||||
"""Export CPU reference fixtures from the fixed, committed Phase 4AR prefix.
|
||||
|
||||
Run with the ORIGINAL models/male-cns-lif/.venv/bin/python -B and --output an
|
||||
absolute, nonexistent directory outside frozen input/source directories. This
|
||||
tool never launches a brain, resumes training, installs weights or changes AR.
|
||||
The original AQ CPU validator is run in fresh CPU-only subprocesses; its only
|
||||
new receipts are placed inside the requested output. A second fresh process per
|
||||
fixture computes the original U Torch CPU reference, including a warm repeat.
|
||||
|
||||
Selection is first and last task_id in each available arm among committed
|
||||
brain/update/verify triples, determined before result/metric files are opened.
|
||||
This bounded engineering sample does not cover all scientific conditions.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
ROOT = Path('/data/digital-drosophila')
|
||||
MODEL = ROOT / 'models/male-cns-lif'
|
||||
EXP = ROOT / 'experiments/phase4ar-normal-conditioning'
|
||||
ORIGINAL_ENV = MODEL / '.venv'
|
||||
REG_SHA = 'b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740'
|
||||
SOURCE_COMMIT = '80aeb2093db655329774eff7b32fb6e417b8b40b'
|
||||
U_SHA = '96efff678cff910654eb08e86f1a17789e4e5589e340345f419c7027a7d547e2'
|
||||
BRIDGE_SHA = '174fb8d14619189e74b095e77a6db18b14c93046dc431c0b55710a5aa2dd2e61'
|
||||
J_SHA = 'abb4574da85f00bd9ef61024c65993ef81d42651ff8d8d63c15dd69c6222471e'
|
||||
ARMS = ('cs_only', 'd_zero', 'dan_only', 'frozen', 'paired', 'random_reward', 'unpaired')
|
||||
INPUT_ARRAYS = ('step', 'neuron_idx', 'kc', 'candidate_edge_id', 'candidate_sources',
|
||||
'candidate_targets', 'candidate_compartments', 'delta_before', 'base_candidate')
|
||||
OUTPUT_ARRAYS = ('delta_after', 'sampled_trace', 'final_trace')
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
if not condition:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
||||
|
||||
|
||||
def digest(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for chunk in iter(lambda: stream.read(8 << 20), b''):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def unlinked(path):
|
||||
path = Path(path)
|
||||
require(path.is_absolute() and '..' not in path.parts, 'Absolute nonescaping path required')
|
||||
require(not any(p.is_symlink() or (hasattr(p, 'is_junction') and p.is_junction())
|
||||
for p in (path, *path.parents)), 'Linked path forbidden: ' + str(path))
|
||||
return path
|
||||
|
||||
|
||||
def read(path):
|
||||
def pairs(items):
|
||||
result = {}
|
||||
for key, value in items:
|
||||
require(key not in result, 'Duplicate JSON key')
|
||||
result[key] = value
|
||||
return result
|
||||
return json.loads(unlinked(path).read_text(encoding='utf-8'), object_pairs_hook=pairs,
|
||||
parse_constant=lambda _: (_ for _ in ()).throw(ValueError('Nonfinite JSON')))
|
||||
|
||||
|
||||
def save(path, value):
|
||||
with unlinked(path).open('x', encoding='utf-8', newline='\n') as stream:
|
||||
json.dump(value, stream, sort_keys=True, indent=2, ensure_ascii=False, allow_nan=False)
|
||||
stream.write('\n')
|
||||
|
||||
|
||||
def identity(path):
|
||||
path = unlinked(path)
|
||||
require(path.is_file(), 'Missing regular file: ' + str(path))
|
||||
size = path.stat().st_size
|
||||
result = dict(sha256=digest(path), bytes=size)
|
||||
require(path.stat().st_size == size, 'File size changed while hashing')
|
||||
return result
|
||||
|
||||
|
||||
def check(path, expected):
|
||||
observed = identity(path)
|
||||
sha = expected if isinstance(expected, str) else expected['sha256']
|
||||
require(observed['sha256'] == sha, 'Pinned bytes changed: ' + str(path))
|
||||
if isinstance(expected, dict) and 'bytes' in expected:
|
||||
require(observed['bytes'] == expected['bytes'], 'Pinned size changed: ' + str(path))
|
||||
return observed
|
||||
|
||||
|
||||
def task_key(task):
|
||||
return 'task-' + hashlib.sha256(task['task_id'].encode()).hexdigest()
|
||||
|
||||
|
||||
def select_tasks(tasks, committed_ids):
|
||||
"""Only plan metadata and committed entry IDs participate in selection."""
|
||||
available = {arm: [] for arm in ARMS}
|
||||
seen = set()
|
||||
for task in tasks:
|
||||
require(task['task_id'] not in seen, 'Duplicate plan task identity')
|
||||
seen.add(task['task_id'])
|
||||
if task['kind'] != 'train':
|
||||
continue
|
||||
require(task['arm'] in available, 'Unexpected training arm')
|
||||
key = task_key(task)
|
||||
if all(key + '--' + stage in committed_ids for stage in ('brain', 'update', 'verify')):
|
||||
available[task['arm']].append(task)
|
||||
selected = []
|
||||
for arm in ARMS:
|
||||
ordered = sorted(available[arm], key=lambda task: task['task_id'])
|
||||
if ordered:
|
||||
selected.append(ordered[0])
|
||||
if ordered[-1]['task_id'] != ordered[0]['task_id']:
|
||||
selected.append(ordered[-1])
|
||||
require(selected, 'No committed train triple is available')
|
||||
return selected, {arm: len(available[arm]) for arm in ARMS}
|
||||
|
||||
|
||||
def ledger_snapshot(exp, reg):
|
||||
"""Read ledger controls, not all historical outcomes; never instantiate Ledger."""
|
||||
control = exp / '.append-ledger'
|
||||
require(not (control / 'writer.lock').exists(), 'Ledger writer/stale lock present')
|
||||
header_path = control / 'header.json'
|
||||
header = read(header_path)
|
||||
require(header['schema'] == 'normal-append-ledger-v1' and header['root'] == str(exp)
|
||||
and header['registration_sha256'] == REG_SHA, 'Ledger header authority differs')
|
||||
expected_initial = {str(Path(p).relative_to(exp)): sha for p, sha in reg['prepared_sha256'].items()}
|
||||
expected_initial['protocol/preregistered.json'] = REG_SHA
|
||||
require({p: info['sha256'] for p, info in header['initial_inventory'].items()} == expected_initial,
|
||||
'Ledger initial inventory differs from registration')
|
||||
control_pins = {str(header_path): identity(header_path)}
|
||||
tracked = {str(exp / p): info for p, info in header['initial_inventory'].items()}
|
||||
entries = {}
|
||||
tail = None
|
||||
paths = sorted((control / 'entries').iterdir())
|
||||
for sequence, path in enumerate(paths, 1):
|
||||
require(path.name == f'{sequence:016d}.json', 'Ledger entries must form a contiguous prefix')
|
||||
row = read(path)
|
||||
name = row['entry_id']
|
||||
require(name not in entries and row['schema'] == 'normal-append-ledger-v1-entry'
|
||||
and row['registration_sha256'] == REG_SHA and row['sequence'] == sequence
|
||||
and row['prev_entry_sha256'] == tail and row['scientific_gate_claimed'] is False,
|
||||
'Ledger chain identity differs')
|
||||
start_path = control / 'started' / (name + '.json')
|
||||
start = read(start_path)
|
||||
control_pins[str(start_path)] = check(start_path, row['start_sha256'])
|
||||
require(start['schema'] == 'normal-append-ledger-v1-start' and start['entry_id'] == name
|
||||
and start['registration_sha256'] == REG_SHA and start['next_sequence'] == sequence
|
||||
and start['prev_entry_sha256'] == tail and start['retry_authorized'] is False,
|
||||
'Ledger start identity differs')
|
||||
for output in row['new_outputs']:
|
||||
output_path = unlinked(output['path'])
|
||||
require(output_path.is_relative_to(exp) and str(output_path.relative_to(exp)) == output['relative_path']
|
||||
and str(output_path) not in tracked, 'Output escapes or repeats immutable history')
|
||||
tracked[str(output_path)] = {key: output[key] for key in ('bytes', 'sha256')}
|
||||
control_pins[str(path)] = identity(path)
|
||||
tail = control_pins[str(path)]['sha256']
|
||||
entries[name] = dict(row=row, start=start, ledger_path=str(path), ledger_sha256=tail)
|
||||
require(entries, 'Empty committed prefix')
|
||||
return entries, tracked, control_pins, dict(entries=len(entries), head_sha256=tail,
|
||||
uncommitted_starts=sorted(p.stem for p in (control / 'started').glob('*.json') if p.stem not in entries),
|
||||
scope='ledger chain controls and selected artifacts; not a full historical payload audit')
|
||||
|
||||
|
||||
def validate_process(entry, tracked, exp):
|
||||
row, start = entry['row'], entry['start']
|
||||
name = row['entry_id']
|
||||
metadata = row['metadata']
|
||||
job_path = unlinked(metadata['job_file'])
|
||||
process_path = unlinked(metadata['process_receipt_file'])
|
||||
require(job_path == exp / 'jobs' / (name + '.json') and process_path == exp / 'receipts' / name / 'process.json',
|
||||
'Process/job location differs')
|
||||
require(str(job_path) in tracked and str(process_path) in tracked, 'Process/job not in committed history')
|
||||
job_pin = check(job_path, tracked[str(job_path)])
|
||||
process_pin = check(process_path, tracked[str(process_path)])
|
||||
require(start['job']['path'] == str(job_path) and start['job']['sha256'] == job_pin['sha256'],
|
||||
'Started job differs from committed job')
|
||||
process = read(process_path)
|
||||
require(process['entry_id'] == name and process['registration_sha256'] == REG_SHA
|
||||
and process['job_sha256'] == job_pin['sha256'] and process['complete'] is True
|
||||
and type(process['exit_code']) is int and process['exit_code'] == 0
|
||||
and process['timed_out'] is False and process['exit_observed_by_parent'] is True
|
||||
and process.get('launch_error') is None and type(metadata['observed_returncode']) is int
|
||||
and metadata['observed_returncode'] == 0, 'Selected process is not committed observed exit zero')
|
||||
require(process['argv'][0] == str(ORIGINAL_ENV / 'bin/python') and '-B' in process['argv'],
|
||||
'Selected process did not use original -B interpreter')
|
||||
job = read(job_path)
|
||||
require(job['registration_sha256'] == REG_SHA, 'Selected job registration differs')
|
||||
outgoing = {item['path']: item for item in row['new_outputs']}
|
||||
require(str(job_path) in outgoing and str(process_path) in outgoing,
|
||||
'Job/process must be outputs of this exact committed entry')
|
||||
consumed = {item['path']: item['sha256'] for item in row['consumed_inputs']}
|
||||
require(all(consumed.get(path) == sha for path, sha in job['input_sha256'].items()),
|
||||
'Selected job input pins differ from committed ledger')
|
||||
return job, {str(job_path): job_pin, str(process_path): process_pin}, process
|
||||
|
||||
|
||||
def array_evidence(array):
|
||||
return dict(dtype=array.dtype.str, shape=list(array.shape), nbytes=int(array.nbytes),
|
||||
raw_c_order_sha256=hashlib.sha256(array.tobytes(order='C')).hexdigest())
|
||||
|
||||
|
||||
def load_npz(path):
|
||||
import numpy as np
|
||||
with np.load(unlinked(path), allow_pickle=False) as archive:
|
||||
return {name: archive[name].copy() for name in archive.files}
|
||||
|
||||
|
||||
def save_npz(path, arrays):
|
||||
import numpy as np
|
||||
with unlinked(path).open('xb') as stream:
|
||||
np.savez_compressed(stream, **arrays)
|
||||
|
||||
|
||||
def load_verified_source(name, path, sha):
|
||||
raw = unlinked(path).read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest() == sha and name not in sys.modules, 'Unverified source/module binding')
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[name] = module
|
||||
exec(compile(raw, str(path), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def cpu_environment():
|
||||
require(sys.dont_write_bytecode and 'torch' not in sys.modules and 'runtime_light' not in sys.modules,
|
||||
'Use a fresh original Python -B process')
|
||||
require(Path(sys.prefix) == ORIGINAL_ENV, 'Reference export requires the original registered .venv')
|
||||
os.environ['CUDA_VISIBLE_DEVICES'] = ''
|
||||
os.environ['PYTHONDONTWRITEBYTECODE'] = '1'
|
||||
|
||||
|
||||
def run_cpu(argv, directory, label):
|
||||
started = time.perf_counter()
|
||||
environment = dict(os.environ, CUDA_VISIBLE_DEVICES='', PYTHONDONTWRITEBYTECODE='1')
|
||||
with (directory / (label + '.stdout.log')).open('xb') as stdout, \
|
||||
(directory / (label + '.stderr.log')).open('xb') as stderr:
|
||||
process = subprocess.run(argv, cwd=directory, env=environment, stdout=stdout, stderr=stderr,
|
||||
timeout=1800, check=False)
|
||||
elapsed = time.perf_counter() - started
|
||||
save(directory / (label + '-process.json'), dict(argv=argv, exit_code=process.returncode,
|
||||
wall_seconds=elapsed, CUDA_VISIBLE_DEVICES='', brain_executed=False))
|
||||
require(process.returncode == 0, label + ' failed; partial outputs retained')
|
||||
return elapsed
|
||||
|
||||
|
||||
def reference_worker(directory):
|
||||
cpu_environment()
|
||||
import numpy as np
|
||||
directory = unlinked(directory)
|
||||
inputs = load_npz(directory / 'inputs.npz')
|
||||
command = read(directory / 'command.json')
|
||||
sources = read(directory / 'reference-sources.json')
|
||||
require(sources['conditioning_update_source']['sha256'] == U_SHA
|
||||
and sources['eligibility_bridge_source']['sha256'] == BRIDGE_SHA
|
||||
and sources['phase4j_source']['sha256'] == J_SHA, 'Original source pins differ')
|
||||
for info in sources.values():
|
||||
check(info['path'], info['sha256'])
|
||||
update = load_verified_source('_acceleration_original_U', sources['conditioning_update_source']['path'], U_SHA)
|
||||
kwargs = {**inputs, **command, 'bridge_source': sources['eligibility_bridge_source']['path'],
|
||||
'phase4j_source': sources['phase4j_source']['path']}
|
||||
before = {name: array_evidence(value) for name, value in inputs.items()}
|
||||
started = time.perf_counter()
|
||||
cold = update.update_epoch(**kwargs)
|
||||
cold_seconds = time.perf_counter() - started
|
||||
started = time.perf_counter()
|
||||
warm = update.update_epoch(**kwargs)
|
||||
warm_seconds = time.perf_counter() - started
|
||||
require(canonical(cold.receipt) == canonical(warm.receipt), 'Cold/warm original receipts differ')
|
||||
for name in OUTPUT_ARRAYS:
|
||||
require(array_evidence(getattr(cold, name)) == array_evidence(getattr(warm, name)),
|
||||
'Cold/warm original output differs: ' + name)
|
||||
require(before == {name: array_evidence(value) for name, value in inputs.items()}, 'Reference input mutated')
|
||||
import torch
|
||||
require(not torch.cuda.is_initialized() and os.environ['CUDA_VISIBLE_DEVICES'] == '', 'CUDA initialized in CPU reference')
|
||||
arrays = {'reference_' + name: getattr(cold, name) for name in OUTPUT_ARRAYS}
|
||||
commands = [] if command['us_tick'] is None else [command['us_tick']]
|
||||
arrays['reference_command_steps'] = np.asarray(commands, dtype=np.int64)
|
||||
arrays['reference_snapshots'] = (np.empty((0, len(inputs['kc'])), np.float32) if not commands
|
||||
else cold.sampled_trace[None, :].copy())
|
||||
save_npz(directory / 'reference.npz', arrays)
|
||||
save(directory / 'reference-update-receipt.json', cold.receipt)
|
||||
save(directory / 'reference-timing.json', dict(schema='conditioning-original-cpu-timing-v1',
|
||||
python_version=sys.version, executable=sys.executable, environment_prefix=sys.prefix,
|
||||
numpy_version=np.__version__, torch_version=torch.__version__, cuda_initialized=False,
|
||||
cold_update_seconds=cold_seconds, warm_update_seconds=warm_seconds,
|
||||
timing_scope='original update_epoch API with loaded arrays, includes source checks/AST parsing; cold includes first Torch import; not pure kernel time',
|
||||
process_time_scope='reference-process.json separately includes startup, loading, two updates and output serialization',
|
||||
snapshot_scope='exact sole declared-US snapshot equals sampled_trace; empty snapshots for no US',
|
||||
output_arrays={name: array_evidence(array) for name, array in arrays.items()},
|
||||
source_pins=sources, cold_warm_bitwise_exact=True, brain_executed=False, weights_installed=False))
|
||||
|
||||
|
||||
def validate_destination(output, protected):
|
||||
output = unlinked(output)
|
||||
require(not output.exists() and output.parent.is_dir(), 'Output must be a fresh directory with an existing parent')
|
||||
require(not any(output.is_relative_to(unlinked(parent)) for parent in protected),
|
||||
'Output overlaps a frozen input/source directory')
|
||||
return output
|
||||
|
||||
|
||||
def export(output):
|
||||
cpu_environment()
|
||||
started = time.perf_counter()
|
||||
own = identity(Path(__file__).absolute())
|
||||
regpath = EXP / 'protocol/preregistered.json'
|
||||
check(regpath, REG_SHA)
|
||||
reg = read(regpath)
|
||||
require(reg['schema'] == 'normal-conditioning-registration-v1'
|
||||
and reg['source_code_commit'] == SOURCE_COMMIT and reg['scientific_scope'] == 'normal-acquisition-only'
|
||||
and reg['subsequent_assays_authorized'] is False, 'Wrong fixed AR authority')
|
||||
source_pins = {**reg['source_sha256'], **{p: sha for p, sha in reg['input_sha256'].items()
|
||||
if Path(p).is_relative_to(MODEL)}}
|
||||
for path, sha in source_pins.items():
|
||||
check(path, sha)
|
||||
planpath = EXP / 'protocol/normal-plan.json'
|
||||
check(planpath, reg['prepared_sha256'][str(planpath)])
|
||||
plan = read(planpath)
|
||||
entries, tracked, control_pins, snapshot = ledger_snapshot(EXP, reg)
|
||||
selected, available = select_tasks(plan['tasks'], set(entries))
|
||||
tasks_by_id = {task['task_id']: task for task in plan['tasks']}
|
||||
protected = {EXP, MODEL, *[Path(p).parent for p in reg['input_sha256']]}
|
||||
output = validate_destination(output, protected)
|
||||
output.mkdir()
|
||||
selection = dict(schema='conditioning-acceleration-selection-v1', registration_sha256=REG_SHA,
|
||||
source_code_commit=SOURCE_COMMIT, rule='first and last lexicographic task_id per arm among committed train brain/update/verify triples',
|
||||
metrics_used_for_selection=False, available_train_counts=available, selected_tasks=selected,
|
||||
selected_count=len(selected), maximum_cases=14, ledger_snapshot=snapshot,
|
||||
coverage_limit='engineering fixtures only; neither complete scientific-condition coverage nor a learning result')
|
||||
save(output / 'selection.json', selection)
|
||||
save(output / 'original-source-pins.json', source_pins)
|
||||
# No task result, update or event array is read before the immutable selection above.
|
||||
fixtures = []
|
||||
for index, task in enumerate(selected):
|
||||
item_started = time.perf_counter()
|
||||
fixture_id = f'{index:02d}-{task["arm"]}'
|
||||
directory = output / fixture_id
|
||||
directory.mkdir()
|
||||
key = task_key(task)
|
||||
file_pins = {}
|
||||
jobs = {}
|
||||
process_records = {}
|
||||
for stage in ('brain', 'update', 'verify'):
|
||||
job, pins, process = validate_process(entries[key + '--' + stage], tracked, EXP)
|
||||
jobs[stage] = job
|
||||
file_pins.update(pins)
|
||||
process_records[stage] = process
|
||||
result_path = EXP / 'results' / (key + '.json')
|
||||
file_pins[str(result_path)] = check(result_path, tracked[str(result_path)])
|
||||
result = read(result_path)
|
||||
require(result['schema'] == 'normal-task-result-v1' and result['complete'] is True
|
||||
and result['registration_sha256'] == REG_SHA and result['task'] == task, 'Selected result/plan differs')
|
||||
authority_path = unlinked(result['epoch_authority']['path'])
|
||||
authority_sha = result['epoch_authority']['sha256']
|
||||
file_pins[str(authority_path)] = check(authority_path, tracked[str(authority_path)])
|
||||
require(file_pins[str(authority_path)]['sha256'] == authority_sha, 'Authority result/ledger pin differs')
|
||||
authority = read(authority_path)
|
||||
command = dict(authority['command'], n_neurons=166700)
|
||||
require(authority['epoch_id'] == task['task_id'] and authority['diagnostic_mode'] == 'light'
|
||||
and command == dict(steps=task['steps'], n_neurons=166700, compartment=task['compartment_verbatim'],
|
||||
us_tick=task['recipe']['us']['tick'], d_command=task['recipe']['D_command'],
|
||||
frozen=not task['recipe']['update_enabled'], trace_backend='torch'), 'Actual command differs from registered task')
|
||||
update_dir = unlinked(result['update_dir'])
|
||||
require(update_dir == EXP / 'updates' / key and authority_path == EXP / 'jobs' / (key + '.authority.json')
|
||||
and authority['checkpoint_dir'] == result['checkpoint_dir'] == str(EXP / 'runs' / key)
|
||||
and authority['checkpoint_manifest_sha256'] == result['checkpoint_manifest_sha256'],
|
||||
'Task checkpoint/update location differs')
|
||||
for stage in ('update', 'verify'):
|
||||
require(jobs[stage]['authority_file'] == str(authority_path) and jobs[stage]['authority_sha256'] == authority_sha,
|
||||
'Authority not bound to selected successful job')
|
||||
require(jobs['brain']['output_dir'] == authority['checkpoint_dir'] and jobs['update']['output_dir'] == str(update_dir)
|
||||
and jobs['verify']['update_dir'] == str(update_dir), 'Selected process output differs')
|
||||
require(jobs['brain']['kind'] == 'brain' and jobs['update']['kind'] == 'update'
|
||||
and jobs['verify']['kind'] == 'cpu_verify', 'Selected process role differs')
|
||||
dependency = task['delta_dependency']
|
||||
if dependency == dict(kind='zero', source=None):
|
||||
expected_before = reg['initial_overlay']
|
||||
else:
|
||||
require(dependency['kind'] == 'epoch_delta_after' and dependency['source'].endswith('/delta-after'),
|
||||
'Unknown registered overlay dependency')
|
||||
previous = tasks_by_id[dependency['source'][:-len('/delta-after')]]
|
||||
require(previous['kind'] == 'train' and all(previous[field] == task[field] for field in ('block_id', 'arm'))
|
||||
and task_key(previous) + '--verify' in entries, 'Previous overlay is not a committed same-arm training output')
|
||||
previous_dir = EXP / 'updates' / task_key(previous)
|
||||
expected_before = dict(overlay_file=str(previous_dir / 'delta-after.npz'),
|
||||
overlay_manifest=str(previous_dir / 'overlay-manifest.json'))
|
||||
require(result['overlay_before'] == expected_before
|
||||
and jobs['brain']['overlay_file'] == expected_before['overlay_file']
|
||||
and jobs['brain']['overlay_manifest'] == expected_before['overlay_manifest']
|
||||
and authority['files']['overlay_before']['path'] == expected_before['overlay_file']
|
||||
and authority['files']['overlay_manifest_before']['path'] == expected_before['overlay_manifest'],
|
||||
'Actual before overlay differs from registered branch dependency')
|
||||
registered_files = {**reg['input_sha256'], **reg['prepared_sha256']}
|
||||
for info in authority['files'].values():
|
||||
require(jobs['update']['input_sha256'].get(info['path']) == info['sha256'], 'Authority role absent from successful update inputs')
|
||||
trusted_sha = registered_files.get(info['path'], tracked.get(info['path'], {}).get('sha256'))
|
||||
require(trusted_sha == info['sha256'], 'Authority role lacks registered or committed file identity')
|
||||
file_pins[info['path']] = check(info['path'], info['sha256'])
|
||||
for name in ('chain-receipt.json', 'update-receipt.json', 'delta-after.npz', 'overlay-manifest.json'):
|
||||
path = update_dir / name
|
||||
file_pins[str(path)] = check(path, tracked[str(path)])
|
||||
chain_sha = file_pins[str(update_dir / 'chain-receipt.json')]['sha256']
|
||||
require(jobs['verify']['chain_sha256'] == chain_sha, 'Selected CPU validator used a different chain')
|
||||
cpu_path = unlinked(result['cpu_validation']['path'])
|
||||
file_pins[str(cpu_path)] = check(cpu_path, tracked[str(cpu_path)])
|
||||
require(file_pins[str(cpu_path)]['sha256'] == result['cpu_validation']['sha256'], 'Original CPU receipt pin differs')
|
||||
original_validation = read(cpu_path)
|
||||
require(original_validation['complete'] is True and original_validation['frozen_U_verify_receipt_recomputed'] is True
|
||||
and original_validation['actual_sealed_events_used'] is True
|
||||
and original_validation['full_candidate_mapping_verified'] is True
|
||||
and original_validation['epoch_authority_sha256'] == authority_sha, 'Original CPU validation incomplete')
|
||||
validator = MODEL / 'conditioning-execution-v1/validate_update_cpu.py'
|
||||
check(validator, reg['input_sha256'][str(validator)])
|
||||
validator_seconds = run_cpu([sys.executable, '-B', str(validator), '--authority', str(authority_path),
|
||||
'--authority-sha256', authority_sha, '--update-dir', str(update_dir), '--chain-sha256', chain_sha,
|
||||
'--receipt', str(directory / 'fresh-cpu-validation.json')], directory, 'validation')
|
||||
fresh = read(directory / 'fresh-cpu-validation.json')
|
||||
require(fresh == original_validation, 'Fresh original validator receipt differs from committed receipt')
|
||||
import numpy as np
|
||||
paths = {role: unlinked(info['path']) for role, info in authority['files'].items()}
|
||||
state = load_npz(paths['state'])
|
||||
mapping = load_npz(paths['candidate_map'])
|
||||
before = load_npz(paths['overlay_before'])
|
||||
after = load_npz(update_dir / 'delta-after.npz')
|
||||
arrays = dict(step=state['step'], neuron_idx=state['neuron_idx'],
|
||||
kc=np.load(paths['kc'], allow_pickle=False), candidate_edge_id=np.load(paths['mask'], allow_pickle=False),
|
||||
candidate_sources=mapping['source_neuron_idx'], candidate_targets=mapping['target_neuron_idx'],
|
||||
candidate_compartments=mapping['target_compartment_verbatim'], delta_before=before['plastic_delta_mv'],
|
||||
base_candidate=np.load(paths['base_candidate'], allow_pickle=False))
|
||||
require(len(arrays['kc']) == 4064 and len(arrays['candidate_edge_id']) == 14232, 'Complete identity dimensions differ')
|
||||
save_npz(directory / 'inputs.npz', arrays)
|
||||
save(directory / 'command.json', command)
|
||||
sources = {role: authority['files'][role] for role in
|
||||
('conditioning_update_source', 'eligibility_bridge_source', 'phase4j_source')}
|
||||
save(directory / 'reference-sources.json', sources)
|
||||
reference_seconds = run_cpu([sys.executable, '-B', str(Path(__file__).absolute()),
|
||||
'--reference-worker', str(directory)], directory, 'reference')
|
||||
reference = load_npz(directory / 'reference.npz')
|
||||
receipt = read(directory / 'reference-update-receipt.json')
|
||||
stored_receipt = read(update_dir / 'update-receipt.json')
|
||||
require(canonical(receipt) == canonical(stored_receipt), 'Original recomputation differs from stored update receipt')
|
||||
require(array_evidence(reference['reference_delta_after']) == array_evidence(after['plastic_delta_mv']),
|
||||
'Original reference delta bytes differ from committed delta-after')
|
||||
for name in OUTPUT_ARRAYS:
|
||||
require(array_evidence(reference['reference_' + name]) == stored_receipt['outputs'][name],
|
||||
'Reference trace/delta does not match original receipt byte identity')
|
||||
fixture = {**arrays, **reference, 'stored_delta_after': after['plastic_delta_mv']}
|
||||
save_npz(directory / 'fixture.npz', fixture)
|
||||
save(directory / 'authority.json', authority)
|
||||
save(directory / 'stored-update-receipt.json', stored_receipt)
|
||||
save(directory / 'source-file-pins.json', file_pins)
|
||||
timing = read(directory / 'reference-timing.json')
|
||||
record = dict(fixture_id=fixture_id, task=task, npz=f'{fixture_id}/fixture.npz',
|
||||
command=f'{fixture_id}/command.json', npz_sha256=digest(directory / 'fixture.npz'),
|
||||
command_sha256=digest(directory / 'command.json'), authority_sha256=authority_sha,
|
||||
original_update_payload_sha256=receipt['payload_sha256'],
|
||||
exact_stored_delta_and_trace_verified=True, full_canonical_KC_count=4064, full_candidate_edge_count=14232,
|
||||
original_validator_verified_full_graph_mapping=True, reference_timing=timing,
|
||||
reference_subprocess_wall_seconds=reference_seconds, original_validator_subprocess_wall_seconds=validator_seconds,
|
||||
fixture_end_to_end_seconds=time.perf_counter() - item_started,
|
||||
historical_process_seconds={stage: {field: proc[field] for field in ('child_wall_seconds', 'end_to_end_seconds')}
|
||||
for stage, proc in process_records.items()},
|
||||
input_arrays={name: array_evidence(value) for name, value in arrays.items()},
|
||||
output_arrays={name: array_evidence(value) for name, value in reference.items()})
|
||||
save(directory / 'fixture.json', record)
|
||||
fixtures.append(record)
|
||||
print(canonical(dict(fixture=fixture_id, complete=True, task_id=task['task_id'])), flush=True)
|
||||
for path, pin in control_pins.items():
|
||||
check(path, pin)
|
||||
require(not (EXP / '.append-ledger/writer.lock').exists()
|
||||
and len(list((EXP / '.append-ledger/entries').iterdir())) == snapshot['entries'],
|
||||
'Ledger changed during export; fixture set not published')
|
||||
for path, sha in source_pins.items():
|
||||
check(path, sha)
|
||||
check(Path(__file__).absolute(), own)
|
||||
# Recheck all selected immutable input/output pins after the entire export.
|
||||
all_pins = {}
|
||||
for fixture in fixtures:
|
||||
all_pins.update(read(output / fixture['fixture_id'] / 'source-file-pins.json'))
|
||||
for path, pin in all_pins.items():
|
||||
check(path, pin)
|
||||
manifest = dict(schema='conditioning-acceleration-fixtures-v1', complete=True,
|
||||
registration_sha256=REG_SHA, source_code_commit=SOURCE_COMMIT,
|
||||
exporter_source=dict(path=str(Path(__file__).absolute()), **own),
|
||||
created_utc=datetime.now(timezone.utc).isoformat(), selection_sha256=digest(output / 'selection.json'),
|
||||
fixtures=fixtures, fixture_count=len(fixtures), coverage=selection,
|
||||
total_export_seconds=time.perf_counter() - started,
|
||||
original_files_modified=False, brain_executed=False, training_executed=False,
|
||||
weights_installed=False, learning_pass_claimed=False,
|
||||
authority_limit='committed selected historical processes and original CPU reference only; AR remains incomplete',
|
||||
files={str(path.relative_to(output)): identity(path) for path in sorted(output.rglob('*')) if path.is_file()})
|
||||
save(output / 'manifest.json', manifest)
|
||||
return manifest
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
mode = parser.add_mutually_exclusive_group(required=True)
|
||||
mode.add_argument('--output', type=Path)
|
||||
mode.add_argument('--reference-worker', type=Path, help=argparse.SUPPRESS)
|
||||
args = parser.parse_args()
|
||||
if args.reference_worker:
|
||||
reference_worker(args.reference_worker)
|
||||
else:
|
||||
result = export(args.output)
|
||||
print(canonical(dict(complete=True, output=str(args.output), fixtures=result['fixture_count'])), flush=True)
|
||||
@@ -0,0 +1,362 @@
|
||||
"""Fixed synthetic full-mapping fixtures, using only the original CPU oracle.
|
||||
|
||||
Run the original science Python -B with --template pointing to a completed real
|
||||
export's fixture.npz and --output a new directory. Anatomical arrays retain the
|
||||
real fixture's authenticated identity; events and delta-before are explicitly
|
||||
synthetic. No brain, training, installed weights or original files are changed.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import time
|
||||
|
||||
import export_fixtures as original
|
||||
|
||||
|
||||
COMPARTMENTS = ("B2B'2a", "a1", "y2a'1", "y5B'2a")
|
||||
STATIC_ARRAYS = ("kc", "candidate_edge_id", "candidate_sources", "candidate_targets",
|
||||
"candidate_compartments", "base_candidate")
|
||||
STEPS = 1200
|
||||
N_NEURONS = 166700
|
||||
SEEDS = (717, 20261001)
|
||||
|
||||
|
||||
def template_binding(template, metadata=None, manifest_path=None):
|
||||
"""Bind to a completed real export and its original full-graph validation."""
|
||||
template = original.unlinked(template)
|
||||
directory = template.parent
|
||||
root = directory.parent
|
||||
metadata = original.unlinked(metadata or directory / 'fixture.json')
|
||||
manifest_path = original.unlinked(manifest_path or root / 'manifest.json')
|
||||
original.require(template == directory / 'fixture.npz' and metadata == directory / 'fixture.json'
|
||||
and manifest_path == root / 'manifest.json', 'Use one intact real-fixture export')
|
||||
manifest = original.read(manifest_path)
|
||||
original.require(manifest['schema'] == 'conditioning-acceleration-fixtures-v1'
|
||||
and manifest['complete'] is True and manifest['registration_sha256'] == original.REG_SHA,
|
||||
'Template requires a completed real-fixture manifest')
|
||||
required = ('fixture.npz', 'fixture.json', 'command.json', 'reference-sources.json',
|
||||
'fresh-cpu-validation.json', 'validation-process.json', 'reference-process.json')
|
||||
pins = {str(manifest_path): original.identity(manifest_path)}
|
||||
for name in required:
|
||||
path = directory / name
|
||||
rel = path.relative_to(root).as_posix()
|
||||
original.require(rel in manifest['files'], 'Template file absent from manifest: ' + rel)
|
||||
pins[str(path)] = original.check(path, manifest['files'][rel])
|
||||
record = original.read(metadata)
|
||||
original.require(record in manifest['fixtures'] and record['fixture_id'] == directory.name
|
||||
and record['npz'] == template.relative_to(root).as_posix()
|
||||
and record['npz_sha256'] == pins[str(template)]['sha256']
|
||||
and record['exact_stored_delta_and_trace_verified'] is True
|
||||
and record['original_validator_verified_full_graph_mapping'] is True
|
||||
and record['full_canonical_KC_count'] == 4064
|
||||
and record['full_candidate_edge_count'] == 14232,
|
||||
'Template record does not bind an authenticated complete original mapping')
|
||||
fresh = original.read(directory / 'fresh-cpu-validation.json')
|
||||
original.require(fresh['complete'] is True and fresh['full_candidate_mapping_verified'] is True
|
||||
and fresh['frozen_U_verify_receipt_recomputed'] is True
|
||||
and fresh['epoch_authority_sha256'] == record['authority_sha256'],
|
||||
'Original full-graph CPU validation differs')
|
||||
for name in ('validation-process.json', 'reference-process.json'):
|
||||
process = original.read(directory / name)
|
||||
original.require(type(process['exit_code']) is int and process['exit_code'] == 0
|
||||
and process['argv'][0] == str(original.ORIGINAL_ENV / 'bin/python')
|
||||
and process['CUDA_VISIBLE_DEVICES'] == '', 'Template original CPU process invalid')
|
||||
sources = original.read(directory / 'reference-sources.json')
|
||||
expected = dict(conditioning_update_source=original.U_SHA,
|
||||
eligibility_bridge_source=original.BRIDGE_SHA, phase4j_source=original.J_SHA)
|
||||
original.require(set(sources) == set(expected), 'Original source roles differ')
|
||||
for role, sha in expected.items():
|
||||
original.require(sources[role]['sha256'] == sha, 'Original source identity differs: ' + role)
|
||||
pins[sources[role]['path']] = original.check(sources[role]['path'], sha)
|
||||
arrays = original.load_npz(template)
|
||||
for name in original.INPUT_ARRAYS:
|
||||
original.require(original.array_evidence(arrays[name]) == record['input_arrays'][name],
|
||||
'Template input array identity differs: ' + name)
|
||||
command = original.read(directory / 'command.json')
|
||||
original.require(command['steps'] == STEPS and command['n_neurons'] == N_NEURONS
|
||||
and command['trace_backend'] == 'torch', 'Unexpected original fixture dimensions')
|
||||
return arrays, sources, pins, record
|
||||
|
||||
|
||||
def fixed_cases(template):
|
||||
"""Create the declared sixteen cases without inspecting candidate outputs."""
|
||||
import numpy as np
|
||||
kc = template['kc']
|
||||
sources = template['candidate_sources']
|
||||
base = template['base_candidate']
|
||||
lower = np.float32(-0.25) * base
|
||||
original.require(kc.dtype == np.int32 and len(kc) == 4064 and np.all(kc[1:] > kc[:-1])
|
||||
and len(base) == len(template['candidate_edge_id']) == 14232,
|
||||
'Expected complete canonical anatomical arrays')
|
||||
original.require(set(np.unique(template['candidate_compartments'])) == set(COMPARTMENTS),
|
||||
'Template must cover all four original compartments')
|
||||
active_sources = np.unique(sources)
|
||||
chosen = active_sources[:3]
|
||||
original.require(len(chosen) == 3, 'Need three distinct candidate KC sources')
|
||||
non_kc = int(np.flatnonzero(~np.isin(np.arange(N_NEURONS, dtype=np.int32), kc))[0])
|
||||
zero = np.zeros(len(base), np.float32)
|
||||
partial = np.float32(-0.125) * base
|
||||
partial[::3] = np.float32(0)
|
||||
|
||||
def events(rows):
|
||||
rows = sorted(set((int(t), int(n)) for t, n in rows))
|
||||
return (np.asarray([row[0] for row in rows], np.int32),
|
||||
np.asarray([row[1] for row in rows], np.int32))
|
||||
|
||||
def case(name, rows, *, us=900, d=1., frozen=False, compartment=COMPARTMENTS[0], delta=None, tags=()):
|
||||
tick, neuron = events(rows)
|
||||
arrays = {key: template[key].copy() for key in STATIC_ARRAYS}
|
||||
arrays.update(step=tick, neuron_idx=neuron,
|
||||
delta_before=(zero if delta is None else delta).copy())
|
||||
return dict(name=name, arrays=arrays,
|
||||
command=dict(steps=STEPS, n_neurons=N_NEURONS, compartment=compartment,
|
||||
us_tick=us, d_command=d, frozen=frozen, trace_backend='torch'),
|
||||
tags=list(tags), synthetic_events=True, synthetic_delta_before=True)
|
||||
|
||||
boundary = [(899, chosen[0]), (900, chosen[1]), (901, chosen[2]),
|
||||
(0, non_kc), (900, non_kc), (1199, non_kc)]
|
||||
ends = [(0, chosen[0]), (1, chosen[1]), (1199, chosen[2]), (0, non_kc), (1199, non_kc)]
|
||||
all_active = [(900, n) for n in active_sources]
|
||||
cases = [
|
||||
case('empty-us900', [], tags=('empty', 'positive-zero')),
|
||||
case('non-kc-only', [(0, non_kc), (900, non_kc), (1199, non_kc)], tags=('ignore-non-KC',)),
|
||||
case('no-us-mixed', boundary, us=None, d=0., tags=('no-US', 'sampled-positive-zero', 'nonzero-final')),
|
||||
case('us-first-tick', ends, us=0, tags=('US-zero', 'after-current-spike')),
|
||||
case('us-final-tick', ends, us=1199, tags=('US-final', 'after-current-spike')),
|
||||
case('before-on-after-us900', boundary, tags=('US-boundary', 'mixed-KC-non-KC')),
|
||||
case('d-zero-existing-delta', boundary, d=0., delta=partial, tags=('D-zero', 'bitwise-identity')),
|
||||
case('frozen-existing-delta', boundary, frozen=True, delta=partial, tags=('frozen', 'bitwise-identity')),
|
||||
]
|
||||
for index, compartment in enumerate(COMPARTMENTS):
|
||||
cases.append(case(f'compartment-{index}', all_active, compartment=compartment, delta=partial,
|
||||
tags=('full-source-activation', 'off-compartment-bitwise-identity', compartment)))
|
||||
cases.append(case('already-at-floor', all_active, delta=lower, tags=('floor', 'already-saturated')))
|
||||
near = np.nextafter(lower, np.full_like(lower, np.inf))
|
||||
cases.append(case('one-ulp-above-floor', all_active, delta=near, tags=('floor', 'new-saturation')))
|
||||
for seed in SEEDS:
|
||||
rng = np.random.default_rng(seed)
|
||||
ticks = rng.integers(0, STEPS, size=5000)
|
||||
neurons = rng.choice(kc, size=5000)
|
||||
extra_ticks = rng.integers(0, STEPS, size=1000)
|
||||
extra_neurons = rng.integers(0, N_NEURONS, size=1000)
|
||||
rows = list(zip(ticks, neurons)) + list(zip(extra_ticks, extra_neurons))
|
||||
delta = -(rng.uniform(0., .249, len(base)).astype(np.float32) * base)
|
||||
delta[::7] = np.float32(0)
|
||||
delta[1::11] = lower[1::11]
|
||||
item = case(f'seeded-sparse-{seed}', rows, delta=delta, tags=('seeded-sparse', 'mixed-delta', 'canonical-zero'))
|
||||
item['rng_seed'] = seed
|
||||
cases.append(item)
|
||||
original.require(len(cases) == 16, 'Fixed synthetic coverage changed')
|
||||
for item in cases:
|
||||
for name in STATIC_ARRAYS:
|
||||
original.require(original.array_evidence(item['arrays'][name]) == original.array_evidence(template[name]),
|
||||
'Synthetic generation changed an anatomical array: ' + name)
|
||||
original.require(not np.any((item['arrays']['delta_before'] == 0)
|
||||
& np.signbit(item['arrays']['delta_before'])), 'Synthetic delta has negative zero')
|
||||
cases[4]['trace_command_steps'] = [0, 900, 1199]
|
||||
cases[4]['tags'].append('multiple-US-snapshots')
|
||||
return cases
|
||||
|
||||
|
||||
def supplemental_worker(directory):
|
||||
"""Fresh original CPU process for multiple snapshots or rejection evidence."""
|
||||
original.cpu_environment()
|
||||
import numpy as np
|
||||
directory = original.unlinked(directory)
|
||||
sources = original.read(directory / 'reference-sources.json')
|
||||
expected = dict(conditioning_update_source=original.U_SHA,
|
||||
eligibility_bridge_source=original.BRIDGE_SHA, phase4j_source=original.J_SHA)
|
||||
original.require(set(sources) == set(expected), 'Supplemental source roles differ')
|
||||
for role, sha in expected.items():
|
||||
original.require(sources[role]['sha256'] == sha, 'Supplemental frozen source differs')
|
||||
original.check(sources[role]['path'], sha)
|
||||
if (directory / 'trace-command-steps.json').exists():
|
||||
arrays = original.load_npz(directory / 'inputs.npz')
|
||||
command = original.read(directory / 'command.json')
|
||||
commands = original.read(directory / 'trace-command-steps.json')
|
||||
bridge = original.load_verified_source('_synthetic_original_bridge',
|
||||
sources['eligibility_bridge_source']['path'], original.BRIDGE_SHA)
|
||||
trace = bridge.trace_from_events(arrays['step'], arrays['neuron_idx'], arrays['kc'],
|
||||
command['steps'], commands, phase4j_source=sources['phase4j_source']['path'],
|
||||
backend='torch', n_neurons=command['n_neurons'])
|
||||
sole = original.load_npz(directory / 'reference.npz')
|
||||
original.require(original.array_evidence(trace.final) == original.array_evidence(sole['reference_final_trace'])
|
||||
and original.array_evidence(trace.last_command_trace)
|
||||
== original.array_evidence(sole['reference_sampled_trace']),
|
||||
'Multiple-US last sample or final differs from original single-US U reference')
|
||||
original.save_npz(directory / 'multiple-reference.npz', dict(reference_snapshots=trace.snapshots,
|
||||
reference_command_steps=trace.command_steps, reference_sampled_trace=trace.last_command_trace,
|
||||
reference_final_trace=trace.final))
|
||||
import torch
|
||||
original.require(not torch.cuda.is_initialized(), 'Supplemental CPU oracle initialized CUDA')
|
||||
original.save(directory / 'multiple-reference.json', dict(complete=True, trace_audit=trace.audit,
|
||||
source_pins=sources, numpy_version=np.__version__, torch_version=torch.__version__,
|
||||
final_and_last_sample_match_original_U=True, brain_executed=False, weights_installed=False))
|
||||
return
|
||||
cases = original.read(directory / 'invalid-selection.json')
|
||||
update = original.load_verified_source('_synthetic_rejection_original_U',
|
||||
sources['conditioning_update_source']['path'], original.U_SHA)
|
||||
records = []
|
||||
for item in cases:
|
||||
arrays = original.load_npz(directory / item['npz'])
|
||||
command = original.read(directory / item['command'])
|
||||
try:
|
||||
update.update_epoch(**arrays, **command,
|
||||
bridge_source=sources['eligibility_bridge_source']['path'],
|
||||
phase4j_source=sources['phase4j_source']['path'])
|
||||
except ValueError as error:
|
||||
records.append(dict(case_name=item['case_name'], rejected=True, exception='ValueError', message=str(error)))
|
||||
else:
|
||||
raise ValueError('Original U unexpectedly accepted invalid case: ' + item['case_name'])
|
||||
original.save(directory / 'original-rejections.json', dict(complete=True, cases=records,
|
||||
source_pins=sources, brain_executed=False, weights_installed=False))
|
||||
|
||||
|
||||
def export_invalid(output, valid_case, sources):
|
||||
import numpy as np
|
||||
directory = output / 'invalid'
|
||||
directory.mkdir()
|
||||
original.save(directory / 'reference-sources.json', sources)
|
||||
definitions = [('duplicate-events', 'prepare'), ('unsorted-events', 'prepare'),
|
||||
('out-of-range-tick', 'prepare'), ('negative-zero-delta', 'run'),
|
||||
('non-kc-candidate-source', 'run'), ('unsorted-kc', 'prepare')]
|
||||
records = []
|
||||
for index, (name, stage) in enumerate(definitions):
|
||||
arrays = {key: value.copy() for key, value in valid_case['arrays'].items()}
|
||||
if name == 'duplicate-events':
|
||||
arrays['step'] = np.array([0, 0], np.int32)
|
||||
arrays['neuron_idx'] = np.full(2, arrays['kc'][0], np.int32)
|
||||
elif name == 'unsorted-events':
|
||||
arrays['step'] = np.array([1, 0], np.int32)
|
||||
arrays['neuron_idx'] = np.full(2, arrays['kc'][0], np.int32)
|
||||
elif name == 'out-of-range-tick':
|
||||
arrays['step'] = np.array([STEPS], np.int32)
|
||||
arrays['neuron_idx'] = np.array([arrays['kc'][0]], np.int32)
|
||||
elif name == 'negative-zero-delta':
|
||||
arrays['delta_before'][0] = np.float32(-0.)
|
||||
elif name == 'non-kc-candidate-source':
|
||||
arrays['candidate_sources'][0] = int(np.flatnonzero(
|
||||
~np.isin(np.arange(N_NEURONS, dtype=np.int32), arrays['kc']))[0])
|
||||
elif name == 'unsorted-kc':
|
||||
arrays['kc'] = arrays['kc'][::-1].copy()
|
||||
npz = f'{index:02d}-{name}.npz'
|
||||
command = f'{index:02d}-{name}.json'
|
||||
original.save_npz(directory / npz, arrays)
|
||||
original.save(directory / command, valid_case['command'])
|
||||
records.append(dict(case_name=name, npz=npz, command=command, stage=stage,
|
||||
expected_exception='ValueError', npz_sha256=original.digest(directory / npz),
|
||||
command_sha256=original.digest(directory / command)))
|
||||
original.save(directory / 'invalid-selection.json', records)
|
||||
original.run_cpu([sys.executable, '-B', str(Path(__file__).absolute()), '--supplemental-worker', str(directory)],
|
||||
directory, 'original-rejection')
|
||||
evidence = original.read(directory / 'original-rejections.json')
|
||||
original.require(evidence['complete'] is True and len(evidence['cases']) == len(records),
|
||||
'Original rejection coverage incomplete')
|
||||
for record, result in zip(records, evidence['cases']):
|
||||
original.require(record['case_name'] == result['case_name'] and result['rejected'] is True,
|
||||
'Original rejection identity differs')
|
||||
record.update(npz='invalid/' + record['npz'], command='invalid/' + record['command'],
|
||||
original_oracle_rejection=result)
|
||||
return records
|
||||
|
||||
|
||||
def export(template, output, metadata=None, manifest_path=None):
|
||||
original.cpu_environment()
|
||||
started = time.perf_counter()
|
||||
own = original.identity(Path(__file__).absolute())
|
||||
helper = original.identity(Path(original.__file__).absolute())
|
||||
arrays, sources, pins, template_record = template_binding(template, metadata, manifest_path)
|
||||
cases = fixed_cases(arrays)
|
||||
protected = {original.ROOT, Path(template).parent.parent, Path(__file__).absolute().parent,
|
||||
*(Path(info['path']).parent for info in sources.values())}
|
||||
output = original.validate_destination(output, protected)
|
||||
output.mkdir()
|
||||
original.save(output / 'template-binding.json', dict(template=str(template), template_record=template_record,
|
||||
input_pins=pins, scope='complete anatomical identity inherited from original full-graph CPU validation',
|
||||
original_events_reused=False, original_delta_before_reused=False))
|
||||
original.save(output / 'selection.json', dict(schema='conditioning-fixed-synthetic-selection-v1',
|
||||
names=[item['name'] for item in cases], count=16, seeds=list(SEEDS),
|
||||
chosen_before_candidate_execution=True, original_full_mapping_preserved=True))
|
||||
fixtures = []
|
||||
for index, item in enumerate(cases):
|
||||
fixture_id = f'{index:02d}-{item["name"]}'
|
||||
directory = output / fixture_id
|
||||
directory.mkdir()
|
||||
original.save_npz(directory / 'inputs.npz', item['arrays'])
|
||||
original.save(directory / 'command.json', item['command'])
|
||||
original.save(directory / 'reference-sources.json', sources)
|
||||
seconds = original.run_cpu([sys.executable, '-B', str(Path(original.__file__).absolute()),
|
||||
'--reference-worker', str(directory)], directory, 'reference')
|
||||
reference = original.load_npz(directory / 'reference.npz')
|
||||
receipt = original.read(directory / 'reference-update-receipt.json')
|
||||
timing = original.read(directory / 'reference-timing.json')
|
||||
original.require(timing['numpy_version'] == template_record['reference_timing']['numpy_version']
|
||||
and timing['torch_version'] == template_record['reference_timing']['torch_version'],
|
||||
'Synthetic oracle differs from the real fixture original environment')
|
||||
for name in original.OUTPUT_ARRAYS:
|
||||
original.require(original.array_evidence(reference['reference_' + name]) == receipt['outputs'][name],
|
||||
'Synthetic reference output/receipt differs: ' + name)
|
||||
if 'trace_command_steps' in item:
|
||||
original.save(directory / 'trace-command-steps.json', item['trace_command_steps'])
|
||||
original.run_cpu([sys.executable, '-B', str(Path(__file__).absolute()),
|
||||
'--supplemental-worker', str(directory)], directory, 'multiple-reference')
|
||||
reference.update(original.load_npz(directory / 'multiple-reference.npz'))
|
||||
original.save_npz(directory / 'fixture.npz', {**item['arrays'], **reference})
|
||||
record = dict(fixture_id=fixture_id, kind='synthetic', name=item['name'], tags=item['tags'],
|
||||
npz=f'{fixture_id}/fixture.npz', command=f'{fixture_id}/command.json',
|
||||
npz_sha256=original.digest(directory / 'fixture.npz'),
|
||||
command_sha256=original.digest(directory / 'command.json'),
|
||||
original_update_payload_sha256=receipt['payload_sha256'],
|
||||
exact_stored_delta_and_trace_verified=False, historical_scientific_output_exists=False,
|
||||
full_canonical_KC_count=4064, full_candidate_edge_count=14232,
|
||||
original_validator_verified_full_graph_mapping=True,
|
||||
mapping_identity_scope='inherited unchanged from template; events and delta-before are synthetic',
|
||||
reference_timing=timing, reference_subprocess_wall_seconds=seconds,
|
||||
input_arrays={name: original.array_evidence(value) for name, value in item['arrays'].items()},
|
||||
output_arrays={name: original.array_evidence(value) for name, value in reference.items()})
|
||||
if 'trace_command_steps' in item:
|
||||
record['snapshot_scope'] = 'Original Torch bridge multiple-US snapshots; last sample matches original U single final-US output'
|
||||
record['command_steps'] = item['trace_command_steps']
|
||||
original.save(directory / 'fixture.json', record)
|
||||
fixtures.append(record)
|
||||
print(original.canonical(dict(fixture=fixture_id, kind='synthetic', complete=True)), flush=True)
|
||||
invalid_cases = export_invalid(output, cases[5], sources)
|
||||
for path, pin in pins.items():
|
||||
original.check(path, pin)
|
||||
original.check(Path(__file__).absolute(), own)
|
||||
original.check(Path(original.__file__).absolute(), helper)
|
||||
manifest = dict(schema='conditioning-acceleration-fixtures-v1', kind='synthetic', complete=True,
|
||||
registration_sha256=original.REG_SHA, source_code_commit=original.SOURCE_COMMIT,
|
||||
exporter_source=dict(path=str(Path(__file__).absolute()), **own),
|
||||
original_helper_source=dict(path=str(Path(original.__file__).absolute()), **helper),
|
||||
created_utc=datetime.now(timezone.utc).isoformat(), fixtures=fixtures, fixture_count=len(fixtures),
|
||||
invalid_cases=invalid_cases, invalid_case_count=len(invalid_cases),
|
||||
selection_sha256=original.digest(output / 'selection.json'),
|
||||
template_binding_sha256=original.digest(output / 'template-binding.json'),
|
||||
total_export_seconds=time.perf_counter() - started, original_files_modified=False,
|
||||
brain_executed=False, training_executed=False, weights_installed=False, learning_pass_claimed=False,
|
||||
authority_limit='synthetic arithmetic edge cases with original mapping; not historical scientific trials',
|
||||
files={str(path.relative_to(output)): original.identity(path)
|
||||
for path in sorted(output.rglob('*')) if path.is_file()})
|
||||
original.save(output / 'manifest.json', manifest)
|
||||
return manifest
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--template', type=Path)
|
||||
parser.add_argument('--metadata', type=Path)
|
||||
parser.add_argument('--manifest', type=Path)
|
||||
parser.add_argument('--output', type=Path)
|
||||
parser.add_argument('--supplemental-worker', type=Path, help=argparse.SUPPRESS)
|
||||
args = parser.parse_args()
|
||||
if args.supplemental_worker:
|
||||
original.require(not any((args.template, args.output, args.metadata, args.manifest)), 'Do not combine worker/export modes')
|
||||
supplemental_worker(args.supplemental_worker)
|
||||
else:
|
||||
original.require(args.template is not None and args.output is not None, '--template and --output are required')
|
||||
result = export(args.template, args.output, args.metadata, args.manifest)
|
||||
print(original.canonical(dict(complete=True, output=str(args.output), fixtures=result['fixture_count'])), flush=True)
|
||||
@@ -0,0 +1,109 @@
|
||||
"""Aggregate measured replay-only results; never estimate unmeasured full-training acceleration."""
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import statistics
|
||||
import subprocess
|
||||
|
||||
BASE = Path('/home/qishizhe/phase4ar-v100-acceleration-20261001')
|
||||
SOURCE = Path(__file__).resolve().parent
|
||||
|
||||
def read(path): return json.loads(Path(path).read_text())
|
||||
def sha(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as f:
|
||||
for c in iter(lambda: f.read(8 << 20), b''): h.update(c)
|
||||
return h.hexdigest()
|
||||
def save(path, data):
|
||||
with Path(path).open('x') as f: json.dump(data, f, indent=2, sort_keys=True, allow_nan=False)
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('--run', action='append', required=True)
|
||||
a = p.parse_args()
|
||||
assert len(a.run) == len(set(a.run)) == 3
|
||||
integrity = read(BASE / 'integrity-after-gpu.json')
|
||||
assert integrity['status'] == 'PASS'
|
||||
devices = []
|
||||
pins = set()
|
||||
for name in a.run:
|
||||
path = BASE / name
|
||||
assert path.parent == BASE and path.is_dir()
|
||||
s = read(path / 'summary.json')
|
||||
assert s['status'] == 'PASS-ELIGIBILITY-UPDATE-REPLAY-EQUIVALENCE'
|
||||
assert s['fixtures'] == 30 and s['rejected_invalid_cases'] == 6 and s['all_fixture_repeats_bitwise_exact']
|
||||
process = read(BASE / 'jobs' / (name + '.exit.json'))
|
||||
assert process['observed_exit'] and process['exit_code'] == 0 and not process['timed_out']
|
||||
pins.add(s['candidate_commit'])
|
||||
real = [read(f) for f in sorted(path.glob('fixtures--*.json'))]
|
||||
assert len(real) == 14
|
||||
medians = [r['summaries']['replay_wall_including_preparation_and_comparison_seconds']['median'] for r in real]
|
||||
kernels = [statistics.median(t['kernel_seconds'] for t in r['resident_timing']['resident_kernel_samples']) for r in real]
|
||||
cpu = [r['reference_timing']['warm_update_seconds'] for r in real]
|
||||
cpu_cold = [r['reference_timing']['cold_update_seconds'] for r in real]
|
||||
devices.append(dict(run=name, device=s['device'], real_fixture_count=len(real),
|
||||
median_real_fixture_cpu_original_update_api_seconds=statistics.median(cpu),
|
||||
median_real_fixture_cpu_cold_update_api_seconds=statistics.median(cpu_cold),
|
||||
median_real_fixture_candidate_replay_seconds=statistics.median(medians),
|
||||
median_real_fixture_resident_kernel_seconds=statistics.median(kernels),
|
||||
mean_real_fixture_candidate_replay_seconds=statistics.mean(medians),
|
||||
original_update_api_to_candidate_replay_ratio=statistics.median([x/y for x,y in zip(cpu,medians)]),
|
||||
ratio_warning='Different API overhead boundaries: original U checks/AST every call; candidate authenticates sources/mapping once. NOT pure CPU/GPU hardware ratio.',
|
||||
cpu_baseline_sample_warning='One cold plus ONE warm original API sample per fixture; GPU 3 warmups +20 repeats per fixture.',
|
||||
first_use_compile_seconds=real[0]['first_call_timing']['cold_compile_seconds'],
|
||||
context_initialization_seconds=s['device']['initialization_seconds'],
|
||||
observed_cuda_pool_reserved_peak_bytes=s['observed_cuda_pool_reserved_peak_bytes'],
|
||||
positive_fixtures=30, invalid_inputs_rejected=6, bitwise_exact=True,
|
||||
benchmark_wall_seconds=s['wall_seconds'], result_sha256=sha(path / 'summary.json')))
|
||||
assert len(pins) == 1, 'GPU runs used different candidate commits'
|
||||
summary = dict(status='PASS-ELIGIBILITY-UPDATE-REPLAY-EQUIVALENCE',
|
||||
created_utc=datetime.now(timezone.utc).isoformat(), benchmark_candidate_commit=next(iter(pins)),
|
||||
report_code_commit=subprocess.check_output(['git','-C',str(SOURCE),'rev-parse','HEAD'],text=True).strip(),
|
||||
devices=devices, frozen_integrity=integrity,
|
||||
scientific_experiment_status='STOPPED, unchanged:1033/30000 CPU-verified training epochs and138/3920 probes',
|
||||
original_experiment_resumed=False, full_training_acceleration_measured=False, weights_installed=False,
|
||||
full_brain_gpu_event_equivalence_tested=False, learned_candidate_created=False,
|
||||
limitations=['Replay module only, not a production training backend',
|
||||
'The sampled committed prefix covers7arms but only available physiological/PAM15/reinforce_A subset',
|
||||
'Repeated kernel calculations reset state and replay identical saved inputs, not additional learning trials',
|
||||
'Original CPU verification remains independent and required',
|
||||
'No simultaneous two-V100 training/scheduling benchmark; devices tested separately',
|
||||
'Original9.07-day estimate is not replaced by this component benchmark'],
|
||||
fixes_preserved=['Initial candidate pip22 lacked--report; upgraded pip only in new venv',
|
||||
'First GPU compile rejected conflictingFTZ options; no kernel executed; explicit nvcc compilation retains original precision'],
|
||||
next_work='Separately validate persistent training/update/verification workers and complete chain timing before authorizing a new scientific execution version')
|
||||
save(BASE / 'final-summary.json', summary)
|
||||
lines = ['# V100 conditioning acceleration — engineering replay result', '',
|
||||
'Status: **PASS-ELIGIBILITY-UPDATE-REPLAY-EQUIVALENCE**. This is not a learning result or a production-training promotion.', '',
|
||||
f'Benchmark code commit: `{next(iter(pins))}`.', '',
|
||||
'| Device | Real-fixture replay median (prep + transfers + comparison) | Resident CUDA kernel median |',
|
||||
'|---|---:|---:|']
|
||||
for d in devices:
|
||||
lines.append(f"| {d['device']['runtime_name']} ({d['run']}) | {d['median_real_fixture_candidate_replay_seconds']*1000:.3f} ms | {d['median_real_fixture_resident_kernel_seconds']*1000:.3f} ms |")
|
||||
lines += ['', 'Each GPU passed14sealed real fixtures +16fixed synthetic cases, with sampled trace, final trace, allUS snapshots and delta byte-identical to the original independent CPU oracle. Six invalid inputs were rejected on each GPU.', '',
|
||||
'CPU warm reference includes the original API\'s repeated provenance checks and AST parsing; it is only one warm sample perfixture. GPU authenticates the source and complete anatomical mapping once. Therefore ratios in JSON describe API implementation replay, not pure hardware acceleration.', '',
|
||||
'The CUDA kernels preserve every timestep, float32 separate round-to-nearest operations, exact US timing, noUS zeros, compartment/frozen/D0 identity and the depression floor. No gain/learning-rate/tau/threshold/connectome/sign changes. No dense time×neuron matrix.', '',
|
||||
'A new candidate-only CuPy environment and explicit CUDA12.6 nvcc compilation are used. Original science and ComfyUI environments are unchanged. All three ComfyUI queues were checked before each fixture; no services were stopped.', '',
|
||||
f"Integrity: {integrity['files_checked']} saved files, {integrity['bytes_checked']} bytes, {integrity['sources_checked']} registered source files checked; no mismatch. This is the saved Phase4AR inventory, not a new Phase1–4AQ numerical regression.", '',
|
||||
'Phase4AR remains stopped at1033/30000CPU-verified epochs and138/3920probes. No weights were installed and no training was resumed.', '',
|
||||
'Next: a separately validated persistent-worker pipeline and end-to-end benchmark. This local optimization does not justify dividing the9-day estimate by the kernel speedup. Independent-seed V100 parallelism is not yet measured.', '',
|
||||
'Preserved failures: candidate packaging incompatibility (--report unsupported bypip22); first CuPy compile FTZ flag conflict (before any kernel ran). Both were corrected only in the independent branch.', '',
|
||||
'Compiler references: [CuPy precompiled RawModule](https://docs.cupy.dev/en/v13.6.0/reference/generated/cupy.RawModule.html), [CUDA12.6 compiler options](https://docs.nvidia.com/cuda/archive/12.6.3/cuda-compiler-driver-nvcc/index.html).', '']
|
||||
with (BASE / 'RESULTS.md').open('x') as f: f.write('\n'.join(lines))
|
||||
# Exclude installed environment, reproducible compiler caches and final manifests themselves;
|
||||
# environment packages/wheel hashes are retained in pip-install-report + freeze.
|
||||
excluded = {'.venv'}
|
||||
files = {}
|
||||
for path in sorted(BASE.rglob('*')):
|
||||
rel = path.relative_to(BASE)
|
||||
if path.is_file() and not path.is_symlink() and not any(part in excluded for part in rel.parts):
|
||||
files[rel.as_posix()] = dict(sha256=sha(path), bytes=path.stat().st_size)
|
||||
save(BASE / 'artifact-manifest.json', dict(schema='independent-acceleration-artifacts-v1',
|
||||
code_commit=summary['report_code_commit'], source_files={p.name:sha(p) for p in SOURCE.iterdir() if p.is_file()},
|
||||
files=files, excluded=['.venv (package versions and downloaded wheel hashes are in installation receipts)'],
|
||||
no_frozen_source_modified=True, no_training_run=True))
|
||||
with (BASE / 'SHA256SUMS').open('x') as f:
|
||||
for rel, info in files.items(): f.write(info['sha256'] + ' ' + rel + '\n')
|
||||
f.write(sha(BASE/'artifact-manifest.json') + ' artifact-manifest.json\n')
|
||||
print(json.dumps(summary), flush=True)
|
||||
@@ -0,0 +1,574 @@
|
||||
"""Independent CUDA eligibility candidate; never installs weights or runs a brain.
|
||||
|
||||
The caller authenticates frozen sources, configuration, the complete KC list,
|
||||
and the candidate edge mapping. This module does not infer D from DAN activity.
|
||||
CuPy is imported only when CudaEligibility is instantiated. Set CUPY_CACHE_DIR
|
||||
to a dedicated candidate directory before doing so. The only files this module
|
||||
writes are explicit nvcc build evidence and cubins beneath that cache directory.
|
||||
|
||||
API: prepare_events(...) once, then CudaEligibility(...).run(prepared, ...).
|
||||
All commands are sampled AFTER the current tick; only the LAST command snapshot
|
||||
feeds the single epoch-boundary update. With no commands sampled_trace is +0.
|
||||
cpu_reference has the same run arguments for host-only validation, and is not a
|
||||
replacement for comparison against the SHA-pinned frozen implementation.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
COMPARTMENTS = ("B2B'2a", "a1", "y2a'1", "y5B'2a")
|
||||
_INT32_MAX = np.iinfo(np.int32).max
|
||||
CUDA_OPTIONS = ("--std=c++11", "--fmad=false", "--ftz=false")
|
||||
DEFAULT_NVCC = "/usr/local/cuda/bin/nvcc"
|
||||
CUDA_SOURCE = r'''
|
||||
extern "C" __global__
|
||||
void eligibility_trace(const long long* ptr, const int* ticks,
|
||||
const int* commands, const int n_commands,
|
||||
const int n_kc, const int n_steps, const float decay,
|
||||
float* snapshots, float* final_trace, float* sampled) {
|
||||
const int k = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
if (k >= n_kc) return;
|
||||
long long cursor = ptr[k];
|
||||
const long long end = ptr[k + 1];
|
||||
int command = 0;
|
||||
float trace = 0.0f;
|
||||
float last_sample = 0.0f;
|
||||
// Each KC follows the FULL sequential recurrence, including empty ticks.
|
||||
for (int tick = 0; tick < n_steps; ++tick) {
|
||||
float spike = 0.0f;
|
||||
if (cursor < end && ticks[cursor] == tick) {
|
||||
spike = 1.0f;
|
||||
++cursor;
|
||||
}
|
||||
trace = __fmul_rn(trace, decay);
|
||||
trace = __fadd_rn(trace, spike);
|
||||
trace = trace < 1.0f ? trace : 1.0f;
|
||||
if (command < n_commands && commands[command] == tick) {
|
||||
snapshots[(long long)command * n_kc + k] = trace;
|
||||
last_sample = trace;
|
||||
++command;
|
||||
}
|
||||
}
|
||||
final_trace[k] = trace;
|
||||
sampled[k] = last_sample;
|
||||
}
|
||||
|
||||
extern "C" __global__
|
||||
void eligibility_delta(const float* sampled, const int* source_local,
|
||||
const unsigned char* selected, const float* delta,
|
||||
const float* base, const int n_edges,
|
||||
const float negative_eta_times_d,
|
||||
const float negative_floor, const int nonzero_d,
|
||||
const int frozen, float* output) {
|
||||
const int edge = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
if (edge >= n_edges) return;
|
||||
if (frozen) {
|
||||
output[edge] = delta[edge];
|
||||
return;
|
||||
}
|
||||
float update = 0.0f;
|
||||
if (nonzero_d && selected[edge])
|
||||
update = __fmul_rn(negative_eta_times_d, sampled[source_local[edge]]);
|
||||
const float out = __fadd_rn(delta[edge], update);
|
||||
const float lower = __fmul_rn(negative_floor, base[edge]);
|
||||
// np.maximum chooses its SECOND operand on equal finite values, including
|
||||
// +0/-0. CUDA fmaxf is deliberately not substituted for that tie behavior.
|
||||
output[edge] = out > lower ? out : lower;
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
def _file_sha256(path: Path) -> str:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as stream:
|
||||
for block in iter(lambda: stream.read(1024 * 1024), b""):
|
||||
digest.update(block)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def _save_json_new(path: Path, value: Any) -> None:
|
||||
with path.open("x", encoding="utf-8", newline="\n") as stream:
|
||||
json.dump(value, stream, sort_keys=True, indent=2, allow_nan=False)
|
||||
stream.write("\n")
|
||||
|
||||
|
||||
def _nvcc_cubin(cache_root: Path, capability: str, nvcc_path: Path) -> tuple[Path, dict, dict]:
|
||||
"""Compile outside CuPy's compiler path, which injects -ftz=true in 13.6.
|
||||
|
||||
A cache entry is immutable. Failed/incomplete entries are retained and cause
|
||||
an error on reuse; the caller can select a fresh candidate cache directory.
|
||||
Only the subprocess's temporary-directory environment is changed.
|
||||
"""
|
||||
probe_started = time.perf_counter()
|
||||
_require(capability.isdigit() and 2 <= len(capability) <= 3, "invalid CUDA compute capability")
|
||||
_require(cache_root.is_absolute(), "candidate cache directory must be absolute")
|
||||
_require(nvcc_path.is_absolute() and nvcc_path.is_file(), "nvcc must be an existing absolute compiler path")
|
||||
_require(not any(os.environ.get(key, "").strip()
|
||||
for key in ("NVCC_PREPEND_FLAGS", "NVCC_APPEND_FLAGS")),
|
||||
"NVCC injected flags are incompatible with explicit candidate compiler options")
|
||||
cache_root = cache_root.resolve()
|
||||
nvcc_path = nvcc_path.resolve()
|
||||
version = subprocess.run([str(nvcc_path), "--version"], capture_output=True, text=True,
|
||||
timeout=30, check=False)
|
||||
_require(version.returncode == 0, "nvcc --version failed: " + version.stderr)
|
||||
options = ("--cubin", "-arch=sm_" + capability, *CUDA_OPTIONS, "--keep")
|
||||
identity = dict(schema="conditioning-cuda-nvcc-build-v1",
|
||||
source_sha256=hashlib.sha256(CUDA_SOURCE.encode("utf-8")).hexdigest(),
|
||||
nvcc_path=str(nvcc_path), nvcc_sha256=_file_sha256(nvcc_path),
|
||||
nvcc_version_stdout=version.stdout, nvcc_version_stderr=version.stderr,
|
||||
options=list(options), compute_capability=capability,
|
||||
nvcc_ccbin=os.environ.get("NVCC_CCBIN", ""))
|
||||
key = hashlib.sha256(json.dumps(identity, sort_keys=True, separators=(",", ":")).encode()).hexdigest()
|
||||
build_dir = cache_root / "eligibility-nvcc" / key
|
||||
_require(not build_dir.is_symlink() and build_dir.resolve().is_relative_to(cache_root),
|
||||
"candidate build cache path escapes the requested directory")
|
||||
cubin = build_dir / "eligibility.cubin"
|
||||
receipt_path = build_dir / "build-receipt.json"
|
||||
probe_seconds = time.perf_counter() - probe_started
|
||||
if build_dir.exists():
|
||||
_require(receipt_path.is_file(), "incomplete nvcc candidate build retained: " + str(build_dir))
|
||||
receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
|
||||
_require(receipt.get("complete") is True and receipt["identity"] == identity,
|
||||
"failed or mismatched nvcc candidate build retained: " + str(build_dir))
|
||||
for name, expected in receipt["files_sha256"].items():
|
||||
path = build_dir / name
|
||||
_require(path.name == name and not path.is_symlink()
|
||||
and path.resolve().is_relative_to(build_dir)
|
||||
and _file_sha256(path) == expected, "nvcc cache artifact changed: " + name)
|
||||
_require(receipt["files_sha256"].get("eligibility.cubin") == _file_sha256(cubin)
|
||||
and receipt["files_sha256"].get("eligibility.cu") == identity["source_sha256"],
|
||||
"nvcc cache lacks authenticated source/cubin")
|
||||
return cubin, dict(cache_key=key, cache_directory=str(build_dir), cache_hit=True,
|
||||
receipt_sha256=_file_sha256(receipt_path), **receipt), dict(
|
||||
compiler_probe_seconds=probe_seconds, nvcc_compile_seconds=0.0)
|
||||
build_dir.mkdir(parents=True, exist_ok=False)
|
||||
source_path = build_dir / "eligibility.cu"
|
||||
with source_path.open("x", encoding="utf-8", newline="\n") as stream:
|
||||
stream.write(CUDA_SOURCE)
|
||||
command = [str(nvcc_path), *options, "--keep-dir", str(build_dir),
|
||||
str(source_path), "-o", str(cubin)]
|
||||
_save_json_new(build_dir / "compile-command.json", dict(argv=command, cwd=str(build_dir),
|
||||
temp_directory=str(build_dir), inherited_nvcc_injected_flags=False))
|
||||
_save_json_new(build_dir / "compiler-identity.json", identity)
|
||||
environment = dict(os.environ, TMPDIR=str(build_dir), TMP=str(build_dir), TEMP=str(build_dir))
|
||||
compile_started = time.perf_counter()
|
||||
returncode = None
|
||||
failure = None
|
||||
try:
|
||||
with (build_dir / "compiler.stdout.log").open("xb") as stdout, \
|
||||
(build_dir / "compiler.stderr.log").open("xb") as stderr:
|
||||
process = subprocess.run(command, cwd=build_dir, env=environment,
|
||||
stdout=stdout, stderr=stderr, timeout=120, check=False)
|
||||
returncode = process.returncode
|
||||
except (OSError, subprocess.TimeoutExpired) as exc:
|
||||
failure = f"{type(exc).__name__}: {exc}"
|
||||
compile_seconds = time.perf_counter() - compile_started
|
||||
complete = returncode == 0 and cubin.is_file() and cubin.stat().st_size > 0
|
||||
receipt = dict(complete=complete, identity=identity, command=command,
|
||||
returncode=returncode, failure=failure,
|
||||
nvcc_compile_seconds=compile_seconds,
|
||||
files_sha256={path.name: _file_sha256(path) for path in sorted(build_dir.iterdir())
|
||||
if path.is_file() and not path.is_symlink()})
|
||||
_save_json_new(receipt_path, receipt)
|
||||
if not complete:
|
||||
raise RuntimeError("explicit nvcc candidate compilation failed; evidence retained at " + str(build_dir))
|
||||
return cubin, dict(cache_key=key, cache_directory=str(build_dir), cache_hit=False,
|
||||
receipt_sha256=_file_sha256(receipt_path), **receipt), dict(
|
||||
compiler_probe_seconds=probe_seconds, nvcc_compile_seconds=compile_seconds)
|
||||
|
||||
|
||||
def _require(condition: Any, message: str) -> None:
|
||||
if not condition:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def _integer(value: Any, name: str, minimum: int = 1) -> int:
|
||||
_require(isinstance(value, (int, np.integer)) and not isinstance(value, (bool, np.bool_)),
|
||||
f"{name} must be an integer")
|
||||
_require(minimum <= int(value) <= _INT32_MAX, f"{name} outside supported int32 range")
|
||||
return int(value)
|
||||
|
||||
|
||||
def _array(value: Any, dtype: Any, name: str) -> np.ndarray:
|
||||
_require(isinstance(value, np.ndarray) and value.ndim == 1 and value.dtype == np.dtype(dtype),
|
||||
f"{name} must be a one-dimensional {np.dtype(dtype)} ndarray")
|
||||
return value
|
||||
|
||||
|
||||
def _owned(value: np.ndarray) -> np.ndarray:
|
||||
result = np.array(value, copy=True, order="C")
|
||||
result.setflags(write=False)
|
||||
return result
|
||||
|
||||
|
||||
def _scalar(value: Any, name: str) -> float:
|
||||
_require(isinstance(value, (float, int, np.floating, np.integer))
|
||||
and not isinstance(value, (bool, np.bool_)), f"{name} must be a real scalar")
|
||||
try:
|
||||
result = float(value)
|
||||
except (ValueError, OverflowError) as exc:
|
||||
raise ValueError(f"{name} must be a finite scalar") from exc
|
||||
_require(math.isfinite(result), f"{name} must be finite")
|
||||
return result
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PreparedEvents:
|
||||
kc: np.ndarray
|
||||
indptr: np.ndarray
|
||||
ticks: np.ndarray
|
||||
command_steps: np.ndarray
|
||||
steps: int
|
||||
n_neurons: int
|
||||
input_event_count: int
|
||||
preparation_seconds: float
|
||||
|
||||
@property
|
||||
def kc_event_count(self) -> int:
|
||||
return len(self.ticks)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class EligibilityResult:
|
||||
sampled_trace: np.ndarray
|
||||
final_trace: np.ndarray
|
||||
snapshots: np.ndarray
|
||||
delta_after: np.ndarray
|
||||
timing: dict[str, Any]
|
||||
audit: dict[str, Any]
|
||||
|
||||
|
||||
def prepare_events(step: np.ndarray, neuron_idx: np.ndarray, kc: np.ndarray,
|
||||
steps: int, command_steps: Any, *, n_neurons: int = 166700) -> PreparedEvents:
|
||||
"""Validate original sparse events and pack sorted per-KC event CSR on CPU.
|
||||
|
||||
Inputs must be sorted by (tick, global neuron ID), unique and int32. No
|
||||
[steps, neurons] raster is allocated. Original input storage is not retained.
|
||||
Empty, one, or multiple sorted unique command ticks are supported.
|
||||
"""
|
||||
started = time.perf_counter()
|
||||
steps = _integer(steps, "steps")
|
||||
n_neurons = _integer(n_neurons, "n_neurons")
|
||||
step = _array(step, np.int32, "step")
|
||||
neuron_idx = _array(neuron_idx, np.int32, "neuron_idx")
|
||||
kc = _array(kc, np.int32, "kc")
|
||||
_require(0 < len(kc) <= _INT32_MAX and np.all((kc >= 0) & (kc < n_neurons)),
|
||||
"KC IDs empty or outside graph")
|
||||
_require(np.all(kc[1:] > kc[:-1]), "KC IDs must be sorted unique global IDs")
|
||||
_require(len(step) == len(neuron_idx), "event columns have different lengths")
|
||||
_require(np.all((step >= 0) & (step < steps)), "event tick outside trial")
|
||||
_require(np.all((neuron_idx >= 0) & (neuron_idx < n_neurons)), "event neuron outside graph")
|
||||
_require(np.all((step[1:] > step[:-1]) |
|
||||
((step[1:] == step[:-1]) & (neuron_idx[1:] > neuron_idx[:-1]))),
|
||||
"events must be sorted by tick/global ID and unique")
|
||||
commands = np.asarray(command_steps)
|
||||
_require(commands.ndim == 1, "command_steps must be one-dimensional")
|
||||
if commands.size == 0:
|
||||
commands = np.empty(0, np.int32)
|
||||
_require(commands.dtype.kind in "iu", "command_steps must be integers")
|
||||
_require(np.all((commands >= 0) & (commands < steps)), "command tick outside trial")
|
||||
_require(np.all(commands[1:] > commands[:-1]), "command_steps must be sorted unique")
|
||||
local = np.searchsorted(kc, neuron_idx)
|
||||
keep = (local < len(kc)) & (kc[np.minimum(local, len(kc) - 1)] == neuron_idx)
|
||||
local = local[keep]
|
||||
order = np.argsort(local, kind="stable")
|
||||
ticks = step[keep][order]
|
||||
counts = np.bincount(local, minlength=len(kc)).astype(np.int64, copy=False)
|
||||
ptr = np.empty(len(kc) + 1, np.int64)
|
||||
ptr[0] = 0
|
||||
np.cumsum(counts, out=ptr[1:])
|
||||
return PreparedEvents(_owned(kc), _owned(ptr), _owned(ticks),
|
||||
_owned(commands.astype(np.int32)), steps, n_neurons,
|
||||
len(step), time.perf_counter() - started)
|
||||
|
||||
|
||||
def _validate_prepared(prepared: PreparedEvents) -> None:
|
||||
_require(isinstance(prepared, PreparedEvents), "prepared must come from prepare_events")
|
||||
_integer(prepared.steps, "steps")
|
||||
_integer(prepared.n_neurons, "n_neurons")
|
||||
kc = _array(prepared.kc, np.int32, "prepared.kc")
|
||||
ptr = _array(prepared.indptr, np.int64, "prepared.indptr")
|
||||
ticks = _array(prepared.ticks, np.int32, "prepared.ticks")
|
||||
commands = _array(prepared.command_steps, np.int32, "prepared.command_steps")
|
||||
_require(0 < len(kc) <= _INT32_MAX and np.all((kc >= 0) & (kc < prepared.n_neurons))
|
||||
and np.all(kc[1:] > kc[:-1]), "invalid prepared KC IDs")
|
||||
_require(len(ptr) == len(kc) + 1 and ptr[0] == 0 and ptr[-1] == len(ticks)
|
||||
and np.all(ptr[1:] >= ptr[:-1]), "invalid prepared CSR offsets")
|
||||
_require(np.all((ticks >= 0) & (ticks < prepared.steps)), "invalid prepared event ticks")
|
||||
# A decrease/equality is permitted only at a CSR row boundary. Checking all
|
||||
# adjacent pairs stays vectorized and also catches a forged PreparedEvents.
|
||||
nonincreasing = ticks[1:] <= ticks[:-1]
|
||||
if len(ticks) > 1:
|
||||
boundaries = ptr[1:-1]
|
||||
boundaries = boundaries[(boundaries > 0) & (boundaries < len(ticks))] - 1
|
||||
nonincreasing[boundaries] = False
|
||||
_require(not np.any(nonincreasing), "prepared KC ticks must be sorted unique")
|
||||
_require(np.all((commands >= 0) & (commands < prepared.steps))
|
||||
and np.all(commands[1:] > commands[:-1]), "invalid prepared command ticks")
|
||||
|
||||
|
||||
def _validate_run(prepared, candidate_sources, candidate_compartments, compartment,
|
||||
delta_before, base_candidate, d, frozen, eta_mv, floor_fraction, decay):
|
||||
_validate_prepared(prepared)
|
||||
sources = _array(candidate_sources, np.int32, "candidate_sources")
|
||||
delta = _array(delta_before, np.float32, "delta_before")
|
||||
base = _array(base_candidate, np.float32, "base_candidate")
|
||||
comps = candidate_compartments
|
||||
_require(isinstance(comps, np.ndarray) and comps.ndim == 1 and comps.dtype.kind == "U",
|
||||
"candidate_compartments must be a Unicode vector")
|
||||
_require(len(delta) <= _INT32_MAX and len(sources) == len(delta) == len(base) == len(comps),
|
||||
"candidate columns have different lengths or exceed int32 capacity")
|
||||
_require(compartment in COMPARTMENTS and np.all(np.isin(comps, COMPARTMENTS)),
|
||||
"unrecognized exact frozen compartment")
|
||||
local = np.searchsorted(prepared.kc, sources)
|
||||
_require(np.all(local < len(prepared.kc)), "all candidate sources must be canonical KCs")
|
||||
_require(np.all(prepared.kc[local] == sources), "all candidate sources must be canonical KCs")
|
||||
d = _scalar(d, "D")
|
||||
_require(d in (0.0, 1.0), "D must be the fixed artificial scalar 0 or 1")
|
||||
_require(isinstance(frozen, (bool, np.bool_)), "frozen must be Boolean")
|
||||
eta = _scalar(eta_mv, "eta_mv")
|
||||
floor = _scalar(floor_fraction, "floor_fraction")
|
||||
decay_value = _scalar(decay, "decay")
|
||||
_require(0 < eta <= np.finfo(np.float32).max, "eta_mv must be positive finite float32 representable")
|
||||
_require(0 < floor <= 1, "floor_fraction must lie in (0,1]")
|
||||
_require(0 < decay_value <= 1, "decay must lie in (0,1]")
|
||||
_require(np.float32(eta) > 0 and np.float32(floor) > 0 and np.float32(decay_value) > 0,
|
||||
"rule scalar underflows float32")
|
||||
_require(np.all(np.isfinite(base)) and np.all(base > 0),
|
||||
"original base must be finite positive float32 mV")
|
||||
lower = np.float32(-floor) * base
|
||||
_require(np.all(np.isfinite(delta)) and np.all((delta >= lower) & (delta <= 0)),
|
||||
"delta violates original frozen floor")
|
||||
_require(not np.any((delta == 0) & np.signbit(delta)), "delta zero must be canonical +0")
|
||||
return dict(local=np.array(local, dtype=np.int32, order="C"),
|
||||
selected=np.asarray(comps == compartment, dtype=np.uint8),
|
||||
delta=np.array(delta, copy=True, order="C"),
|
||||
base=np.array(base, copy=True, order="C"), d=d, frozen=bool(frozen),
|
||||
eta=eta, floor=floor, decay=decay_value,
|
||||
negative_eta_times_d=np.float32(-eta * d), negative_floor=np.float32(-floor))
|
||||
|
||||
|
||||
def _audit(prepared: PreparedEvents, work: dict, backend: str) -> dict[str, Any]:
|
||||
return dict(backend=backend, steps=prepared.steps, kc_count=len(prepared.kc),
|
||||
events=prepared.input_event_count, actual_kc_events=prepared.kc_event_count,
|
||||
command_count=len(prepared.command_steps), candidate_count=len(work["base"]),
|
||||
d_command=work["d"], frozen=work["frozen"], eta_mv=work["eta"],
|
||||
floor_fraction=work["floor"], decay_python_float=work["decay"],
|
||||
decay_float32_bits=int(np.asarray(np.float32(work["decay"])).view(np.uint32)),
|
||||
initial_trace="float32 canonical +0", sampling="after_current_tick_spike",
|
||||
update_sample="last command snapshot, or canonical +0 without commands",
|
||||
trace_tick_skipping=False, dense_tick_neuron_raster=False,
|
||||
original_source_executed=False, caller_must_verify_source_identity=True,
|
||||
source_identity_verified_by_this_module=False,
|
||||
complete_mapping_verified_by_this_module=False,
|
||||
d_semantics="artificial scheduled command; not measured DAN activity",
|
||||
actual_dan_activity_used_to_gate=False, brain_dynamics_executed=False,
|
||||
training_executed=False, weights_installed=False, learning_pass_claimed=False)
|
||||
|
||||
|
||||
def cpu_reference(prepared: PreparedEvents, candidate_sources: np.ndarray,
|
||||
candidate_compartments: np.ndarray, compartment: str,
|
||||
delta_before: np.ndarray, base_candidate: np.ndarray, *, d: float,
|
||||
frozen: bool, eta_mv: float, floor_fraction: float, decay: float) -> EligibilityResult:
|
||||
"""Host arithmetic mirror for tests; frozen-source validation is external."""
|
||||
started = time.perf_counter()
|
||||
work = _validate_run(prepared, candidate_sources, candidate_compartments, compartment,
|
||||
delta_before, base_candidate, d, frozen, eta_mv, floor_fraction, decay)
|
||||
nkc = len(prepared.kc)
|
||||
trace = np.zeros(nkc, np.float32)
|
||||
snapshots = np.empty((len(prepared.command_steps), nkc), np.float32)
|
||||
positions = prepared.indptr[:-1].copy()
|
||||
ends = prepared.indptr[1:]
|
||||
spike = np.zeros(nkc, np.float32)
|
||||
command = 0
|
||||
for tick in range(prepared.steps):
|
||||
spike.fill(0)
|
||||
active = np.flatnonzero(positions < ends)
|
||||
active = active[prepared.ticks[positions[active]] == tick]
|
||||
spike[active] = np.float32(1)
|
||||
positions[active] += 1
|
||||
np.multiply(trace, np.float32(work["decay"]), out=trace)
|
||||
np.add(trace, spike, out=trace)
|
||||
np.minimum(trace, np.float32(1), out=trace)
|
||||
if command < len(prepared.command_steps) and prepared.command_steps[command] == tick:
|
||||
snapshots[command] = trace
|
||||
command += 1
|
||||
sampled = snapshots[-1].copy() if len(snapshots) else np.zeros(nkc, np.float32)
|
||||
output = work["delta"].copy()
|
||||
if not work["frozen"]:
|
||||
update = np.zeros(len(output), np.float32)
|
||||
selected = work["selected"].astype(bool)
|
||||
if work["d"] != 0:
|
||||
update[selected] = work["negative_eta_times_d"] * sampled[work["local"][selected]]
|
||||
output = output + update
|
||||
output = np.maximum(output, work["negative_floor"] * work["base"]).astype(np.float32)
|
||||
return EligibilityResult(_owned(sampled), _owned(trace), _owned(snapshots), _owned(output),
|
||||
dict(end_to_end_seconds=time.perf_counter() - started,
|
||||
preparation_seconds=prepared.preparation_seconds),
|
||||
_audit(prepared, work, "numpy-host-math-mirror"))
|
||||
|
||||
|
||||
class CudaEligibility:
|
||||
"""Explicit nvcc cubin, loaded by CuPy, with separate float32 rounding.
|
||||
|
||||
Use a dedicated environment and set an absolute CUPY_CACHE_DIR outside any
|
||||
frozen tree before construction. The first run builds or authenticates one
|
||||
nvcc cubin and loads its kernels with RawModule(path=...). CuPy's compiler
|
||||
is not called, so it cannot inject an incompatible FTZ option. Cold timing
|
||||
separates nvcc compilation, compiler probing and driver module loading.
|
||||
run includes validation, transfers and output ownership in end-to-end wall.
|
||||
"""
|
||||
|
||||
def __init__(self, device_index: int = 0, *, nvcc_path: str = DEFAULT_NVCC):
|
||||
started = time.perf_counter()
|
||||
self.device_index = _integer(device_index, "device_index", 0)
|
||||
cache_dir = os.environ.get("CUPY_CACHE_DIR", "")
|
||||
_require(bool(cache_dir) and Path(cache_dir).is_absolute(),
|
||||
"set CUPY_CACHE_DIR to an absolute candidate cache directory outside frozen trees")
|
||||
self.cache_root = Path(cache_dir)
|
||||
self.nvcc_path = Path(nvcc_path)
|
||||
try:
|
||||
import cupy as cp
|
||||
except ImportError as exc:
|
||||
raise RuntimeError("CuPy unavailable; use the dedicated CUDA candidate environment") from exc
|
||||
self.cp = cp
|
||||
self.device = cp.cuda.Device(self.device_index)
|
||||
with self.device:
|
||||
self.stream = cp.cuda.Stream(non_blocking=True)
|
||||
self.device.synchronize()
|
||||
self.initialization_seconds = time.perf_counter() - started
|
||||
self._compiled = False
|
||||
|
||||
def run(self, prepared: PreparedEvents, candidate_sources: np.ndarray,
|
||||
candidate_compartments: np.ndarray, compartment: str,
|
||||
delta_before: np.ndarray, base_candidate: np.ndarray, *, d: float,
|
||||
frozen: bool, eta_mv: float, floor_fraction: float, decay: float,
|
||||
kernel_warmup: int = 0, kernel_repeats: int = 1) -> EligibilityResult:
|
||||
"""Transfer one fixture and optionally benchmark resident kernel repeats.
|
||||
|
||||
Each repeat starts from zero trace and the SAME delta_before; repeats
|
||||
never accumulate training updates. CUDA timing fields are medians across
|
||||
kernel_repeats. end_to_end_seconds includes all warmups and repeats, so
|
||||
use default counts for a single-call end-to-end benchmark.
|
||||
"""
|
||||
started = time.perf_counter()
|
||||
work = _validate_run(prepared, candidate_sources, candidate_compartments, compartment,
|
||||
delta_before, base_candidate, d, frozen, eta_mv, floor_fraction, decay)
|
||||
kernel_warmup = _integer(kernel_warmup, "kernel_warmup", 0)
|
||||
kernel_repeats = _integer(kernel_repeats, "kernel_repeats")
|
||||
validation_seconds = time.perf_counter() - started
|
||||
cp = self.cp
|
||||
first_run = not self._compiled
|
||||
compile_seconds = 0.0
|
||||
compilation_timing = dict(compiler_probe_seconds=0.0, nvcc_compile_seconds=0.0,
|
||||
module_load_seconds=0.0)
|
||||
with self.device, self.stream:
|
||||
if first_run:
|
||||
compile_started = time.perf_counter()
|
||||
cubin, self.compilation_audit, probe_timing = _nvcc_cubin(
|
||||
self.cache_root, str(self.device.compute_capability), self.nvcc_path)
|
||||
compilation_timing.update(probe_timing)
|
||||
load_started = time.perf_counter()
|
||||
self.module = cp.RawModule(path=str(cubin))
|
||||
self.trace_kernel = self.module.get_function("eligibility_trace")
|
||||
self.delta_kernel = self.module.get_function("eligibility_delta")
|
||||
self.stream.synchronize()
|
||||
compilation_timing["module_load_seconds"] = time.perf_counter() - load_started
|
||||
compile_seconds = time.perf_counter() - compile_started
|
||||
self._compiled = True
|
||||
transfer_started = time.perf_counter()
|
||||
ptr_gpu, ticks_gpu, commands_gpu, local_gpu, selected_gpu, delta_gpu, base_gpu = [
|
||||
cp.asarray(a) for a in (prepared.indptr, prepared.ticks, prepared.command_steps,
|
||||
work["local"], work["selected"], work["delta"], work["base"])]
|
||||
nkc, nedges = len(prepared.kc), len(work["delta"])
|
||||
snapshots_gpu = cp.empty((len(prepared.command_steps), nkc), cp.float32)
|
||||
final_gpu = cp.empty(nkc, cp.float32)
|
||||
sampled_gpu = cp.empty(nkc, cp.float32)
|
||||
output_gpu = cp.empty(nedges, cp.float32)
|
||||
self.stream.synchronize()
|
||||
upload_seconds = time.perf_counter() - transfer_started
|
||||
trace_args = (
|
||||
ptr_gpu, ticks_gpu, commands_gpu, np.int32(len(prepared.command_steps)),
|
||||
np.int32(nkc), np.int32(prepared.steps), np.float32(work["decay"]),
|
||||
snapshots_gpu, final_gpu, sampled_gpu)
|
||||
delta_args = (
|
||||
sampled_gpu, local_gpu, selected_gpu, delta_gpu, base_gpu,
|
||||
np.int32(nedges), work["negative_eta_times_d"], work["negative_floor"],
|
||||
np.int32(work["d"] != 0), np.int32(work["frozen"]), output_gpu)
|
||||
|
||||
def launch_pair():
|
||||
self.trace_kernel(((nkc + 127) // 128,), (128,), trace_args)
|
||||
if nedges:
|
||||
self.delta_kernel(((nedges + 255) // 256,), (256,), delta_args)
|
||||
|
||||
for _ in range(kernel_warmup):
|
||||
launch_pair()
|
||||
self.stream.synchronize()
|
||||
resident_samples = []
|
||||
for _ in range(kernel_repeats):
|
||||
trace_start, trace_end, update_end = cp.cuda.Event(), cp.cuda.Event(), cp.cuda.Event()
|
||||
trace_start.record(self.stream)
|
||||
self.trace_kernel(((nkc + 127) // 128,), (128,), trace_args)
|
||||
trace_end.record(self.stream)
|
||||
if nedges:
|
||||
self.delta_kernel(((nedges + 255) // 256,), (256,), delta_args)
|
||||
update_end.record(self.stream)
|
||||
update_end.synchronize()
|
||||
resident_samples.append(dict(
|
||||
trace_kernel_seconds=cp.cuda.get_elapsed_time(trace_start, trace_end) / 1000.0,
|
||||
update_kernel_seconds=cp.cuda.get_elapsed_time(trace_end, update_end) / 1000.0,
|
||||
kernel_seconds=cp.cuda.get_elapsed_time(trace_start, update_end) / 1000.0))
|
||||
medians = {key: float(np.median([sample[key] for sample in resident_samples]))
|
||||
for key in resident_samples[0]}
|
||||
download_started = time.perf_counter()
|
||||
sampled, final, snapshots, output = [
|
||||
_owned(cp.asnumpy(a, stream=self.stream, blocking=True))
|
||||
for a in (sampled_gpu, final_gpu, snapshots_gpu, output_gpu)]
|
||||
download_seconds = time.perf_counter() - download_started
|
||||
guard_started = time.perf_counter()
|
||||
for name, array in (("sampled_trace", sampled), ("final_trace", final), ("snapshots", snapshots)):
|
||||
if not (np.all(np.isfinite(array)) and np.all((array >= 0) & (array <= 1))):
|
||||
raise RuntimeError(f"CUDA output guard failed: invalid {name}")
|
||||
lower = work["negative_floor"] * work["base"]
|
||||
if not (np.all(np.isfinite(output)) and np.all((output >= lower) & (output <= 0))):
|
||||
raise RuntimeError("CUDA output guard failed: delta outside finite frozen floor")
|
||||
selected = work["selected"].astype(bool)
|
||||
if output[~selected].tobytes() != work["delta"][~selected].tobytes():
|
||||
raise RuntimeError("CUDA output guard failed: off-compartment delta changed")
|
||||
if (work["frozen"] or work["d"] == 0) and output.tobytes() != work["delta"].tobytes():
|
||||
raise RuntimeError("CUDA output guard failed: frozen/zero-D identity")
|
||||
guard_seconds = time.perf_counter() - guard_started
|
||||
timing = dict(first_run=first_run, initialization_seconds=self.initialization_seconds,
|
||||
cold_compile_seconds=compile_seconds,
|
||||
**compilation_timing,
|
||||
compile_timing_semantics="first-use nvcc probe/build or authenticated cache, then driver module load",
|
||||
preparation_seconds=prepared.preparation_seconds,
|
||||
run_validation_seconds=validation_seconds,
|
||||
host_to_device_and_allocation_seconds=upload_seconds,
|
||||
**medians, device_to_host_seconds=download_seconds,
|
||||
output_guard_seconds=guard_seconds,
|
||||
resident_kernel_warmup=kernel_warmup,
|
||||
resident_kernel_repeats=kernel_repeats,
|
||||
resident_kernel_samples=resident_samples,
|
||||
kernel_statistic="median of resident timed repeats",
|
||||
end_to_end_semantics="all requested warmups/repeats and transfers; preparation excluded",
|
||||
end_to_end_seconds=time.perf_counter() - started)
|
||||
audit = _audit(prepared, work, "nvcc-cubin-cupy-independent-candidate")
|
||||
audit.update(numpy_version=str(np.__version__), cupy_version=str(cp.__version__),
|
||||
device_index=self.device_index, cuda_options=list(CUDA_OPTIONS),
|
||||
compiler_backend="external nvcc --cubin; CuPy RawModule path loading only",
|
||||
compilation=self.compilation_audit,
|
||||
float32_separate_rounding_intrinsics=True, tf32_used=False,
|
||||
numerical_equivalence_established_by_this_call=False)
|
||||
return EligibilityResult(sampled, final, snapshots, output, timing, audit)
|
||||
@@ -0,0 +1,36 @@
|
||||
"""Write new engineering child-process exit receipts; never retry a job."""
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('--label', required=True)
|
||||
p.add_argument('--timeout', type=int, default=900)
|
||||
p.add_argument('command', nargs=argparse.REMAINDER)
|
||||
a = p.parse_args()
|
||||
assert re.fullmatch(r'[a-z0-9-]+', a.label)
|
||||
assert a.command
|
||||
out = Path('/home/qishizhe/phase4ar-v100-acceleration-20261001') / 'jobs'
|
||||
out.mkdir(exist_ok=True)
|
||||
start = time.perf_counter()
|
||||
receipt = dict(command=a.command, label=a.label, started_utc=datetime.now(timezone.utc).isoformat(),
|
||||
original_experiment_resumed=False)
|
||||
with (out / (a.label + '.start.json')).open('x') as f:
|
||||
json.dump(receipt, f, indent=2)
|
||||
with (out / (a.label + '.stdout.log')).open('x') as stdout, (out / (a.label + '.stderr.log')).open('x') as stderr:
|
||||
try:
|
||||
result = subprocess.run(a.command, stdout=stdout, stderr=stderr,
|
||||
env={**os.environ, 'PYTHONDONTWRITEBYTECODE': '1'}, timeout=a.timeout)
|
||||
receipt.update(exit_code=result.returncode, observed_exit=True, timed_out=False)
|
||||
except subprocess.TimeoutExpired:
|
||||
receipt.update(exit_code=None, observed_exit=False, timed_out=True)
|
||||
receipt.update(wall_seconds=time.perf_counter()-start, finished_utc=datetime.now(timezone.utc).isoformat())
|
||||
with (out / (a.label + '.exit.json')).open('x') as f:
|
||||
json.dump(receipt, f, indent=2)
|
||||
print(json.dumps(receipt), flush=True)
|
||||
raise SystemExit(receipt['exit_code'] if receipt['observed_exit'] else 124)
|
||||
@@ -0,0 +1,22 @@
|
||||
"""Log repair of candidate-only packaging tool; preserve first failed attempt."""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
OUT = Path('/home/qishizhe/phase4ar-v100-acceleration-20261001')
|
||||
PYTHON = OUT / '.venv/bin/python'
|
||||
assert PYTHON.exists() and (OUT / 'install-candidate.stderr.log').exists()
|
||||
|
||||
def run(args, stem):
|
||||
with (OUT / (stem + '.stdout.log')).open('x') as stdout, (OUT / (stem + '.stderr.log')).open('x') as stderr:
|
||||
result = subprocess.run([str(PYTHON), '-B', '-m', 'pip', *args], stdout=stdout, stderr=stderr,
|
||||
env={**os.environ, 'PYTHONDONTWRITEBYTECODE': '1'})
|
||||
print(json.dumps({'step': stem, 'exit_code': result.returncode}), flush=True)
|
||||
if result.returncode:
|
||||
raise RuntimeError(stem)
|
||||
|
||||
run(['install', '--disable-pip-version-check', 'pip==25.2'], 'upgrade-candidate-pip')
|
||||
run(['install', '--disable-pip-version-check', '--report', str(OUT / 'pip-install-report.json'),
|
||||
'numpy==2.2.6', 'cupy-cuda12x==13.6.0'], 'install-candidate-attempt-02')
|
||||
run(['freeze'], 'candidate-freeze')
|
||||
@@ -0,0 +1,2 @@
|
||||
numpy==2.2.6
|
||||
cupy-cuda12x==13.6.0
|
||||
@@ -0,0 +1,33 @@
|
||||
"""Provision only a new worktree and independent benchmark environment."""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
ROOT=Path('/data/digital-drosophila')
|
||||
WORK=Path('/home/qishizhe/digital-drosophila-v100-acceleration')
|
||||
OUT=Path('/home/qishizhe/phase4ar-v100-acceleration-20261001')
|
||||
BASE='09187e4d4d67badf1b418c5f211258ca5d8fb328'
|
||||
|
||||
def run(argv, log):
|
||||
with (OUT/(log+'.stdout.log')).open('x') as out, (OUT/(log+'.stderr.log')).open('x') as err:
|
||||
r=subprocess.run(argv,stdout=out,stderr=err,env={**os.environ,'PYTHONDONTWRITEBYTECODE':'1'})
|
||||
print(json.dumps({'step':log,'exit_code':r.returncode}),flush=True)
|
||||
if r.returncode:raise RuntimeError('Environment preparation failed: '+log)
|
||||
|
||||
assert not WORK.exists() and not OUT.exists(), 'Provisioning targets must be new'
|
||||
assert subprocess.check_output(['git','-C',str(ROOT),'rev-parse','HEAD'],text=True).strip()==BASE
|
||||
assert subprocess.check_output(['git','-C',str(ROOT),'status','--porcelain'],text=True)==''
|
||||
OUT.mkdir()
|
||||
with (OUT/'environment-authority.json').open('x') as f:
|
||||
json.dump(dict(scope='independent engineering replay only',base_commit=BASE,
|
||||
created_utc=datetime.now(timezone.utc).isoformat(),original_science_environment_modified=False,
|
||||
original_experiment_resumed=False),f,indent=2)
|
||||
run(['git','-C',str(ROOT),'worktree','add','-b','codex/v100-conditioning-acceleration',str(WORK),BASE],'create-worktree')
|
||||
run([sys.executable,'-m','venv',str(OUT/'.venv')],'create-venv')
|
||||
run([str(OUT/'.venv/bin/python'),'-B','-m','pip','install','--disable-pip-version-check',
|
||||
'--report',str(OUT/'pip-install-report.json'),'numpy==2.2.6','cupy-cuda12x==13.6.0'],'install-candidate')
|
||||
run([str(OUT/'.venv/bin/python'),'-B','-m','pip','freeze'],'candidate-freeze')
|
||||
print(json.dumps({'worktree':str(WORK),'benchmark_root':str(OUT),'environment_ready':True}),flush=True)
|
||||
@@ -0,0 +1,135 @@
|
||||
"""Small authority/selection tests; never access or run the production brain."""
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
PATH = Path(__file__).with_name('export_fixtures.py')
|
||||
SPEC = importlib.util.spec_from_file_location('acceleration_fixture_export_tests', PATH)
|
||||
E = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(E)
|
||||
|
||||
|
||||
def task(arm, number, kind='train'):
|
||||
return dict(task_id=f'block/normal/{arm}/{number:03d}', arm=arm, kind=kind)
|
||||
|
||||
|
||||
def committed(tasks):
|
||||
return {E.task_key(t) + '--' + stage for t in tasks for stage in ('brain', 'update', 'verify')}
|
||||
|
||||
|
||||
class SelectionTests(unittest.TestCase):
|
||||
def test_fixed_first_last_all_seven_arms_before_metrics(self):
|
||||
tasks = [task(arm, n) for arm in E.ARMS for n in range(5)]
|
||||
selected, counts = E.select_tasks(list(reversed(tasks)), committed(tasks))
|
||||
self.assertEqual(len(selected), 14)
|
||||
self.assertEqual(counts, {arm: 5 for arm in E.ARMS})
|
||||
self.assertEqual([(t['arm'], t['task_id'].split('/')[-1]) for t in selected],
|
||||
[(arm, n) for arm in E.ARMS for n in ('000', '004')])
|
||||
|
||||
def test_uncommitted_last_is_not_selected(self):
|
||||
tasks = [task('paired', n) for n in range(4)]
|
||||
ids = committed(tasks)
|
||||
ids.remove(E.task_key(tasks[-1]) + '--verify')
|
||||
selected, counts = E.select_tasks(tasks, ids)
|
||||
self.assertEqual(selected, [tasks[0], tasks[2]])
|
||||
self.assertEqual(counts['paired'], 3)
|
||||
|
||||
def test_probe_and_duplicate_selection(self):
|
||||
train, probe = task('paired', 0), task('paired', 1, 'probe')
|
||||
selected, _ = E.select_tasks([train, probe], committed([train, probe]))
|
||||
self.assertEqual(selected, [train])
|
||||
with self.assertRaisesRegex(ValueError, 'Duplicate'):
|
||||
E.select_tasks([train, train], committed([train]))
|
||||
|
||||
def test_no_complete_triple_fails(self):
|
||||
train = task('paired', 0)
|
||||
with self.assertRaisesRegex(ValueError, 'No committed'):
|
||||
E.select_tasks([train], {E.task_key(train) + '--verify'})
|
||||
|
||||
|
||||
class FileSafetyTests(unittest.TestCase):
|
||||
def test_output_must_be_new_and_outside_protected(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary).resolve()
|
||||
frozen = root / 'frozen'
|
||||
frozen.mkdir()
|
||||
with self.assertRaisesRegex(ValueError, 'fresh'):
|
||||
E.validate_destination(frozen, [frozen])
|
||||
with self.assertRaisesRegex(ValueError, 'overlaps'):
|
||||
E.validate_destination(frozen / 'new', [frozen])
|
||||
self.assertEqual(E.validate_destination(root / 'allowed', [frozen]), root / 'allowed')
|
||||
self.assertFalse((root / 'allowed').exists())
|
||||
|
||||
def test_exclusive_save_and_mismatch_rejection(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
path = Path(temporary).resolve() / 'new.json'
|
||||
E.save(path, {'a': 1})
|
||||
original = path.read_bytes()
|
||||
with self.assertRaises(FileExistsError):
|
||||
E.save(path, {'a': 2})
|
||||
self.assertEqual(path.read_bytes(), original)
|
||||
with self.assertRaisesRegex(ValueError, 'Pinned bytes'):
|
||||
E.check(path, '0' * 64)
|
||||
|
||||
def test_duplicate_json_rejected(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
path = Path(temporary).resolve() / 'bad.json'
|
||||
path.write_text('{"a":1,"a":2}', encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError, 'Duplicate'):
|
||||
E.read(path)
|
||||
|
||||
|
||||
class ProcessAuthorityTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self.temp.name).resolve()
|
||||
self.name = 'task-synthetic--verify'
|
||||
self.job_path = self.root / 'jobs' / (self.name + '.json')
|
||||
self.process_path = self.root / 'receipts' / self.name / 'process.json'
|
||||
self.job_path.parent.mkdir()
|
||||
self.process_path.parent.mkdir(parents=True)
|
||||
E.save(self.job_path, dict(registration_sha256=E.REG_SHA, input_sha256={}))
|
||||
self.process = dict(entry_id=self.name, registration_sha256=E.REG_SHA,
|
||||
job_sha256=E.digest(self.job_path), complete=True, exit_code=0, timed_out=False,
|
||||
exit_observed_by_parent=True, launch_error=None, argv=[str(E.ORIGINAL_ENV / 'bin/python'), '-B', 'validator.py'])
|
||||
|
||||
def tearDown(self):
|
||||
self.temp.cleanup()
|
||||
|
||||
def verify(self, process):
|
||||
E.save(self.process_path, process)
|
||||
tracked = {str(p): E.identity(p) for p in (self.job_path, self.process_path)}
|
||||
row = dict(entry_id=self.name, metadata=dict(job_file=str(self.job_path),
|
||||
process_receipt_file=str(self.process_path), observed_returncode=0), consumed_inputs=[],
|
||||
new_outputs=[dict(path=p, **info) for p, info in tracked.items()])
|
||||
start = dict(job=dict(path=str(self.job_path), sha256=E.digest(self.job_path)))
|
||||
return E.validate_process(dict(row=row, start=start), tracked, self.root)
|
||||
|
||||
def test_observed_complete_zero_is_required(self):
|
||||
self.verify(self.process)
|
||||
|
||||
def test_failed_or_unobserved_process_rejected(self):
|
||||
self.process['exit_code'] = 1
|
||||
with self.assertRaisesRegex(ValueError, 'observed exit zero'):
|
||||
self.verify(self.process)
|
||||
|
||||
def test_boolean_zero_is_not_os_exit(self):
|
||||
self.process['exit_code'] = False
|
||||
with self.assertRaisesRegex(ValueError, 'observed exit zero'):
|
||||
self.verify(self.process)
|
||||
|
||||
def test_different_registration_rejected(self):
|
||||
self.process['registration_sha256'] = '0' * 64
|
||||
with self.assertRaisesRegex(ValueError, 'observed exit zero'):
|
||||
self.verify(self.process)
|
||||
|
||||
def test_different_interpreter_rejected(self):
|
||||
self.process['argv'][0] = '/different/venv/bin/python'
|
||||
with self.assertRaisesRegex(ValueError, 'original -B'):
|
||||
self.verify(self.process)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,315 @@
|
||||
"""Host-only tests; CUDA equality requires separate real-device evidence."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import replace
|
||||
import importlib.util
|
||||
import math
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import numpy as np
|
||||
|
||||
from gpu_backend import (CUDA_OPTIONS, CUDA_SOURCE, COMPARTMENTS, CudaEligibility, _nvcc_cubin, cpu_reference,
|
||||
prepare_events)
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PHASE4J = Path(os.environ.get("PHASE4J_SOURCE", str(ROOT / "models" / "male-cns-lif" / "phase4j.py")))
|
||||
BRIDGE_PATH = Path(os.environ.get("ELIGIBILITY_BRIDGE_SOURCE", str(ROOT / "wholebrain-plastic-interface-v1" / "eligibility_bridge.py")))
|
||||
spec = importlib.util.spec_from_file_location("_gpu_math_frozen_bridge", BRIDGE_PATH)
|
||||
bridge = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = bridge
|
||||
spec.loader.exec_module(bridge)
|
||||
|
||||
|
||||
def assert_bits(test, left, right):
|
||||
test.assertEqual(left.dtype, right.dtype)
|
||||
test.assertEqual(left.shape, right.shape)
|
||||
test.assertEqual(left.tobytes(), right.tobytes())
|
||||
|
||||
|
||||
class HostMathTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.kc = np.array([2, 5, 9], np.int32)
|
||||
self.step = np.array([0, 0, 1, 2, 2, 5, 7], np.int32)
|
||||
self.neurons = np.array([2, 4, 2, 5, 9, 9, 2], np.int32)
|
||||
self.sources = np.array([2, 2, 5, 9], np.int32)
|
||||
self.compartments = np.array([COMPARTMENTS[0], COMPARTMENTS[1],
|
||||
COMPARTMENTS[0], COMPARTMENTS[0]])
|
||||
self.base = np.array([0.001, 0.01, 0.004, 0.08], np.float32)
|
||||
self.delta = np.zeros(4, np.float32)
|
||||
self.kw = dict(d=1.0, frozen=False, eta_mv=bridge.ETA_MV,
|
||||
floor_fraction=bridge.FLOOR_FRACTION,
|
||||
decay=math.exp(-bridge.DT_MS / bridge.TAU_MS))
|
||||
|
||||
def prepared(self, commands=(0, 2, 6), steps=8):
|
||||
return prepare_events(self.step, self.neurons, self.kc, steps, commands, n_neurons=12)
|
||||
|
||||
def run_host(self, prepared=None, **overrides):
|
||||
args = self.kw | overrides
|
||||
return cpu_reference(self.prepared() if prepared is None else prepared,
|
||||
self.sources, self.compartments, COMPARTMENTS[0],
|
||||
self.delta, self.base, **args)
|
||||
|
||||
def test_matches_frozen_trace_and_update_and_no_input_mutation(self):
|
||||
arrays = (self.step, self.neurons, self.kc, self.sources,
|
||||
self.compartments, self.base, self.delta)
|
||||
before = [(a.tobytes(), a.flags.writeable) for a in arrays]
|
||||
prepared = self.prepared()
|
||||
result = self.run_host(prepared)
|
||||
trace = bridge.trace_from_events(self.step, self.neurons, self.kc, 8, [0, 2, 6],
|
||||
phase4j_source=PHASE4J, n_neurons=12)
|
||||
expected, _ = bridge.apply_eligibility(trace.last_command_trace, self.kc,
|
||||
self.sources, self.compartments, COMPARTMENTS[0], self.delta, self.base,
|
||||
d=1.0, frozen=False, phase4j_source=PHASE4J, n_neurons=12)
|
||||
for left, right in ((result.snapshots, trace.snapshots),
|
||||
(result.final_trace, trace.final),
|
||||
(result.sampled_trace, trace.last_command_trace),
|
||||
(result.delta_after, expected)):
|
||||
assert_bits(self, left, right)
|
||||
self.assertFalse(left.flags.writeable)
|
||||
self.assertEqual(before, [(a.tobytes(), a.flags.writeable) for a in arrays])
|
||||
self.assertEqual(prepared.kc_event_count, 6)
|
||||
self.assertEqual(prepared.indptr.tolist(), [0, 3, 4, 6])
|
||||
self.assertEqual(prepared.ticks.tolist(), [0, 1, 7, 2, 2, 5])
|
||||
|
||||
def test_no_command_returns_positive_zero_but_nonzero_final(self):
|
||||
result = self.run_host(self.prepared(()), d=0)
|
||||
self.assertEqual(result.snapshots.shape, (0, 3))
|
||||
assert_bits(self, result.sampled_trace, np.zeros(3, np.float32))
|
||||
self.assertTrue(np.any(result.final_trace > 0))
|
||||
assert_bits(self, result.delta_after, self.delta)
|
||||
|
||||
def test_sampling_after_spike_and_last_command_only(self):
|
||||
result = self.run_host(self.prepared((0, 2, 7)))
|
||||
self.assertEqual(result.snapshots[0, 0], np.float32(1))
|
||||
self.assertEqual(result.snapshots[1, 1], np.float32(1))
|
||||
assert_bits(self, result.sampled_trace, result.snapshots[-1])
|
||||
assert_bits(self, result.final_trace, result.snapshots[-1])
|
||||
|
||||
def test_frozen_d_zero_off_compartment_and_floor(self):
|
||||
self.delta = np.array([-0.0001, -0.0005, -0.001, 0], np.float32)
|
||||
for kwargs in (dict(d=0), dict(frozen=True)):
|
||||
assert_bits(self, self.run_host(**kwargs).delta_after, self.delta)
|
||||
result = self.run_host()
|
||||
assert_bits(self, result.delta_after[1:2], self.delta[1:2])
|
||||
self.assertEqual(result.delta_after[0], np.float32(-0.25) * self.base[0])
|
||||
self.assertEqual(result.delta_after[2], self.delta[2])
|
||||
|
||||
def test_empty_events_and_one_tick(self):
|
||||
prepared = prepare_events(np.empty(0, np.int32), np.empty(0, np.int32),
|
||||
self.kc, 1, [0], n_neurons=12)
|
||||
result = self.run_host(prepared)
|
||||
assert_bits(self, result.final_trace, np.zeros(3, np.float32))
|
||||
assert_bits(self, result.delta_after, self.delta)
|
||||
|
||||
def test_long_empty_gap_does_not_use_power(self):
|
||||
self.step = np.array([0], np.int32)
|
||||
self.neurons = np.array([2], np.int32)
|
||||
prepared = self.prepared((9999,), steps=10000)
|
||||
result = self.run_host(prepared)
|
||||
expected = np.float32(1)
|
||||
for _ in range(9999):
|
||||
expected = np.float32(expected * np.float32(self.kw["decay"]))
|
||||
assert_bits(self, result.sampled_trace[:1], np.array([expected], np.float32))
|
||||
jumped = np.float32(float(np.float32(self.kw["decay"])) ** 9999)
|
||||
self.assertNotEqual(expected.view(np.uint32), jumped.view(np.uint32))
|
||||
|
||||
def test_random_sparse_case_matches_frozen(self):
|
||||
rng = np.random.default_rng(717)
|
||||
self.kc = np.arange(0, 80, 2, dtype=np.int32)
|
||||
encoded = np.unique(rng.integers(0, 80 * 257, size=1400))
|
||||
self.step = (encoded // 80).astype(np.int32)
|
||||
self.neurons = (encoded % 80).astype(np.int32)
|
||||
self.sources = rng.choice(self.kc, 159).astype(np.int32)
|
||||
self.compartments = rng.choice(np.asarray(COMPARTMENTS), 159)
|
||||
self.base = rng.uniform(0.0001, 2, 159).astype(np.float32)
|
||||
self.delta = -(rng.uniform(0, 0.24, 159).astype(np.float32) * self.base)
|
||||
prepared = prepare_events(self.step, self.neurons, self.kc, 257, [0, 1, 20, 99, 256], n_neurons=80)
|
||||
result = self.run_host(prepared)
|
||||
trace = bridge.trace_from_events(self.step, self.neurons, self.kc, 257,
|
||||
[0, 1, 20, 99, 256], phase4j_source=PHASE4J, n_neurons=80)
|
||||
expected, _ = bridge.apply_eligibility(trace.last_command_trace, self.kc,
|
||||
self.sources, self.compartments, COMPARTMENTS[0], self.delta, self.base,
|
||||
d=1, phase4j_source=PHASE4J, n_neurons=80)
|
||||
assert_bits(self, result.snapshots, trace.snapshots)
|
||||
assert_bits(self, result.delta_after, expected)
|
||||
|
||||
def test_signed_zero_source_floor_tie_is_preserved(self):
|
||||
# The bridge's identity guard rejects this pathological subnormal base.
|
||||
# Compare the original apply_v2 directly: np.maximum(+0,-0) gives -0.
|
||||
self.base[:] = np.nextafter(np.float32(0), np.float32(1))
|
||||
result = self.run_host(d=0)
|
||||
original, _, _ = bridge._load_original(PHASE4J)
|
||||
from types import SimpleNamespace
|
||||
validator = SimpleNamespace(n=12, kc=self.kc, base_candidate=self.base,
|
||||
cand={"source_neuron_idx": bridge._Column(self.sources),
|
||||
"target_compartment_verbatim": bridge._Column(self.compartments)})
|
||||
expected, _ = original(validator, result.sampled_trace, COMPARTMENTS[0], 0,
|
||||
self.delta, {"eligibility_v2": {"eta_effective_mv": bridge.ETA_MV,
|
||||
"max_fractional_depression": bridge.FLOOR_FRACTION}})
|
||||
assert_bits(self, result.delta_after, expected)
|
||||
self.assertTrue(np.all(np.signbit(result.delta_after)))
|
||||
assert_bits(self, self.run_host(frozen=True).delta_after, self.delta)
|
||||
|
||||
def test_input_validation(self):
|
||||
bad_events = [
|
||||
(self.step.astype(np.int64), self.neurons, self.kc, 8, [0]),
|
||||
(self.step, self.neurons.astype(np.float32), self.kc, 8, [0]),
|
||||
(self.step, self.neurons, self.kc[::-1], 8, [0]),
|
||||
(self.step, self.neurons, self.kc, 8, [0, 0]),
|
||||
(self.step, self.neurons, self.kc, 8, [0.0]),
|
||||
(self.step, self.neurons, self.kc, 8, [8]),
|
||||
(self.step, self.neurons, self.kc, True, [0]),
|
||||
(self.step, self.neurons, self.kc, 0, []),
|
||||
(np.array([0, 0], np.int32), np.array([2, 2], np.int32), self.kc, 8, []),
|
||||
]
|
||||
for args in bad_events:
|
||||
with self.subTest(args=args), self.assertRaises(ValueError):
|
||||
prepare_events(*args, n_neurons=12)
|
||||
for kwargs in (dict(d=True), dict(d=0.5), dict(d=float("nan")),
|
||||
dict(frozen=1), dict(eta_mv=float("inf")),
|
||||
dict(floor_fraction=0), dict(decay=float("nan"))):
|
||||
with self.subTest(kwargs=kwargs), self.assertRaises(ValueError):
|
||||
self.run_host(**kwargs)
|
||||
self.delta[0] = -0.0
|
||||
with self.assertRaises(ValueError):
|
||||
self.run_host()
|
||||
self.delta[0] = 0
|
||||
self.base[0] = np.nan
|
||||
with self.assertRaises(ValueError):
|
||||
self.run_host()
|
||||
|
||||
def test_forged_prepared_rejected(self):
|
||||
prepared = self.prepared()
|
||||
bad = replace(prepared, ticks=np.array([0, 0, 7, 2, 2, 5], np.int32))
|
||||
with self.assertRaises(ValueError):
|
||||
self.run_host(bad)
|
||||
|
||||
def test_cuda_entry_rejects_bad_inputs_before_accessing_device(self):
|
||||
# An uninitialized shell has no cp/device fields. Rejection therefore
|
||||
# proves the CUDA entry's validation happens before any CUDA operation.
|
||||
backend = object.__new__(CudaEligibility)
|
||||
prepared = self.prepared()
|
||||
base_args = dict(prepared=prepared, candidate_sources=self.sources,
|
||||
candidate_compartments=self.compartments, compartment=COMPARTMENTS[0],
|
||||
delta_before=self.delta, base_candidate=self.base, **self.kw)
|
||||
bad = [dict(candidate_sources=self.sources.astype(np.int64)),
|
||||
dict(candidate_compartments=self.compartments.astype("S")),
|
||||
dict(delta_before=self.delta.astype(np.float64)),
|
||||
dict(base_candidate=np.array([np.inf, 1, 1, 1], np.float32)),
|
||||
dict(delta_before=np.array([np.nan, 0, 0, 0], np.float32)),
|
||||
dict(candidate_sources=np.array([1, 2, 5, 9], np.int32)),
|
||||
dict(candidate_sources=np.array([2, 2, 5, 11], np.int32)),
|
||||
dict(delta_before=np.array([-1, 0, 0, 0], np.float32)),
|
||||
dict(compartment="unknown"), dict(kernel_warmup=-1),
|
||||
dict(kernel_repeats=0), dict(kernel_repeats=True)]
|
||||
for overrides in bad:
|
||||
with self.subTest(overrides=overrides), self.assertRaises(ValueError):
|
||||
backend.run(**(base_args | overrides))
|
||||
|
||||
def test_no_dense_tick_raster_and_input_storage_owned(self):
|
||||
prepared = self.prepared()
|
||||
for arr in (prepared.kc, prepared.indptr, prepared.ticks, prepared.command_steps):
|
||||
self.assertEqual(arr.ndim, 1)
|
||||
self.assertFalse(arr.flags.writeable)
|
||||
self.kc[:] = 0
|
||||
self.step[:] = 0
|
||||
self.assertEqual(prepared.kc.tolist(), [2, 5, 9])
|
||||
self.assertEqual(prepared.ticks.tolist(), [0, 1, 7, 2, 2, 5])
|
||||
|
||||
def test_kernel_explicit_rounding_controls(self):
|
||||
self.assertIn("--fmad=false", CUDA_OPTIONS)
|
||||
self.assertIn("--ftz=false", CUDA_OPTIONS)
|
||||
self.assertIn("__fmul_rn", CUDA_SOURCE)
|
||||
self.assertIn("__fadd_rn", CUDA_SOURCE)
|
||||
self.assertNotIn("pow(", CUDA_SOURCE)
|
||||
self.assertNotIn("__expf", CUDA_SOURCE)
|
||||
|
||||
|
||||
class CompilerCacheTests(unittest.TestCase):
|
||||
"""Host-side compiler invocation/evidence checks; these do not compile CUDA."""
|
||||
|
||||
def test_explicit_flags_authenticated_cache_and_no_global_environment_mutation(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
compiler = root / "nvcc"
|
||||
compiler.write_bytes(b"host-test-compiler-placeholder")
|
||||
calls = []
|
||||
|
||||
def run(argv, **kwargs):
|
||||
if argv[-1] == "--version":
|
||||
return subprocess.CompletedProcess(argv, 0, stdout="nvcc test version", stderr="")
|
||||
calls.append((argv, kwargs))
|
||||
self.assertIn("--ftz=false", argv)
|
||||
self.assertIn("--fmad=false", argv)
|
||||
self.assertIn("-arch=sm_70", argv)
|
||||
self.assertNotIn("--use_fast_math", argv)
|
||||
self.assertNotIn("-ftz=true", argv)
|
||||
Path(argv[argv.index("-o") + 1]).write_bytes(b"test cubin, not executable CUDA")
|
||||
kwargs["stdout"].write(b"mock nvcc stdout\n")
|
||||
kwargs["stderr"].write(b"mock nvcc stderr\n")
|
||||
return subprocess.CompletedProcess(argv, 0)
|
||||
|
||||
with mock.patch.dict(os.environ, {"NVCC_PREPEND_FLAGS": "", "NVCC_APPEND_FLAGS": ""}), \
|
||||
mock.patch("gpu_backend.subprocess.run", side_effect=run):
|
||||
before = dict(os.environ)
|
||||
cubin, evidence, timing = _nvcc_cubin(root / "cache", "70", compiler)
|
||||
self.assertFalse(evidence["cache_hit"])
|
||||
self.assertTrue(evidence["complete"])
|
||||
self.assertIn("eligibility.cubin", evidence["files_sha256"])
|
||||
self.assertIn("compiler.stdout.log", evidence["files_sha256"])
|
||||
self.assertIn("compiler.stderr.log", evidence["files_sha256"])
|
||||
self.assertEqual(before, dict(os.environ))
|
||||
again, cached, second_timing = _nvcc_cubin(root / "cache", "70", compiler)
|
||||
self.assertEqual(cubin, again)
|
||||
self.assertTrue(cached["cache_hit"])
|
||||
self.assertEqual(second_timing["nvcc_compile_seconds"], 0)
|
||||
self.assertEqual(len(calls), 1)
|
||||
self.assertEqual(evidence["receipt_sha256"], cached["receipt_sha256"])
|
||||
cubin.write_bytes(b"corrupted test cache")
|
||||
with self.assertRaisesRegex(ValueError, "artifact changed"):
|
||||
_nvcc_cubin(root / "cache", "70", compiler)
|
||||
|
||||
def test_failed_compile_evidence_is_retained_and_not_overwritten(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
compiler = root / "nvcc"
|
||||
compiler.write_bytes(b"host-test-compiler-placeholder")
|
||||
|
||||
def run(argv, **kwargs):
|
||||
if argv[-1] == "--version":
|
||||
return subprocess.CompletedProcess(argv, 0, stdout="nvcc test version", stderr="")
|
||||
kwargs["stderr"].write(b"mock compiler failure\n")
|
||||
return subprocess.CompletedProcess(argv, 1)
|
||||
|
||||
with mock.patch.dict(os.environ, {"NVCC_PREPEND_FLAGS": "", "NVCC_APPEND_FLAGS": ""}), \
|
||||
mock.patch("gpu_backend.subprocess.run", side_effect=run):
|
||||
with self.assertRaisesRegex(RuntimeError, "evidence retained"):
|
||||
_nvcc_cubin(root / "cache", "70", compiler)
|
||||
receipts = list((root / "cache").rglob("build-receipt.json"))
|
||||
self.assertEqual(len(receipts), 1)
|
||||
before = receipts[0].read_bytes()
|
||||
with self.assertRaisesRegex(ValueError, "failed or mismatched"):
|
||||
_nvcc_cubin(root / "cache", "70", compiler)
|
||||
self.assertEqual(receipts[0].read_bytes(), before)
|
||||
|
||||
def test_injected_compiler_flags_rejected_without_clearing_global_environment(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
compiler = root / "nvcc"
|
||||
compiler.write_bytes(b"host-test-compiler-placeholder")
|
||||
with mock.patch.dict(os.environ, {"NVCC_APPEND_FLAGS": "--ftz=true"}):
|
||||
with self.assertRaisesRegex(ValueError, "injected flags"):
|
||||
_nvcc_cubin(root / "cache", "70", compiler)
|
||||
self.assertEqual(os.environ["NVCC_APPEND_FLAGS"], "--ftz=true")
|
||||
self.assertFalse((root / "cache").exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,178 @@
|
||||
# Conditioning execution branch — bounded preparation protocol
|
||||
|
||||
Status: DRAFT, NOT REGISTERED, NO GPU EXECUTION AUTHORITY YET.
|
||||
|
||||
This is a new independent model branch authorized by the user. All previously
|
||||
registered sources, raw data, frozen brains and experiment artifacts remain
|
||||
read-only. Existing scientific failures remain failures. The completed AP
|
||||
interface test does not establish functional learning.
|
||||
|
||||
## Scope and the next scientific decision
|
||||
|
||||
Consolidate updated-weight/same-state continuation, fixed functional gates and
|
||||
measured complete-process resource costs in this package. Then register and run
|
||||
the already proposed normal acquisition and all six controls, for all eight
|
||||
cells and five independent training replicates. Do not keep replacing functional
|
||||
learning experiments with unbounded engineering milestones.
|
||||
|
||||
No learning-rate, threshold, gain, transmitter, anatomical weight, input-rate,
|
||||
odor, mask, APL calibration or eligibility-v2 changes are permitted by this
|
||||
package. Any future biological dynamics hypothesis requires a separately named
|
||||
model/version and a pre-outcome hypothesis; permission for a new branch does not
|
||||
reclassify a changed model as an exact optimization of the old one.
|
||||
|
||||
No games, decoder, RL, visual stimulation, web services or 3D are included.
|
||||
|
||||
## Exact boundary semantics
|
||||
|
||||
- A fresh, sealed neural epoch and its actual original E postprocess identify
|
||||
the one permitted update. Recompute original U from the actual sealed spike
|
||||
events in a separate CPU interpreter, without executing the brain or E again.
|
||||
- Install original base plus the full after-delta once, using the frozen
|
||||
float32-mV to float64-SI bridge. Never add the after-delta to old effective
|
||||
weights. Keep the original 14,232 existing candidate edges and fixed floor.
|
||||
- Preserve voltage, existing g, refractory state, pending spike ring, APL state,
|
||||
complete APL pending amplitudes and absolute tick. Counts/events are explicitly
|
||||
segment-local in the new recording, not falsely lifetime counts.
|
||||
- Already accumulated g is not recomputed or rescaled. Pending presynaptic spike
|
||||
flags use current weights when they arrive, exactly as the frozen runtime
|
||||
does. Already queued APL amplitudes are preserved. The delays remain 18 steps;
|
||||
the spike ring has 19 slots and the APL ring has 18.
|
||||
- Later idle continuations retain the same after-overlay. A probe can fork a
|
||||
checkpoint but cannot become an idle ancestor. No analytical time advance.
|
||||
- New checkpoints use their own explicit updated-boundary schema. They do not
|
||||
claim the original C fixed-weight boundary rule was satisfied.
|
||||
|
||||
The independent oracle re-executes the exact fresh parent prefix, never calls
|
||||
restore, verifies live prefix state/events against that parent, changes only
|
||||
the authorized weights once and executes the unchanged reference timestep loop.
|
||||
Its explicit within-run weight switch is diagnostic, not a production backend.
|
||||
The one added boundary hook is independently removed to verify exact AST
|
||||
rollback. Its honest `within_trial_weight_updates=true` admission is not passed
|
||||
off as an unchanged-weight checkpoint.
|
||||
|
||||
## Bounded validation inventory
|
||||
|
||||
Use sealed AP reference epoch-001 parents for D1, D0 and frozen. New outputs never
|
||||
go into AP. Compare D1 restored reference/light 100 ms suffixes to a fresh
|
||||
220 ms continuous oracle. Compare D0/frozen new reference/light suffixes to
|
||||
original C fixed-weight continuation. Compare all events and final state/queues
|
||||
exactly; compare per-tick hashes, request acceptance, CSR queue and APL traces
|
||||
where actually recorded. Do not claim light records unseen intermediate states.
|
||||
|
||||
AP D1 epoch-001 has 765 spikes in its final 18 ticks, but none from its 79
|
||||
changed-edge sources. Thus it has useful real pending queues but cannot alone
|
||||
prove updated-weight handling on a pending changed candidate edge.
|
||||
|
||||
Add one deterministic mechanical diagnostic parent: 120 ms fresh dynamics with
|
||||
no requests until tick 1199, then one requested spike in the minimum canonical
|
||||
KC source ID among actual y5B'2a candidates, together with the four verified
|
||||
PAM15 DAN IDs. Run original U with US at tick 1199, D=1 and the unchanged rule.
|
||||
This is a test fixture stimulus, not a new odor or a learning-success trial.
|
||||
No seed search or parameter adjustment follows missing coverage. Require a
|
||||
real changed existing candidate edge, a real source spike crossing the boundary,
|
||||
and an accepted timed arrival. Nonempty queues alone are insufficient. Compare
|
||||
its restored reference/light suffixes to the independent continuous oracle.
|
||||
|
||||
Also run actual no-input 1 s then 9 s idle dynamics from AP D1, preserving one
|
||||
lineage. At 0, 1 and 10 s fork A/B no-US/no-update 120 ms probes. The two saved
|
||||
evaluation inputs use the original first block's distinct evaluation streams
|
||||
from master 20260930, the original L physiological rate tables and [0,100 ms)
|
||||
CS window; no sampler is run until registration. Repeated probes are not new
|
||||
training seeds and never feed back to the idle chain.
|
||||
|
||||
The bounded engineering suite does not run acquisition or claim retention of
|
||||
a learned association. A failure is preserved with partial outputs; no silent
|
||||
retry, replacement seed or post-result trial selection is allowed.
|
||||
|
||||
Two fixed measurement calls avoid extrapolating incomplete or mismatched costs.
|
||||
Re-execute AP D1 epoch-001's original saved natural input from a fresh state and
|
||||
its recorded before-overlay, using light recording followed by original E and
|
||||
the independent CPU validator. Compare its events, final state and actual delta
|
||||
to AP. Separately measure one fresh-state/no-US A evaluation probe with the
|
||||
original zero overlay. Retention-continuation probes are not substituted for
|
||||
normal fresh-state probe costs. These measurements are engineering diagnostics,
|
||||
not additional acquisition or a seed search.
|
||||
|
||||
The complete proposed inventory is 23 new brain calls / 125,200 ticks, seven
|
||||
CPU update/validation children and one GPU sampler process (two uniform batches):
|
||||
31 child processes. Compilation caches may evolve and are inventoried separately;
|
||||
previous scientific outputs remain immutable. All future checkpoints/hashes are
|
||||
derived from actual completed children, not fabricated during registration.
|
||||
|
||||
## Functional gates fixed before acquisition
|
||||
|
||||
`learning_gates.py` retains the frozen normal/delayed predicates, requires five
|
||||
independent training replicates, checks full 63-bit stream identities and keeps
|
||||
evaluation streams separate. A majority means at least three replicates each
|
||||
satisfy the entire conjunction, not different seeds passing different clauses.
|
||||
|
||||
Two explicit additional operationalizations are fixed before outcomes:
|
||||
|
||||
1. Reversal and real-time retention use nonMBONDownstream for the downstream
|
||||
functional gate, while reporting the entire legacyDownstream union as well.
|
||||
MBON-local change cannot be counted twice as downstream transfer.
|
||||
2. The legacy H mean-control predicate is called separately for the PAM15 and
|
||||
PPL103 control sources in each (input mode, reinforced cue) group. Both must
|
||||
pass that separate audit. No control pooling or favorable-source selection.
|
||||
|
||||
Reversal keeps the original conditioned-minus-neutral orientation and original
|
||||
pre baseline, with strict nonzero sign crossing and no-reversal continuation
|
||||
remaining on its original side. Retention requires the same replicate to pass
|
||||
both 1 s and 10 s against time-matched frozen controls. Delta change alone is
|
||||
never a functional learning gate. See the pinned original PROTOCOL_DRAFT and
|
||||
EVALUATION_POLICY_DRAFT for the complete unchanged input/assay inventory.
|
||||
|
||||
Pure gate functions authenticate neither disk/process evidence nor anatomy;
|
||||
their results explicitly say conditional predicates, not scientific PASS.
|
||||
The eventual coordinator must bind completed real trajectories and input,
|
||||
population, seed, delta and checkpoint receipts before making a learning claim.
|
||||
|
||||
## Resource accounting and stop policy
|
||||
|
||||
Proposed bounded validation cap: 4 GiB of new outputs, at least 10 GiB free
|
||||
reserve, 1,800 seconds per child and 7,200 seconds total. Confirm measured free
|
||||
space and commit the registration before execution. Use only the admitted
|
||||
RTX 4090, check all three ComfyUI queues and do not stop or evict services.
|
||||
|
||||
Measure parent wall time from before spawn through actual exit and independent
|
||||
result validation, including input hashing, CUDA startup/compilation, graph load,
|
||||
CPU update verification, lossless compression and I/O. Worker/core timing is a
|
||||
separate field. No extrapolation may label GPU-only time as complete latency.
|
||||
|
||||
The proposed normal suite has 30,000 training/control epochs plus 3,920 probes:
|
||||
33,920 brain calls and 4,070.4 biological seconds. The full proposal has 68,000
|
||||
epochs, 9,440 probes and 80 actual 10 s idle lineages, totaling 11,892.8 biological
|
||||
seconds before engineering validation. These are inventory arithmetic, not wall
|
||||
time or disk measurements. Predeclare a finite normal-run resource budget using
|
||||
measured complete outputs, a stated reserve and explicit uncertainty about
|
||||
learning-dependent activity. No unbounded automatic launch is authorized here.
|
||||
|
||||
If normal acquisition fails the registered all-cell gate, preserve and seal the
|
||||
actual failure; delayed/reversal/retention are NOT-RUN. Do not tune to rescue it.
|
||||
If it passes, run the already registered follow-up matrix. Frozen integrity and
|
||||
required numerical regressions remain independent gates, not learning evidence.
|
||||
|
||||
## Provenance
|
||||
|
||||
Before registration require every new source to match its recorded Git commit,
|
||||
snapshot the protocol and sources, and pin all old inputs by SHA-256. Record
|
||||
actual child exits; worker self-receipts do not prove their own process exited.
|
||||
All output files receive SHA-256 and an exact manifest at sealing. No old source
|
||||
or runtime global is patched. Full experimental arrays remain server-side;
|
||||
source/evidence Git synchronization must not be described as a bulk-data backup.
|
||||
|
||||
`audit_execution.py` reads actual recorded process exits and full output hashes;
|
||||
`prepare_execution.py integrity` runs in a separate CPU process after execution.
|
||||
`finalize_execution.py` requires externally supplied registration, numerical,
|
||||
budget and after-integrity report hashes and creates an exclusive experiment
|
||||
seal. The entire model directory is not itself claimed sealed: every registered
|
||||
source is bound to its committed blob and sealed source snapshot instead.
|
||||
|
||||
`budget_report.py` may return insufficient information rather than invent future
|
||||
large-suite overhead. A few measured cycles cannot establish the cost of a
|
||||
growing full-directory hash policy, unknown learning-dependent activity or final
|
||||
integrity work. No normal-suite resource assumptions or execution authorization
|
||||
are implicitly supplied by this finite engineering registration. Real measured
|
||||
cycle cost and conservative accounting bounds must still be reported even when
|
||||
a credible reserved complete-suite projection is unavailable.
|
||||
@@ -0,0 +1,491 @@
|
||||
"""Read-only, process-bound finite engineering audit; never a learning gate.
|
||||
|
||||
Only the optional final JSON is written, exclusively. The recorded successful
|
||||
parent-process exits are authenticated file evidence, not re-observed exits.
|
||||
Old integrity/sealing is deliberately a separate process. No E, U or Torch is
|
||||
imported here; all checkpoint loading shares updated_continuation.C.R.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from types import ModuleType
|
||||
|
||||
import numpy as np
|
||||
|
||||
import boundary_compare as B
|
||||
import boundary_plan as PLAN
|
||||
import execution_authority as A
|
||||
import isolated_execution as W
|
||||
import updated_continuation as D
|
||||
from prepare_execution import EXP, MODEL, LAB, save
|
||||
|
||||
N, EDGES = 166700, 25582938
|
||||
require, read, digest = A.require, A.read, A.digest
|
||||
|
||||
|
||||
def canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
||||
|
||||
|
||||
def same_json(left, right):
|
||||
return canonical(left) == canonical(right)
|
||||
|
||||
|
||||
def verify_pins(pins):
|
||||
require(type(pins) is dict and pins, 'Nonempty input authority required')
|
||||
for path, sha in pins.items():
|
||||
require(A.pin(path)['sha256'] == sha, 'Pinned file changed: ' + str(path))
|
||||
|
||||
|
||||
def tree(directory):
|
||||
root = Path(directory)
|
||||
require(root.is_dir(), 'Missing output tree')
|
||||
result = {}
|
||||
for p in sorted(root.rglob('*')):
|
||||
require(not any(q.is_symlink() or (hasattr(q, 'is_junction') and q.is_junction())
|
||||
for q in (p, *p.parents)), 'Linked evidence forbidden')
|
||||
if p.is_file():
|
||||
result[p.relative_to(root).as_posix()] = dict(sha256=digest(p), bytes=p.stat().st_size)
|
||||
else:
|
||||
require(p.is_dir(), 'Nonregular evidence forbidden')
|
||||
require(result, 'Empty output tree')
|
||||
return result
|
||||
|
||||
|
||||
def _helpers():
|
||||
raw = W.AP.read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest() == W.AP_SHA, 'Frozen worker helper changed')
|
||||
module = ModuleType('_conditioning_execution_audit_pure_worker_helpers')
|
||||
module.__file__ = str(W.AP)
|
||||
exec(compile(raw, str(W.AP), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def expected_processes(plan):
|
||||
calls = {row['call_id']: row for row in plan['calls']}
|
||||
require(len(calls) == len(plan['calls']), 'Duplicate call')
|
||||
kinds = {name: ('brain' if row['runner'] in ('runtime_light', 'fresh_probe') else
|
||||
'oracle' if row['runner'] == 'boundary_oracle' else
|
||||
'unchanged' if row['runner'] == 'runtime_continuation' else 'updated')
|
||||
for name, row in calls.items()}
|
||||
for arm in ('D1', 'D0', 'frozen'):
|
||||
kinds['AP-' + arm + '--cpu-verify'] = 'validate_cpu'
|
||||
for name in ('mechanical--fresh-parent', 'performance--natural-light-fresh'):
|
||||
kinds[name + '--original-E'] = 'update'
|
||||
kinds[name + '--cpu-verify'] = 'validate_cpu'
|
||||
kinds['evaluation-inputs'] = 'sample'
|
||||
require(len(kinds) == plan['counts']['total_children'], 'Planned child inventory differs')
|
||||
return kinds
|
||||
|
||||
|
||||
def _closure(reg, reg_sha):
|
||||
return {**reg['source_sha256'], **reg['input_sha256'], **reg['prepared_file_sha256'],
|
||||
str(EXP / 'protocol/preregistered.json'): reg_sha}
|
||||
|
||||
|
||||
def verify_process(name, kind, reg, reg_sha, process_path, helper):
|
||||
"""Recheck actual bytes; never accept worker pass flags as a seal."""
|
||||
paths = {key: EXP / f'{sub}/{name}{suffix}' for key, sub, suffix in (
|
||||
('job', 'jobs', '.json'), ('worker', 'receipts', '.worker.json'),
|
||||
('process', 'receipts', '.process.json'), ('stdout', 'logs', '.stdout.log'),
|
||||
('stderr', 'logs', '.stderr.log'))}
|
||||
require(Path(process_path) == paths['process'], 'Wrong fixed process record path')
|
||||
job, receipt, process = (read(paths[k]) for k in ('job', 'worker', 'process'))
|
||||
ap = kind in ('brain', 'update')
|
||||
script = W.AP if ap else MODEL / 'isolated_execution.py'
|
||||
worker_sha = W.AP_SHA if ap else reg['source_sha256'][str(script)]
|
||||
schema = 'phase4ap-isolated-worker-job-v1' if ap else W.SCHEMA
|
||||
require(job['schema'] == schema and job['job_id'] == name and job['kind'] == kind and
|
||||
job['registration_sha256'] == reg_sha and job['worker_sha256'] == worker_sha,
|
||||
'Actual job identity differs')
|
||||
require(process['schema'] == 'conditioning-execution-process-v1' and process['complete'] is True and
|
||||
process['exit_code'] == 0 and type(process['exit_code']) is int and process['timed_out'] is False and
|
||||
process['name'] == name and process['kind'] == kind and process['registration_sha256'] == reg_sha,
|
||||
'Missing successful recorded process exit')
|
||||
job_sha = digest(paths['job'])
|
||||
require(process['job_sha256'] == job_sha and process['worker_receipt_sha256'] == digest(paths['worker']) and
|
||||
all(process[k + '_sha256'] == digest(paths[k]) for k in ('stdout', 'stderr')), 'Process file chain changed')
|
||||
argv = process['argv']
|
||||
require(type(argv) is list and len(argv) == (8 if ap else 7) and type(argv[0]) is str and bool(argv[0]),
|
||||
'Recorded process command is incomplete')
|
||||
require(argv[1:] == ['-B', str(script), *([kind] if ap else []), '--job', str(paths['job']),
|
||||
'--job-sha256', job_sha], 'Recorded command differs from pinned worker/job')
|
||||
expected_schema = 'phase4ap-isolated-worker-receipt-v1' if ap else 'conditioning-isolated-execution-receipt-v1'
|
||||
require(receipt['schema'] == expected_schema and receipt['complete'] is True and
|
||||
all(receipt[k] == job[k] for k in ('job_id', 'kind', 'registration_sha256', 'worker_sha256')) and
|
||||
receipt['job_sha256'] == job_sha and receipt['process_exit_independently_observed'] is False,
|
||||
'Worker receipt identity/scope differs')
|
||||
closure = _closure(reg, reg_sha)
|
||||
require(all(job['input_sha256'].get(p) == s for p, s in closure.items()), 'Registered input closure omitted')
|
||||
inputs = dict(closure)
|
||||
if kind == 'brain':
|
||||
roles = ('runtime_light', 'runtime_continuation')
|
||||
case = Path(job['case_dir'])
|
||||
extra = [case / 'spec.json', case / 'requests.npz', Path(job['overlay_file']), Path(job['overlay_manifest'])]
|
||||
inputs.update({str(p): digest(p) for p in extra})
|
||||
else:
|
||||
authority = Path(job['authority_file'])
|
||||
require(digest(authority) == job['authority_sha256'], 'Worker authority changed')
|
||||
inputs[str(authority)] = job['authority_sha256']
|
||||
value = read(authority)
|
||||
if kind == 'sample':
|
||||
require(authority == EXP / 'protocol/preregistered.json' and job['authority_sha256'] == reg_sha,
|
||||
'Sampler is not bound to actual registration')
|
||||
else:
|
||||
inputs.update(A.files_from_authority(value))
|
||||
if kind == 'validate_cpu':
|
||||
update = Path(job['update_dir'])
|
||||
require({p.name for p in update.iterdir()} == set(D.UPDATE_FILES), 'Update must contain exact four files')
|
||||
inputs.update({str(p): digest(p) for p in update.iterdir()})
|
||||
require(job['chain_sha256'] == digest(update / 'chain-receipt.json'), 'CPU chain pin differs')
|
||||
if kind == 'oracle':
|
||||
case = Path(job['oracle_case'])
|
||||
for filename, key in (('spec.json', 'oracle_spec_sha256'), ('requests.npz', 'oracle_requests_sha256')):
|
||||
require(digest(case / filename) == job[key], 'Live oracle case pin differs')
|
||||
inputs[str(case / filename)] = job[key]
|
||||
roles = ('conditioning_epoch',) if kind == 'update' else ()
|
||||
require(job['input_sha256'] == inputs, 'Actual job has missing/undeclared input authority')
|
||||
pins = {**inputs, str(paths['job']): job_sha, str(script): worker_sha}
|
||||
if ap:
|
||||
expected_sources = {n: dict(path=str(LAB / (n + '.py')), sha256=helper.SOURCE_PINS[n]) for n in roles}
|
||||
require(job['sources'] == expected_sources and receipt['source_files'] == expected_sources, 'Frozen process source differs')
|
||||
pins.update({v['path']: v['sha256'] for v in expected_sources.values()})
|
||||
else:
|
||||
require(set(job['source_sha256']) == W.SOURCES[kind], 'New worker source inventory differs')
|
||||
for filename, sha in job['source_sha256'].items():
|
||||
require(reg['source_sha256'][str(MODEL / filename)] == sha, 'New source not registered')
|
||||
pins[str(MODEL / filename)] = sha
|
||||
pins[str(W.AP)] = W.AP_SHA
|
||||
require(receipt['verified_input_sha256' if ap else 'input_sha256'] == pins, 'Worker did not check the complete actual closure')
|
||||
verify_pins(pins)
|
||||
if kind == 'unchanged':
|
||||
W.bind_unchanged_authority(helper, job, dict(authority=Path(job['authority_file']),
|
||||
checkpoint=Path(job['checkpoint_dir']), case=Path(job['case_dir']),
|
||||
overlay_file=Path(job['overlay_file']), overlay_manifest=Path(job['overlay_manifest'])),
|
||||
{Path(p): sha for p, sha in pins.items()})
|
||||
expected_output = EXP / ('updates' if kind == 'update' else 'runs') / name.removesuffix('--original-E')
|
||||
require(Path(job['output_dir']) == expected_output and receipt['output_dir'] == str(expected_output) and
|
||||
job['receipt_file'] == str(paths['worker']), 'Output or receipt escaped fixed inventory')
|
||||
outputs = tree(expected_output)
|
||||
hashes = {k: v['sha256'] for k, v in outputs.items()}
|
||||
require(hashes == receipt['output_files_sha256'] and process['output_bytes'] == sum(v['bytes'] for v in outputs.values()) and
|
||||
process['output_inventory_sha256'] == hashlib.sha256(json.dumps(hashes, sort_keys=True).encode()).hexdigest(),
|
||||
'Full output inventory changed')
|
||||
attempt = Path(str(paths['worker']) + '.attempt.json')
|
||||
require(digest(attempt) == receipt['attempt_sha256'], 'Attempt record changed')
|
||||
av = read(attempt)
|
||||
require(av['complete'] is False and av['job_sha256'] == job_sha and av['no_automatic_retry'] is True,
|
||||
'Attempt record does not bind actual invocation')
|
||||
require(receipt.get('scientific_learning_pass_claimed', receipt.get('scientific_gate_pass_claimed')) is False,
|
||||
'Worker claims a scientific gate')
|
||||
for key in ('child_wall_seconds', 'end_to_end_seconds', 'validation_wall_seconds'):
|
||||
require(type(process[key]) in (float, int) and np.isfinite(process[key]) and process[key] >= 0, 'Invalid recorded timing')
|
||||
evidence = {str(p): digest(p) for p in (*paths.values(), attempt)}
|
||||
return dict(name=name, kind=kind, paths=paths, job=job, receipt=receipt, process=process,
|
||||
output=expected_output, output_inventory=outputs, evidence_sha256=evidence, input_pins=pins)
|
||||
|
||||
|
||||
def _npz(path):
|
||||
with np.load(path, allow_pickle=False) as archive:
|
||||
return {name: archive[name].copy() for name in archive.files}
|
||||
|
||||
|
||||
def _pair(left, right):
|
||||
B._complete(left); B._complete(right)
|
||||
checks, observed = B.C._pair_checks(left, right)
|
||||
exact = all(checks.values())
|
||||
return dict(numerical_exact=exact, pass_all=exact, checks=checks,
|
||||
failed_checks=[k for k, v in checks.items() if not v], observed=observed,
|
||||
light_intermediate_states_observed=False, learning_pass_claimed=False)
|
||||
|
||||
|
||||
def _parent(reg, complete, role):
|
||||
record = complete['parents'][role]
|
||||
if role in reg['parent_records']:
|
||||
original = reg['parent_records'][role]
|
||||
require(all(same_json(record[k], v) for k, v in original.items()), 'Imported parent declaration changed')
|
||||
return record
|
||||
|
||||
|
||||
def _update_check(parent, verified, cpu_name):
|
||||
"""Bind actual CPU recomputation process to original E four-file evidence."""
|
||||
cpu = verified[cpu_name]
|
||||
require(cpu['kind'] == 'validate_cpu', 'Missing independent CPU update verification process')
|
||||
directory = Path(parent['update_dir']); hashes = {n: digest(directory / n) for n in D.UPDATE_FILES}
|
||||
require(set(p.name for p in directory.iterdir()) == set(D.UPDATE_FILES), 'Unexpected update inventory')
|
||||
require(parent['after_overlay'] == dict(overlay_file=str(directory / 'delta-after.npz'),
|
||||
overlay_manifest=str(directory / 'overlay-manifest.json')), 'After snapshot paths leave actual E update')
|
||||
authority = parent['epoch_authority']; epoch = read(authority['path'])
|
||||
require(A.pin(authority['path']) == authority and cpu['job']['authority_file'] == authority['path'] and
|
||||
cpu['job']['authority_sha256'] == authority['sha256'] and Path(cpu['job']['update_dir']) == directory and
|
||||
cpu['job']['chain_sha256'] == hashes['chain-receipt.json'], 'CPU verification points to another update')
|
||||
chain, update = (read(directory / name) for name in ('chain-receipt.json', 'update-receipt.json'))
|
||||
report = read(cpu['output'] / 'validation.json')
|
||||
require(same_json(report, cpu['receipt']['result']) and report['schema'] == 'conditioning-update-cpu-validation-v1' and
|
||||
report['complete'] is True and report['epoch_authority_sha256'] == authority['sha256'] and
|
||||
report['parent_checkpoint_manifest_sha256'] == parent['checkpoint_sha256'] and
|
||||
report['update_files_sha256'] == hashes and report['frozen_U_verify_receipt_recomputed'] is True and
|
||||
report['actual_sealed_events_used'] is True and report['full_candidate_mapping_verified'] is True and
|
||||
report['brain_executed'] is False and report['learning_pass_claimed'] is False and
|
||||
report['frozen_U_source_sha256'] == D.SOURCE_PINS['conditioning_update_source'] and
|
||||
report['validator_source'] == A.pin(MODEL / 'validate_update_cpu.py'), 'CPU recomputation receipt mismatch')
|
||||
require(chain.get('schema') == 'phase4an-epoch-postprocess-chain-v1' and chain['complete'] is True and
|
||||
all(chain[k] is False for k in ('weights_installed', 'brain_executed', 'learning_pass_claimed', 'candidate_generated')) and
|
||||
chain['authority_sha256'] == authority['sha256'] and chain['source_neural_checkpoint_dir'] == parent['directory'] and
|
||||
chain['source_neural_checkpoint_manifest_sha256'] == parent['checkpoint_sha256'] and
|
||||
chain['output_files_sha256'] == {k: v for k, v in hashes.items() if k != 'chain-receipt.json'} and
|
||||
chain['update_receipt_payload_sha256'] == report['update_receipt_payload_sha256'] == update['payload_sha256'],
|
||||
'Original E chain no longer binds the same update')
|
||||
before = _npz(parent['before_overlay']['overlay_file']); after = _npz(parent['after_overlay']['overlay_file'])
|
||||
require(set(before) == set(after) == {'edge_id', 'plastic_delta_mv'} and
|
||||
B.bit_equal(before['edge_id'], after['edge_id']), 'Overlay identity changed')
|
||||
require(report['before_overlay_sha256'] == digest(parent['before_overlay']['overlay_file']) and
|
||||
report['before_manifest_sha256'] == digest(parent['before_overlay']['overlay_manifest']) and
|
||||
report['after_overlay_sha256'] == hashes['delta-after.npz'] and
|
||||
report['after_manifest_sha256'] == hashes['overlay-manifest.json'] and
|
||||
report['before_delta_raw_sha256'] == B._raw(before['plastic_delta_mv']) and
|
||||
report['after_delta_raw_sha256'] == B._raw(after['plastic_delta_mv']), 'Actual delta differs from CPU verification')
|
||||
require(update['payload_sha256'] == hashlib.sha256(canonical({k: v for k, v in update.items() if k != 'payload_sha256'}).encode()).hexdigest(),
|
||||
'Update receipt payload changed')
|
||||
require(epoch['checkpoint_dir'] == parent['directory'] and epoch['checkpoint_manifest_sha256'] == parent['checkpoint_sha256'],
|
||||
'Update is not from actual neural parent')
|
||||
return dict(pass_all=True, CPU_process=cpu_name, update_files_sha256=hashes,
|
||||
before_delta_raw_sha256=report['before_delta_raw_sha256'], after_delta_raw_sha256=report['after_delta_raw_sha256'],
|
||||
U_receipt_payload_sha256=update['payload_sha256'], U_recomputed_in_this_audit=False,
|
||||
U_recomputation_from_authenticated_separate_CPU_process=True)
|
||||
|
||||
|
||||
def outcome(checks, pending):
|
||||
"""Numerical failure and missing nonvacuous coverage are not equivalent."""
|
||||
require(type(checks) is dict and bool(checks) and all(type(v) is bool for v in checks.values()),
|
||||
'Explicit nonempty numerical/lineage checks required')
|
||||
require(set(pending) == {'D1', 'mechanical'}, 'Both predetermined pending-edge audits required')
|
||||
exact = all(checks.values())
|
||||
coverage = pending['mechanical']['accepted_changed_edge_witness_verified'] is True
|
||||
status = 'FAIL-NUMERICAL-OR-LINEAGE' if not exact else ('PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING'
|
||||
if coverage else 'INCOMPLETE-CHANGED-EDGE-COVERAGE')
|
||||
return exact, coverage, status
|
||||
|
||||
|
||||
def _pending(parent, child, parent_descriptor):
|
||||
epoch = read(parent_descriptor['epoch_authority']['path']); spec = read(epoch['files']['spec']['path'])
|
||||
graph = Path(spec['graph_dir']); apl_dir = Path(spec['apl_bundle_dir']); arrays = {}
|
||||
try:
|
||||
for name in ('ptr', 'src', 'dst', 'edge_id', 'weights'):
|
||||
arrays[name] = np.load(graph / (name + '.npy'), mmap_mode='r', allow_pickle=False)
|
||||
apl = np.load(apl_dir / 'apl_globals.npy', allow_pickle=False)
|
||||
before = _npz(parent_descriptor['before_overlay']['overlay_file'])
|
||||
after = _npz(parent_descriptor['after_overlay']['overlay_file'])
|
||||
require(B.bit_equal(before['edge_id'], after['edge_id']), 'Changed witness candidate mask differs')
|
||||
paths = [graph / (n + '.npy') for n in arrays] + [apl_dir / 'apl_globals.npy',
|
||||
Path(parent_descriptor['before_overlay']['overlay_file']), Path(parent_descriptor['after_overlay']['overlay_file'])]
|
||||
return B.audit_changed_pending(parent, child, ptr=arrays['ptr'], src=arrays['src'], dst=arrays['dst'],
|
||||
edge_id=arrays['edge_id'], base_weights=arrays['weights'], apl_mask=np.isin(arrays['src'], apl),
|
||||
candidate_edge_id=before['edge_id'], delta_before=before['plastic_delta_mv'],
|
||||
delta_after=after['plastic_delta_mv'], input_pins={str(p): digest(p) for p in paths})
|
||||
finally:
|
||||
for value in arrays.values():
|
||||
value._mmap.close()
|
||||
|
||||
|
||||
def _lineage(reg, complete, verified, records):
|
||||
"""Actual advancing idle chain plus non-feedback probes, not memory success."""
|
||||
checks = {}; probe_rows = []
|
||||
base = reg['parent_records'][reg['plan']['imported_parents']['D1']['role']]
|
||||
delta = {k: digest(v) for k, v in base['after_overlay'].items()}
|
||||
sampler = verified['evaluation-inputs']; sr = read(sampler['output'] / 'sampler-receipt.json')
|
||||
require(same_json(sr, sampler['receipt']['result']) and sr['complete'] is True and sr['registration_sha256'] == sampler['job']['registration_sha256'] and
|
||||
sr['uniform_batch_calls'] == 2 and sr['US_added'] is False and sr['brain_executed'] is False,
|
||||
'Sampler receipt changed or wrong scope')
|
||||
for cue in ('A', 'B'):
|
||||
sample = sampler['output'] / (cue + '-requests.npz')
|
||||
rows = [r for r in sr['rows'] if r['cue'] == cue]
|
||||
require(len(rows) == 1 and rows[0]['saved_requests_sha256'] == digest(sample), 'Sampler cue binding differs')
|
||||
req = _npz(sample); rates = _npz(EXP / f'inputs/static/{cue}-rates.npz')
|
||||
require(set(req) == {'tick', 'neuron_idx'} and req['tick'].dtype == req['neuron_idx'].dtype == np.int32 and
|
||||
req['tick'].shape == req['neuron_idx'].shape and np.all((req['tick'] >= 0) & (req['tick'] < 1000)) and
|
||||
np.isin(req['neuron_idx'], rates['targets']).all(), 'Probe contains non-CS or out-of-window input')
|
||||
require(rows[0]['stream']['seed'] == reg['plan']['evaluation_streams'][cue]['seed'] and
|
||||
rows[0]['stream']['semantic_key'] == reg['plan']['evaluation_streams'][cue]['key'] and
|
||||
rows[0]['stream']['split'] == 'evaluation', 'Probe seed semantic binding differs')
|
||||
for label in ('t0', 't1', 't10'):
|
||||
name = f'D1--probe--{label}--{cue}'; call = next(c for c in reg['plan']['calls'] if c['call_id'] == name)
|
||||
job = verified[name]['job']; auth = read(job['authority_file'])
|
||||
case = Path(auth['case']['requests']['path'])
|
||||
parent = _parent(reg, complete, call['parent'])
|
||||
checks[name + '.input_bytes'] = digest(case) == digest(sample)
|
||||
checks[name + '.parent_clock'] = auth['parent'] == dict(directory=parent['directory'], checkpoint_manifest_sha256=parent['checkpoint_sha256']) and auth['global_tick_offset'] == call['global_tick_offset']
|
||||
checks[name + '.fixed_delta'] = auth['overlay_after']['file']['sha256'] == delta['overlay_file'] and auth['overlay_after']['manifest']['sha256'] == delta['overlay_manifest']
|
||||
checks[name + '.no_update_US_backflow'] = call['US'] is call['plastic_update'] is call['feedback_to_idle'] is False and not records[name]['summary']['within_trial_weight_updates']
|
||||
probe_rows.append(dict(call_id=name, global_tick_offset=records[name]['global_tick_offset'],
|
||||
actual_CS_requests=len(req['tick']), actual_US_requests=0, inputs_sha256=digest(case),
|
||||
complete_response_metrics_or_retention_gate=False))
|
||||
for name in ('D1--idle--1s', 'D1--idle--9s'):
|
||||
call = next(c for c in reg['plan']['calls'] if c['call_id'] == name)
|
||||
auth = read(verified[name]['job']['authority_file']); parent = _parent(reg, complete, call['parent'])
|
||||
req = _npz(auth['case']['requests']['path'])
|
||||
checks[name + '.actual_duration'] = records[name]['steps'] == call['steps']
|
||||
checks[name + '.parent_clock'] = auth['parent'] == dict(directory=parent['directory'], checkpoint_manifest_sha256=parent['checkpoint_sha256']) and auth['global_tick_offset'] == call['global_tick_offset']
|
||||
checks[name + '.empty_input'] = len(req['tick']) == len(req['neuron_idx']) == 0
|
||||
checks[name + '.fixed_delta'] = auth['overlay_after']['file']['sha256'] == delta['overlay_file'] and auth['overlay_after']['manifest']['sha256'] == delta['overlay_manifest']
|
||||
checks['no_probe_feeds_other_segment'] = all('--probe--' not in str(c.get('parent')) for c in reg['plan']['calls'])
|
||||
checks['ten_seconds_actually_advanced'] = records['D1--idle--1s']['steps'] + records['D1--idle--9s']['steps'] == 100000 and records['D1--idle--9s']['summary']['global_next_tick'] == 101200
|
||||
perf = verified['performance--evaluation-A-light-fresh']['job']
|
||||
checks['normal_probe_performance_actual_A_bytes'] = digest(Path(perf['case_dir']) / 'requests.npz') == digest(sampler['output'] / 'A-requests.npz')
|
||||
checks['normal_probe_performance_zero_overlay'] = perf['overlay_file'] == reg['initial_overlay']['overlay_file'] and perf['overlay_manifest'] == reg['initial_overlay']['overlay_manifest']
|
||||
return dict(pass_all=all(checks.values()), checks=checks, failed_checks=[k for k, v in checks.items() if not v],
|
||||
probes=probe_rows, biological_retention_demonstrated=False, learning_pass_claimed=False,
|
||||
light_per_tick_identity_claimed=False, one_and_nine_second_same_state_lineage_verified=all(checks.values()))
|
||||
|
||||
|
||||
def audit(reg_sha, *, save_report=True):
|
||||
require(sys.dont_write_bytecode and 'torch' not in sys.modules and 'conditioning_epoch' not in sys.modules,
|
||||
'Run a fresh pure CPU Python -B audit process')
|
||||
regfile = EXP / 'protocol/preregistered.json'
|
||||
require(digest(regfile) == reg_sha, 'External registration SHA changed')
|
||||
reg = read(regfile); PLAN.validate_plan(reg['plan'])
|
||||
require(reg['schema'] == 'conditioning-execution-registration-v1' and reg['engineering_only'] is True and
|
||||
reg['scientific_acquisition_authorized'] is False, 'Not an engineering-only authority')
|
||||
pins = _closure(reg, reg_sha); verify_pins(pins)
|
||||
complete_path = EXP / 'audit/execution-complete.json'; complete_sha = digest(complete_path); complete = read(complete_path)
|
||||
calls = reg['plan']['calls']; expected = expected_processes(reg['plan'])
|
||||
require(complete['complete'] is True and complete['registration_sha256'] == reg_sha and
|
||||
complete['completed_calls'] == [c['call_id'] for c in calls] and set(complete['processes']) == set(expected) and
|
||||
complete['scientific_learning_pass_claimed'] is complete['candidate_generated'] is False,
|
||||
'Execution inventory incomplete or scientifically overclaimed')
|
||||
helper = _helpers(); verified = {name: verify_process(name, kind, reg, reg_sha, complete['processes'][name], helper)
|
||||
for name, kind in expected.items()}
|
||||
records = {}; imports = {}; checks = {}; updates = {}; comparisons = {}; pending = {}; used_pins = dict(pins)
|
||||
for item in verified.values():
|
||||
for path, sha in {**item['input_pins'], **item['evidence_sha256']}.items():
|
||||
require(path not in used_pins or used_pins[path] == sha, 'Conflicting actual process authority')
|
||||
used_pins[path] = sha
|
||||
try:
|
||||
for arm, descriptor in reg['plan']['imported_parents'].items():
|
||||
parent = _parent(reg, complete, descriptor['role'])
|
||||
require(str(Path(parent['directory']) / 'checkpoint-manifest.json') == descriptor['checkpoint_manifest'] and
|
||||
parent['checkpoint_sha256'] == descriptor['sha256'], 'Imported authority differs')
|
||||
D.C.load_checkpoint(parent['directory'], descriptor['sha256'])
|
||||
imports[arm] = B.load_record(parent['directory'], kind='parent')
|
||||
updates['AP-' + arm] = _update_check(parent, verified, 'AP-' + arm + '--cpu-verify')
|
||||
for call in calls:
|
||||
name = call['call_id']; run = verified[name]; directory = run['output']; receipt = run['receipt']
|
||||
case = EXP / 'cases' / call['case_group']
|
||||
expected_spec = read(reg['case_templates'][call['case_group']])
|
||||
if call['parent'] is not None:
|
||||
p = _parent(reg, complete, call['parent'])
|
||||
expected_spec.update(parent_checkpoint_manifest_sha256=p['checkpoint_sha256'],
|
||||
global_tick_offset=call['global_tick_offset'])
|
||||
require(same_json(read(case / 'spec.json'), expected_spec), 'Executed case drifted from registered template')
|
||||
if run['kind'] in ('brain', 'unchanged'):
|
||||
require(Path(run['job']['case_dir']) == case, 'Wrong registered runtime case')
|
||||
elif run['kind'] == 'oracle':
|
||||
require(Path(run['job']['oracle_case']) == case, 'Wrong registered oracle case')
|
||||
else:
|
||||
auth = read(run['job']['authority_file'])
|
||||
require(auth['case'] == dict(spec=A.pin(case / 'spec.json'), requests=A.pin(case / 'requests.npz')) and
|
||||
auth['boundary_id'] == name and auth['registration_sha256'] == reg_sha and
|
||||
auth['diagnostic_mode'] == call['diagnostic_mode'] and auth['input_policy'] == call['input_policy'] and
|
||||
auth['transition'] == call['transition'] and auth['parent'] == dict(directory=p['directory'],
|
||||
checkpoint_manifest_sha256=p['checkpoint_sha256']), 'Boundary authority differs from actual registered call')
|
||||
if call['runner'] == 'boundary_oracle':
|
||||
manifest = read(directory / 'oracle-manifest.json')
|
||||
actual = {k: v['sha256'] for k, v in tree(directory).items() if k != 'oracle-manifest.json'}
|
||||
require(manifest == dict(schema='conditioning-live-oracle-files-v1', complete=True, files_sha256=actual),
|
||||
'Live oracle exact manifest differs')
|
||||
kind = 'oracle'
|
||||
else:
|
||||
checkpoint_sha = receipt['result']['checkpoint_manifest_sha256']
|
||||
D.load_checkpoint(directory, checkpoint_sha)
|
||||
kind = 'updated' if call['runner'] == 'updated_continuation' else 'parent'
|
||||
record = B.load_record(directory, kind=kind); records[name] = record; B._complete(record)
|
||||
require(record['steps'] == call['steps'] and record['global_tick_offset'] == call['global_tick_offset'] and
|
||||
record['summary']['nodes'] == N and record['summary']['edges'] == EDGES and
|
||||
record['summary']['diagnostic_mode'] == call['diagnostic_mode'], 'Actual graph/clock/mode differs from registered call')
|
||||
if call['runner'] == 'updated_continuation':
|
||||
declared = _parent(reg, complete, name)
|
||||
require(declared['directory'] == str(directory) and declared['checkpoint_sha256'] == checkpoint_sha,
|
||||
'Saved parent registry differs from actual checkpoint')
|
||||
helper._verify_precision(receipt['environment'], record['summary']['apl_component']['environment'])
|
||||
cycle = read(EXP / 'receipts' / (name + '.cycle.json'))
|
||||
used_pins[str(EXP / 'receipts' / (name + '.cycle.json'))] = digest(EXP / 'receipts' / (name + '.cycle.json'))
|
||||
require(cycle['complete'] is True and same_json(cycle['call'], call) and cycle['source_registration_sha256'] == reg_sha,
|
||||
'Complete-cycle descriptor mismatch')
|
||||
for relative, evidence in cycle['output_inventory'].items():
|
||||
path = EXP / relative
|
||||
require(path.is_relative_to(EXP) and '..' not in Path(relative).parts and
|
||||
evidence == dict(sha256=digest(path), bytes=path.stat().st_size), 'Cycle immutable output changed')
|
||||
for name in ('mechanical--fresh-parent', 'performance--natural-light-fresh'):
|
||||
parent = _parent(reg, complete, name)
|
||||
require(parent['directory'] == str(verified[name]['output']) and parent['checkpoint_sha256'] == records[name]['manifest_sha256'],
|
||||
'New E source parent identity differs')
|
||||
updates[name] = _update_check(parent, verified, name + '--cpu-verify')
|
||||
worker = verified[name + '--original-E']
|
||||
require(worker['output'] == Path(parent['update_dir']) and
|
||||
worker['receipt']['result']['chain_receipt_sha256'] == digest(worker['output'] / 'chain-receipt.json'),
|
||||
'Original E actual process output differs')
|
||||
for arm in ('D1', 'mechanical'):
|
||||
oracle = records[arm + '--live-oracle']
|
||||
parent = imports['D1'] if arm == 'D1' else records['mechanical--fresh-parent']
|
||||
descriptor = _parent(reg, complete, reg['plan']['imported_parents']['D1']['role'] if arm == 'D1' else 'mechanical--fresh-parent')
|
||||
original_authority = Path(verified[arm + '--updated--reference']['job']['authority_file'])
|
||||
auth = read(original_authority)
|
||||
for mode in ('reference', 'light'):
|
||||
name = arm + '--updated--' + mode; authority = Path(verified[name]['job']['authority_file'])
|
||||
comparisons[arm + '-live-vs-' + mode] = B.compare_boundary(oracle, records[name], parent=parent,
|
||||
expected_before_sha256=auth['expected_effective_weight_before_sha256'],
|
||||
expected_after_sha256=auth['expected_effective_weight_after_sha256'],
|
||||
paired_authorities=(original_authority.read_bytes(), authority.read_bytes()))
|
||||
pending[arm] = _pending(parent, records[arm + '--updated--reference'], descriptor)
|
||||
for arm in ('D0', 'frozen'):
|
||||
for mode in ('reference', 'light'):
|
||||
comparisons[arm + '-old-C-vs-' + mode] = _pair(records[arm + '--old-C--reference'], records[arm + '--updated--' + mode])
|
||||
performance = 'performance--natural-light-fresh'
|
||||
comparisons['performance-natural-vs-AP'] = _pair(imports['D1'], records[performance])
|
||||
old = reg['parent_records'][reg['plan']['imported_parents']['D1']['role']]
|
||||
new = complete['parents'][performance]
|
||||
old_delta, new_delta = (_npz(x['after_overlay']['overlay_file']) for x in (old, new))
|
||||
checks['natural_fullcycle_after_delta_exact'] = set(old_delta) == set(new_delta) and all(B.bit_equal(v, new_delta[k]) for k, v in old_delta.items())
|
||||
checks['natural_fullcycle_U_receipt_exact'] = same_json(read(Path(old['update_dir']) / 'update-receipt.json'), read(Path(new['update_dir']) / 'update-receipt.json'))
|
||||
lineage = _lineage(reg, complete, verified, records)
|
||||
checks.update({name: result['numerical_exact'] for name, result in comparisons.items()})
|
||||
checks['D1_conditional_queue_exact'] = pending['D1']['conditional_ref_request_queue_exact'] and pending['D1']['reference_queue_and_ref_coverage_complete']
|
||||
checks['mechanical_conditional_queue_exact'] = pending['mechanical']['conditional_ref_request_queue_exact'] and pending['mechanical']['reference_queue_and_ref_coverage_complete']
|
||||
checks['actual_idle_and_probe_lineage'] = lineage['pass_all']
|
||||
exact, coverage, status = outcome(checks, pending)
|
||||
require(len(records) == 23 and sum(r['steps'] for r in records.values()) == 125200, 'Actual full-call/tick inventory differs')
|
||||
verify_pins(used_pins)
|
||||
for name, item in verified.items():
|
||||
require(tree(item['output']) == item['output_inventory'], 'Audited outputs changed')
|
||||
require(digest(complete_path) == complete_sha, 'Execution receipt changed')
|
||||
result = dict(schema='conditioning-execution-numerical-audit-v1', complete=True, status=status,
|
||||
pass_all=exact and coverage, numerical_exact=exact, registration_sha256=reg_sha,
|
||||
execution_complete_sha256=digest(complete_path), checks=checks, failed_checks=[k for k, v in checks.items() if not v],
|
||||
comparisons=comparisons, updates=updates, pending_edge_audits=pending, idle_probe_lineage=lineage,
|
||||
actual_new_brain_calls=len(records), actual_new_brain_ticks=sum(r['steps'] for r in records.values()),
|
||||
actual_processes=len(verified), actual_CPU_processes=sum(r['kind'] in ('update', 'validate_cpu') for r in verified.values()),
|
||||
actual_GPU_sampler_processes=sum(r['kind'] == 'sample' for r in verified.values()), all_actual_runs_finite=True,
|
||||
process_evidence={name: dict(kind=v['kind'], process_sha256=digest(v['paths']['process']), worker_sha256=digest(v['paths']['worker']),
|
||||
job_sha256=digest(v['paths']['job']), output_files=len(v['output_inventory']), recorded_exit_code=0) for name, v in verified.items()},
|
||||
observed_scope='Sparse events, complete final state/queues; full reference-only histories; authenticated recorded process evidence',
|
||||
light_intermediate_states_observed=False, AP_D1_changed_edge_coverage_is_not_required=True,
|
||||
historical_integrity_after_checked_here=False, sealed_here=False, brain_executed_here=False,
|
||||
U_recomputed_here=False, learning_pass_claimed=False, full_retention_experiment=False, candidate_generated=False)
|
||||
if save_report:
|
||||
save(EXP / 'audit/numerical-comparison.json', result)
|
||||
return result
|
||||
finally:
|
||||
for record in [*records.values(), *imports.values()]:
|
||||
B.close_record(record)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--registration-sha256', required=True)
|
||||
args = parser.parse_args()
|
||||
result = audit(args.registration_sha256)
|
||||
print(json.dumps({k: result[k] for k in ('complete', 'status', 'pass_all', 'actual_new_brain_calls', 'actual_processes')}), flush=True)
|
||||
@@ -0,0 +1,371 @@
|
||||
"""Pure CPU comparison of live-boundary and saved/restored diagnostics.
|
||||
|
||||
Array APIs require caller-authenticated records and immutable original graph /
|
||||
delta arrays. They do NOT authenticate registrations, process receipts or disk
|
||||
seals. load_record reads existing bytes without writing; its scope tags are not
|
||||
authority. No GPU, learning, membrane replay or physiological inference.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
PINS = {
|
||||
'engineering_compare.py': '5a2403f11bc08d65a9d242ac2cf9686b850e0c3680d65659f785e9b6b50c0238',
|
||||
'engineering_queue_audit.py': '6ddaec52f2a0b5d0c528d51230d372fe2344160aef5eccea6a95b6c5e61a574e',
|
||||
}
|
||||
AUTHORITY_FIELDS = {'schema', 'boundary_id', 'registration_sha256', 'transition', 'diagnostic_mode', 'input_policy',
|
||||
'case', 'parent', 'global_tick_offset', 'overlay_before', 'overlay_after',
|
||||
'expected_effective_weight_before_sha256', 'expected_effective_weight_after_sha256', 'update',
|
||||
'cpu_validation', 'source_files', 'frozen_inputs'}
|
||||
|
||||
|
||||
def _digest(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for block in iter(lambda: stream.read(8 << 20), b''):
|
||||
h.update(block)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _load(filename, expected):
|
||||
path = Path(__file__).resolve().parent.parent / 'olfactory-conditioning-lab-v1' / filename
|
||||
raw = path.read_bytes()
|
||||
if hashlib.sha256(raw).hexdigest() != expected:
|
||||
raise ValueError('Frozen pure helper source differs: ' + filename)
|
||||
module = ModuleType('conditioning_boundary_' + filename[:-3])
|
||||
module.__file__ = str(path)
|
||||
exec(compile(raw, str(path), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
C = _load('engineering_compare.py', PINS['engineering_compare.py'])
|
||||
require, bit_equal = C.require, C.bit_equal
|
||||
|
||||
|
||||
def _raw(a):
|
||||
h = hashlib.sha256()
|
||||
for start in range(0, len(a), 1 << 18):
|
||||
h.update(np.ascontiguousarray(a[start:start+(1 << 18)], dtype=a.dtype.newbyteorder('<')).tobytes())
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def load_record(directory, *, kind):
|
||||
"""Read actual inherited schemas; never disguise oracle as fixed-weight.
|
||||
|
||||
No external SHA pin is accepted or inferred here. The caller independently
|
||||
verifies the complete oracle/new/old checkpoint seal before this reader.
|
||||
"""
|
||||
require(kind in ('oracle', 'updated', 'parent'), 'Explicit record kind required')
|
||||
record = C.load_run(directory)
|
||||
try:
|
||||
summary = record['summary']
|
||||
if kind == 'oracle':
|
||||
require(summary.get('diagnostic_live_boundary') is True and summary.get('within_trial_weight_updates') is True and
|
||||
summary.get('production_backend') is False and summary.get('restored_from_checkpoint') is False,
|
||||
'Not a declared live-boundary diagnostic')
|
||||
record['boundary_snapshot'] = C._npz(Path(directory)/'boundary-snapshot.npz',
|
||||
('v','g','ref','counts','spike_ring','apl_state','apl_pending'))
|
||||
record['boundary_report'] = C._json(Path(directory)/'boundary-comparison.json')
|
||||
record['oracle_provenance'] = C._json(Path(directory)/'oracle-provenance.json')
|
||||
else:
|
||||
require(summary.get('within_trial_weight_updates') is False, 'Checkpoint segment updated during run')
|
||||
if kind == 'updated':
|
||||
require(summary.get('updated_boundary_schema') == 'conditioning-updated-boundary-v1' and
|
||||
summary.get('checkpoint_continuation_used') is True, 'Not an updated checkpoint segment')
|
||||
record['manifest_sha256'] = _digest(Path(directory)/'checkpoint-manifest.json')
|
||||
record['read_scope'] = kind
|
||||
return record
|
||||
except BaseException:
|
||||
C.close_run(record)
|
||||
raise
|
||||
|
||||
|
||||
def close_record(record):
|
||||
C.close_run(record)
|
||||
|
||||
|
||||
def _checks():
|
||||
checks = {}
|
||||
def check(name, okay):
|
||||
checks[name] = bool(okay)
|
||||
return checks, check
|
||||
|
||||
|
||||
def _complete(record):
|
||||
C.validate_run(record)
|
||||
s=record.get('summary',{})
|
||||
require(s.get('complete') is True and s.get('pass_all') is True and s.get('all_finite') is True and
|
||||
type(s.get('steps')) is int and s['steps']==record['steps']==s.get('completed_ticks') and
|
||||
type(s.get('nodes')) is int and s['nodes']==len(record['state']['v']) and
|
||||
s.get('precision')=='float64' and s.get('apl_precision')=='float32' and s.get('apl_delay_steps')==18,
|
||||
'Record summary is incomplete or has wrong numerical scope')
|
||||
|
||||
|
||||
def _canonical(value):
|
||||
return json.dumps(value,sort_keys=True,separators=(',',':'),ensure_ascii=False,allow_nan=False).encode('utf-8')
|
||||
|
||||
|
||||
def _paired_authorities(pair, oracle_sha, child_sha, child_mode):
|
||||
"""Bind actual raw JSON bytes and compare canonical content, not self hashes.
|
||||
|
||||
File SHA and canonical SHA are intentionally distinct. Only diagnostic_mode
|
||||
and boundary_id may differ; every other byte of canonical JSON must agree.
|
||||
"""
|
||||
require(type(pair) in (tuple,list) and len(pair)==2 and all(type(raw)is bytes for raw in pair),
|
||||
'paired_authorities must be the two original raw JSON byte strings')
|
||||
def unique(items):
|
||||
result={}
|
||||
for key,value in items:
|
||||
require(key not in result,'Duplicate authority JSON key: '+key);result[key]=value
|
||||
return result
|
||||
values=[json.loads(raw.decode('utf-8'),object_pairs_hook=unique,
|
||||
parse_constant=lambda value:(_ for _ in ()).throw(ValueError('Nonfinite authority JSON'))) for raw in pair]
|
||||
for value in values:
|
||||
require(type(value)is dict and set(value)==AUTHORITY_FIELDS and value.get('schema')=='conditioning-updated-boundary-v1',
|
||||
'Paired authority must use the exact boundary schema')
|
||||
require(type(value['boundary_id'])is str and bool(value['boundary_id']) and value['boundary_id'].strip()==value['boundary_id'],
|
||||
'Invalid paired boundary ID')
|
||||
hashes=[hashlib.sha256(raw).hexdigest() for raw in pair]
|
||||
allowed={'diagnostic_mode','boundary_id'}
|
||||
normalized=[{k:v for k,v in value.items() if k not in allowed} for value in values]
|
||||
differences=[key for key in sorted(AUTHORITY_FIELDS-allowed) if _canonical(values[0][key])!=_canonical(values[1][key])]
|
||||
checks=dict(actual_raw_file_SHA_bound=hashes==[oracle_sha,child_sha],
|
||||
explicit_modes=values[0]['diagnostic_mode']=='reference' and values[1]['diagnostic_mode']==child_mode,
|
||||
only_two_allowed_fields_differ=_canonical(normalized[0])==_canonical(normalized[1]))
|
||||
return dict(pass_all=all(checks.values()),checks=checks,raw_sha256=hashes,
|
||||
canonical_sha256=[hashlib.sha256(_canonical(value)).hexdigest() for value in values],
|
||||
common_content_canonical_sha256=[hashlib.sha256(_canonical(value)).hexdigest() for value in normalized],
|
||||
allowed_differences=sorted(allowed),disallowed_different_fields=differences,
|
||||
actual_disk_or_registration_authority_verified_here=False)
|
||||
|
||||
|
||||
def compare_boundary(oracle, continuation, *, parent, expected_before_sha256, expected_after_sha256, paired_authorities=None):
|
||||
"""Compare full oracle prefix/suffix against an authenticated parent/child.
|
||||
|
||||
Both reference and light children are supported. A light child's absent
|
||||
intermediate traces/hashes are explicitly unobserved, never called exact.
|
||||
No nonvacuity gate is invented here; changed-edge coverage is separate.
|
||||
"""
|
||||
for record in (oracle, continuation, parent): _complete(record)
|
||||
require(C._sha(expected_before_sha256) and C._sha(expected_after_sha256), 'External expected weight identities required')
|
||||
require(C._sha(parent.get('manifest_sha256')), 'Caller-authenticated parent manifest identity required')
|
||||
require(parent['global_tick_offset'] == oracle['global_tick_offset'] == 0, 'Need original fresh parent/live oracle')
|
||||
cut, steps = parent['steps'], continuation['steps']
|
||||
require(continuation['global_tick_offset'] == cut and oracle['steps'] == cut+steps, 'Wrong boundary/duration')
|
||||
n = len(parent['state']['v'])
|
||||
require(len(oracle['state']['v']) == len(continuation['state']['v']) == n, 'Population differs')
|
||||
require(oracle.get('traces') and oracle.get('state_hashes') is not None and oracle.get('queues') is not None,
|
||||
'Live oracle must retain full reference diagnostics')
|
||||
os, cs, ps = oracle['summary'], continuation['summary'], parent['summary']
|
||||
require(cs.get('diagnostic_mode') in ('reference','light'), 'Child recording mode is undeclared')
|
||||
reference = cs['diagnostic_mode'] == 'reference'
|
||||
if reference:
|
||||
require(continuation.get('traces') and continuation.get('state_hashes') is not None and continuation.get('queues') is not None,
|
||||
'Reference child diagnostics missing')
|
||||
else:
|
||||
require(not continuation.get('traces') and continuation.get('state_hashes') is None and continuation.get('queues') is None,
|
||||
'Light scope must not manufacture intermediate histories')
|
||||
if ps.get('diagnostic_mode')=='reference':
|
||||
require(parent.get('traces') and parent.get('state_hashes') is not None and parent.get('queues') is not None,
|
||||
'Reference parent diagnostics missing')
|
||||
checks, check = _checks()
|
||||
check('oracle.explicit_live_scope', os.get('diagnostic_mode') == 'reference' and
|
||||
os.get('diagnostic_live_boundary') is True and os.get('within_trial_weight_updates') is True and
|
||||
os.get('explicit_weight_switches') == 1 and type(os.get('explicit_weight_switches')) is int and
|
||||
os.get('boundary_tick') == cut and os.get('restored_from_checkpoint') is False and os.get('production_backend') is False)
|
||||
check('child.explicit_updated_scope', cs.get('within_trial_weight_updates') is False and
|
||||
cs.get('checkpoint_continuation_used') is True and cs.get('updated_boundary_schema') == 'conditioning-updated-boundary-v1' and
|
||||
cs.get('parent_checkpoint_manifest_sha256') == parent['manifest_sha256'] and
|
||||
cs.get('global_next_tick') == cut+steps and cs.get('boundary_transition') == 'epoch_update')
|
||||
check('weights.before', ps.get('effective_weights_raw_sha256') == os.get('initial_effective_weights_raw_sha256') == expected_before_sha256)
|
||||
check('weights.after', cs.get('effective_weights_raw_sha256') == os.get('effective_weights_raw_sha256') == expected_after_sha256)
|
||||
ot, on = oracle['state']['step'], oracle['state']['neuron_idx']
|
||||
split = int(np.searchsorted(ot,cut))
|
||||
check('prefix.events.tick',bit_equal(ot[:split],parent['state']['step']))
|
||||
check('prefix.events.neuron_idx',bit_equal(on[:split],parent['state']['neuron_idx']))
|
||||
check('prefix.counts',np.array_equal(np.bincount(on[:split],minlength=n),parent['state']['counts']))
|
||||
check('suffix.events.absolute_tick',np.array_equal(continuation['state']['step'].astype(np.int64)+cut,ot[split:].astype(np.int64)))
|
||||
check('suffix.events.neuron_idx',bit_equal(continuation['state']['neuron_idx'],on[split:]))
|
||||
check('suffix.segment_counts',np.array_equal(continuation['state']['counts'],np.bincount(on[split:],minlength=n)))
|
||||
check('prefix_plus_suffix.total_counts',np.array_equal(parent['state']['counts'].astype(np.int64)+continuation['state']['counts'],oracle['state']['counts']))
|
||||
for name in ('v','g','ref'):check('final.'+name,bit_equal(continuation['state'][name],oracle['state'][name]))
|
||||
check('final.phase_normalized_spike_ring',bit_equal(C.normalized_ring(continuation['terminal']),C.normalized_ring(oracle['terminal'])))
|
||||
for name in ('apl_pending','apl_state'):check('final.'+name,bit_equal(continuation['terminal'][name],oracle['terminal'][name]))
|
||||
snapshot = oracle.get('boundary_snapshot')
|
||||
require(type(snapshot) is dict and set(snapshot) == {'v','g','ref','counts','spike_ring','apl_state','apl_pending'}, 'Missing live boundary snapshot')
|
||||
for name in ('v','g','ref','counts'):check('boundary.live_parent.'+name,bit_equal(snapshot[name],parent['state'][name]))
|
||||
for name in ('spike_ring','apl_state','apl_pending'):check('boundary.live_parent.'+name,bit_equal(snapshot[name],parent['terminal'][name]))
|
||||
report, provenance = oracle.get('boundary_report'), oracle.get('oracle_provenance')
|
||||
require(type(report) is dict and type(provenance) is dict, 'Missing explicit oracle provenance/report')
|
||||
paired=None
|
||||
authority_matches=(C._sha(cs.get('boundary_authority_sha256')) and
|
||||
provenance.get('authority_sha256')==cs['boundary_authority_sha256'])
|
||||
if paired_authorities is not None:
|
||||
paired=_paired_authorities(paired_authorities,provenance.get('authority_sha256'),
|
||||
cs.get('boundary_authority_sha256'),cs['diagnostic_mode'])
|
||||
authority_matches=paired['pass_all']
|
||||
check('oracle.boundary_metadata',report.get('complete') is True and report.get('boundary_tick') == cut and
|
||||
report.get('parent_checkpoint_manifest_sha256') == parent['manifest_sha256'] and report.get('restore_called') is False and
|
||||
report.get('initial_state_replaced') is False and report.get('queues_replaced') is False and report.get('existing_weights_replaced_once') is True and
|
||||
report.get('before_effective_sha256') == expected_before_sha256 and report.get('after_effective_sha256') == expected_after_sha256)
|
||||
check('oracle.authority_matches_child',provenance.get('schema') == 'conditioning-live-boundary-oracle-v1' and
|
||||
provenance.get('complete') is True and provenance.get('restore_called') is False and
|
||||
provenance.get('prefix_sparse_events_exact') is True and provenance.get('learning_pass_claimed') is False and
|
||||
authority_matches)
|
||||
for label,record,start,stop in (('prefix',parent,0,cut),('suffix',continuation,cut,cut+steps)):
|
||||
req=oracle['requests'];lo,hi=np.searchsorted(req[:,0],(start,stop))
|
||||
actual=record['requests'].copy();actual[:,0]+=start
|
||||
check(label+'.requests_all_five_fields',bit_equal(actual,req[lo:hi]))
|
||||
if record.get('traces'):
|
||||
for name in C.TRACE_FILES:check(label+'.trace.'+name,bit_equal(record['traces'][name],oracle['traces'][name][start:stop]))
|
||||
if record.get('state_hashes') is not None:
|
||||
check(label+'.state_hashes',all(all(row[key]==oracle['state_hashes'][start+t][key] for key in C.HASH_FIELDS)
|
||||
for t,row in enumerate(record['state_hashes'])))
|
||||
if record.get('queues') is not None:
|
||||
check(label+'.queue_order_acceptance',all(all(row[key]==oracle['queues'][start+t][key] for key in C.QUEUE_FIELDS)
|
||||
for t,row in enumerate(record['queues'])))
|
||||
consume=min(steps,18)
|
||||
if reference:check('boundary.applied_parent_APL',bit_equal(continuation['traces']['applied'][:consume],parent['terminal']['apl_pending'][:consume]))
|
||||
if steps<18:check('boundary.unconsumed_parent_APL',bit_equal(continuation['terminal']['apl_pending'][:18-steps],parent['terminal']['apl_pending'][steps:]))
|
||||
if steps<19:check('boundary.unwritten_parent_spike_slots',bit_equal(continuation['terminal']['spike_ring'][steps:],C.normalized_ring(parent['terminal'])[steps:]))
|
||||
exact=all(checks.values())
|
||||
return dict(schema='conditioning-live-vs-restored-comparison-v1',pass_all=exact,numerical_exact=exact,
|
||||
status='EXACT-RECORDED-BOUNDARY-SCOPE-NOT-LEARNING' if exact else 'FAIL-BOUNDARY-NUMERICAL',checks=checks,
|
||||
failed_checks=[k for k,v in checks.items() if not v],boundary_tick=cut,suffix_steps=steps,neurons=n,
|
||||
child_mode=cs['diagnostic_mode'],suffix_reference_diagnostics_compared=reference,
|
||||
paired_authority_audit=paired,
|
||||
light_intermediate_states_observed=False,light_per_tick_identity_claimed=False,
|
||||
queue_joint_hash_compared=False,queue_joint_hash_exclusion='Local tick headers differ; independent audit checks each actual header',
|
||||
changed_candidate_pending_arrival_coverage_verified=False,external_file_authority_verified_here=False,
|
||||
independent_membrane_replay_performed=False,learning_pass_claimed=False,candidate_generated=False)
|
||||
|
||||
|
||||
def _effective_hash(base, apl, rows, values):
|
||||
h=hashlib.sha256()
|
||||
for start in range(0,len(base),1<<18):
|
||||
stop=min(start+(1<<18),len(base));a=np.array(base[start:stop],copy=True)
|
||||
a[apl[start:stop]]=np.float64(0)
|
||||
lo,hi=np.searchsorted(rows,(start,stop));a[rows[lo:hi]-start]=values[lo:hi]
|
||||
h.update(np.ascontiguousarray(a,dtype='<f8').tobytes())
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _candidates(ptr,src,dst,edge_id,base,apl,ids,before,after,Q):
|
||||
n,e=Q._graph(ptr,dst,edge_id,base)
|
||||
require(isinstance(src,np.ndarray) and src.dtype==np.int32 and src.shape==(e,), 'Invalid actual CSR source array')
|
||||
require(isinstance(apl,np.ndarray) and apl.dtype==np.bool_ and apl.shape==(e,), 'Invalid fast APL mask')
|
||||
for start in range(0,e,1<<18):
|
||||
stop=min(start+(1<<18),e)
|
||||
expected=np.searchsorted(ptr[1:],np.arange(start,stop,dtype=np.int64),side='right')
|
||||
require(np.array_equal(src[start:stop],expected),'Source array disagrees with original CSR ordering')
|
||||
require(isinstance(ids,np.ndarray) and ids.dtype==np.int64 and ids.ndim==1 and len(ids)>0 and
|
||||
np.all(ids>=0) and np.all(ids[1:]>ids[:-1]),'Candidate IDs must preserve canonical sorted unique order')
|
||||
for name,a in (('before',before),('after',after)):
|
||||
require(isinstance(a,np.ndarray) and a.dtype==np.float32 and a.shape==ids.shape and
|
||||
np.isfinite(a).all() and np.all(a<=0),'Invalid f32 mV delta '+name)
|
||||
require(np.all(after<=before),'This diagnostic admits only existing depression, not potentiation')
|
||||
rows=np.searchsorted(edge_id,ids)
|
||||
require(np.all(rows<e) and np.array_equal(edge_id[rows],ids),'Candidate missing from actual graph')
|
||||
require(not np.any(apl[rows]) and np.all(base[rows]>0),'Candidate overlaps APL or has nonpositive original weight')
|
||||
values=[]
|
||||
for delta in (before,after):
|
||||
a=base[rows].copy();nz=delta!=np.float32(0)
|
||||
a[nz]=np.add(a[nz],np.multiply(delta[nz].astype(np.float64),np.float64(.001)))
|
||||
require(np.isfinite(a).all() and np.all(a>0),'Effective candidate weight changed sign/nonfinite')
|
||||
values.append(a)
|
||||
return n,e,rows,values[0],values[1]
|
||||
|
||||
|
||||
def audit_changed_pending(parent,child,*,ptr,src,dst,edge_id,base_weights,apl_mask,
|
||||
candidate_edge_id,delta_before,delta_after,input_pins):
|
||||
"""Conditional ref/request/CSR audit plus a changed-edge crossing witness.
|
||||
|
||||
Post-threshold ref=22 precedes arrivals; requests use prior ref<=1. Every
|
||||
real edge remains in source/CSR order, including rejected/zero weights.
|
||||
Witnesses require an actual numeric effective-weight change and accepted
|
||||
arrival emitted before cut and arriving within the child. This is not a
|
||||
unique-cause claim and does not independently predict membrane spikes.
|
||||
"""
|
||||
require(type(input_pins)is dict and input_pins and all(type(k)is str and C._sha(v) for k,v in input_pins.items()),'Caller input anchors required')
|
||||
Q=_load('engineering_queue_audit.py',PINS['engineering_queue_audit.py'])
|
||||
for record in (parent,child):_complete(record)
|
||||
n,e,rows,before,after=_candidates(ptr,src,dst,edge_id,base_weights,apl_mask,candidate_edge_id,delta_before,delta_after,Q)
|
||||
require(parent['global_tick_offset']==0 and child['global_tick_offset']==parent['steps'],'Fresh parent / exact child boundary required')
|
||||
require(len(parent['state']['v'])==len(child['state']['v'])==n,'Record/graph population mismatch')
|
||||
require(all(type(record['summary'].get('edges')) is int and record['summary']['edges']==e for record in (parent,child)),
|
||||
'Record/graph edge count differs')
|
||||
cut,total=parent['steps'],parent['steps']+child['steps']
|
||||
require(total<=np.iinfo(np.int32).max,'Diagnostic clock exceeds exact int32 event range')
|
||||
before_sha=_effective_hash(base_weights,apl_mask,rows,before);after_sha=_effective_hash(base_weights,apl_mask,rows,after)
|
||||
require(parent['summary'].get('effective_weights_raw_sha256')==before_sha and
|
||||
child['summary'].get('effective_weights_raw_sha256')==after_sha,'Delta/base arithmetic mismatches actual runtime effective SHA')
|
||||
changed=(before.view(np.uint64)!=after.view(np.uint64)) & (before!=after)
|
||||
changed_rows=rows[changed];changed_ids=candidate_edge_id[changed]
|
||||
effective=base_weights.copy();effective[apl_mask]=np.float64(0);effective[rows]=after
|
||||
tick=np.concatenate((parent['state']['step'],child['state']['step']+np.int32(cut)))
|
||||
node=np.concatenate((parent['state']['neuron_idx'],child['state']['neuron_idx']))
|
||||
request=np.concatenate((parent['requests'],child['requests']+np.array([cut,0,0,0,0],np.int64)))
|
||||
ref=np.zeros(n,np.int32);differences=[];difference_count=0
|
||||
def check(ok,field,t):
|
||||
nonlocal difference_count
|
||||
if not ok:
|
||||
difference_count+=1
|
||||
if len(differences)<60:differences.append(dict(field=field,global_tick=t))
|
||||
coverage=dict(changed_candidate_crossing_arrivals=0,accepted_changed_candidate_crossing_arrivals=0,
|
||||
rejected_changed_candidate_crossing_arrivals=0,first_witness=None)
|
||||
full=all(record.get('queues') is not None and record.get('state_hashes') is not None for record in (parent,child))
|
||||
for t in range(total):
|
||||
record,local=(parent,t) if t<cut else (child,t-cut)
|
||||
rlo,rhi=np.searchsorted(request[:,0],(t,t+1));requested=request[rlo:rhi,1]
|
||||
accepted=ref[requested]<=1
|
||||
expected=request[rlo:rhi].copy();expected[:,2]=1;expected[:,3]=accepted;expected[:,4]=~accepted
|
||||
check(bit_equal(request[rlo:rhi],expected),'request.acceptance',t)
|
||||
np.maximum(ref-np.int32(1),np.int32(0),out=ref)
|
||||
lo,hi=np.searchsorted(tick,(t,t+1));fired=node[lo:hi]
|
||||
check(np.all(ref[fired]==0),'spike_during_refractory',t)
|
||||
check(np.isin(requested[accepted],fired,assume_unique=True).all(),'accepted_request_without_spike',t)
|
||||
ref[fired]=22
|
||||
lo,hi=np.searchsorted(tick,(t-18,t-17));sources=node[lo:hi] if t>=18 else node[:0]
|
||||
qrows,_,_=Q._queue(t,local,sources,ref,ptr,dst,edge_id,effective,[])
|
||||
expected_queue=qrows[0] if t<cut else qrows[1]
|
||||
if record.get('queues') is not None:
|
||||
check(record['queues'][local]==expected_queue,'source_ordered_queue_all_fields',t)
|
||||
if record.get('state_hashes') is not None:
|
||||
check(record['state_hashes'][local]['ref_sha256']==_raw(ref),'ref_hash',t)
|
||||
if local==record['steps']-1:check(bit_equal(record['state']['ref'],ref),'final_ref',t)
|
||||
if t-18<cut<=t and t<total:
|
||||
for source in sources:
|
||||
lo,hi=np.searchsorted(changed_rows,(ptr[source],ptr[source+1]))
|
||||
for at in range(int(lo),int(hi)):
|
||||
row=int(changed_rows[at]);target=int(dst[row]);accepted_edge=ref[target]==0
|
||||
coverage['changed_candidate_crossing_arrivals']+=1
|
||||
coverage['accepted_changed_candidate_crossing_arrivals' if accepted_edge else 'rejected_changed_candidate_crossing_arrivals']+=1
|
||||
if accepted_edge and coverage['first_witness'] is None:
|
||||
original=int(np.searchsorted(rows,row))
|
||||
coverage['first_witness']=dict(global_edge_id=int(changed_ids[at]),csr_row=row,
|
||||
source_neuron_idx=int(source),target_neuron_idx=target,source_spike_global_tick=t-18,
|
||||
arrival_global_tick=t,arrival_child_local_tick=t-cut,post_threshold_target_ref=0,accepted=True,
|
||||
before_weight_SI_volt=float(before[original]),after_weight_SI_volt=float(after[original]),
|
||||
before_weight_f64_le_hex=np.asarray(before[original],dtype='<f8').tobytes().hex(),
|
||||
after_weight_f64_le_hex=np.asarray(after[original],dtype='<f8').tobytes().hex(),
|
||||
delta_before_f32_mv_hex=np.asarray(delta_before[original],dtype='<f4').tobytes().hex(),
|
||||
delta_after_f32_mv_hex=np.asarray(delta_after[original],dtype='<f4').tobytes().hex(),
|
||||
unique_cause_or_necessity_claim=False)
|
||||
exact=difference_count==0;witness=coverage['first_witness'] is not None;passed=exact and full and witness
|
||||
return dict(schema='conditioning-changed-pending-edge-audit-v1',pass_all=passed,
|
||||
status='FAIL-QUEUE-REF-REQUEST' if not exact else ('PASS-CHANGED-PENDING-EDGE-SCOPE' if passed else 'INCOMPLETE-CHANGED-EDGE-COVERAGE'),
|
||||
conditional_ref_request_queue_exact=exact,reference_queue_and_ref_coverage_complete=full,
|
||||
accepted_changed_edge_witness_verified=passed,difference_count=difference_count,differences=differences,
|
||||
differences_truncated=difference_count>len(differences),coverage=coverage,neurons=n,edges=e,boundary_tick=cut,
|
||||
changed_delta_bit_count=int(np.count_nonzero(delta_before.view(np.uint32)!=delta_after.view(np.uint32))),
|
||||
changed_effective_numeric_count=int(changed.sum()),before_effective_sha256=before_sha,after_effective_sha256=after_sha,
|
||||
supplied_input_pins=dict(input_pins),array_raw_sha256={key:_raw(a) for key,a in dict(ptr=ptr,src=src,dst=dst,edge_id=edge_id,
|
||||
base_weights=base_weights,apl_mask=apl_mask,candidate_edge_id=candidate_edge_id,delta_before=delta_before,delta_after=delta_after).items()},
|
||||
delay_steps=18,refractory_steps=22,actual_membrane_dynamics_independently_replayed=False,
|
||||
observed_spikes_condition_the_audit=True,external_file_authority_verified_here=False,learning_pass_claimed=False)
|
||||
@@ -0,0 +1,219 @@
|
||||
"""Diagnostic live-boundary oracle, NOT a production/learned brain backend.
|
||||
|
||||
Re-execute a fresh parent's exact inputs/old overlay, without calling restore.
|
||||
At the declared epoch boundary compare live state to the sealed parent, replace
|
||||
only existing candidate weights with base+delta-after, and continue the original
|
||||
reference loop. One whitelisted hook is independently removable from its AST.
|
||||
The diagnostic has an explicit within-run boundary switch; old C must NOT load
|
||||
its output as an unchanged-weight checkpoint.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import copy
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
LAB=Path(__file__).resolve().parent.parent/'olfactory-conditioning-lab-v1'
|
||||
C_SHA='0b8e8e0a6a23a079dc62a88355ce355d53b3ae22f6665519a8f6aef2dcfc5aba'
|
||||
HOOK="if tick == _oracle.boundary_tick:\n _oracle.switch(tick, weights, v, g, ref, counts, ring, apl_ring, apl, out_dir)"
|
||||
|
||||
|
||||
def require(ok,message):
|
||||
if not ok:raise ValueError(message)
|
||||
|
||||
|
||||
def digest(path):
|
||||
h=hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for b in iter(lambda:stream.read(8<<20),b''):h.update(b)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def load(name,path,sha):
|
||||
raw=Path(path).read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest()==sha and name not in sys.modules,'Unverified oracle source/module binding')
|
||||
spec=importlib.util.spec_from_file_location(name,path);module=importlib.util.module_from_spec(spec)
|
||||
sys.modules[name]=module;exec(compile(raw,str(path),'exec'),module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def frozen():
|
||||
return load('_conditioning_live_oracle_C',LAB/'runtime_continuation.py',C_SHA)
|
||||
|
||||
|
||||
def derive_oracle(c,source_bytes):
|
||||
tree,inherited=c.R.derive_ast(source_bytes,'reference');before=copy.deepcopy(tree)
|
||||
loops=[n for n in ast.walk(tree) if isinstance(n,ast.For) and isinstance(n.target,ast.Name) and n.target.id=='tick']
|
||||
require(len(loops)==1,'Unique frozen timestep loop required')
|
||||
loops[0].body.insert(0,ast.parse(HOOK).body[0]);tree=ast.fix_missing_locations(tree)
|
||||
rollback=copy.deepcopy(tree)
|
||||
matches=[n for n in ast.walk(rollback) if isinstance(n,ast.For) and isinstance(n.target,ast.Name) and n.target.id=='tick']
|
||||
require(ast.unparse(matches[0].body[0])==HOOK,'Oracle hook changed')
|
||||
del matches[0].body[0]
|
||||
require(c.R._dump(rollback)==c.R._dump(before),'Unlisted oracle mathematical AST edit')
|
||||
return tree,dict(base=inherited,explicit_boundary_hook=HOOK,full_AST_rollback_identical=True,
|
||||
frozen_within_epoch_math_unchanged=True,restore_called=False,
|
||||
diagnostic_live_weight_switch=True,production_backend=False,
|
||||
ast_sha256=hashlib.sha256(c.R._dump(tree).encode()).hexdigest())
|
||||
|
||||
|
||||
def expected_candidate_values(base_si,edge_ids,after_delta):
|
||||
"""Base+f32-mV delta with the frozen separate f64 multiply/add contract."""
|
||||
require(base_si.dtype==np.float64 and base_si.ndim==1 and edge_ids.dtype==np.int64 and edge_ids.ndim==1 and
|
||||
after_delta.dtype==np.float32 and after_delta.shape==edge_ids.shape,'Wrong candidate bridge dtype/shape')
|
||||
require(np.all((edge_ids>=0)&(edge_ids<len(base_si))) and np.all(edge_ids[1:]>edge_ids[:-1]),'Invalid existing edge IDs')
|
||||
require(np.isfinite(after_delta).all() and np.all(after_delta<=0),'Invalid depression delta')
|
||||
result=base_si[edge_ids].copy();nonzero=after_delta!=np.float32(0)
|
||||
result[nonzero]=np.add(result[nonzero],np.multiply(after_delta[nonzero].astype(np.float64),np.float64(.001)))
|
||||
require(np.isfinite(result).all() and np.all(result>0),'Candidate sign changed')
|
||||
return result
|
||||
|
||||
|
||||
def boundary_arrays(parent,tick,v,g,ref,counts,ring,apl_ring,apl_state):
|
||||
require(type(tick)is int and tick==parent['steps']==parent['global_next_tick'] and parent['fresh'] is True,
|
||||
'Oracle needs the exact fresh-parent boundary')
|
||||
arrays=dict(v=v,g=g,ref=ref,counts=counts,spike_ring=ring,apl_state=apl_state,
|
||||
apl_pending=np.concatenate((apl_ring[tick%18:],apl_ring[:tick%18]),axis=0))
|
||||
expected={**{k:parent['state'][k] for k in ('v','g','ref','counts')},
|
||||
**{k:parent['terminal'][k] for k in ('spike_ring','apl_state','apl_pending')}}
|
||||
checks={k:(a.dtype==expected[k].dtype and a.shape==expected[k].shape and a.tobytes()==expected[k].tobytes())
|
||||
for k,a in arrays.items()}
|
||||
require(all(checks.values()),'Live prefix differs from sealed parent: '+str([k for k,v in checks.items() if not v]))
|
||||
return arrays,checks
|
||||
|
||||
|
||||
def runtime_class(c):
|
||||
r=c.R
|
||||
class Oracle(r._Runtime):
|
||||
def __init__(self,*args,boundary,**kwargs):
|
||||
super().__init__(*args,**kwargs);self.boundary=boundary;self.parent=boundary['parent']
|
||||
self.boundary_tick=self.parent['steps'];self.switches=0
|
||||
|
||||
def tensor_sha(self,value):
|
||||
h=hashlib.sha256()
|
||||
for start in range(0,value.numel(),1<<20):h.update(value[start:start+(1<<20)].cpu().numpy().astype('<f8',copy=False).tobytes())
|
||||
return h.hexdigest()
|
||||
|
||||
def install(self,weights,graph,apl_mask,upload,out_dir,inherited,device):
|
||||
require(self.installations==0 and len(graph['nodes'])==166700 and len(graph['edge_id'])==25582938 and
|
||||
int(apl_mask.sum())==5845,'Only one intact frozen fullgraph installation')
|
||||
prior=self.helper.map_installation(graph['weights'],graph['edge_id'],apl_mask,self.plan)
|
||||
following=self.helper.map_installation(graph['weights'],graph['edge_id'],apl_mask,self.boundary['after_plan'])
|
||||
require(prior['missing_candidate_count']==following['missing_candidate_count']==0,'Incomplete candidate mapping')
|
||||
if len(prior['rows']):
|
||||
idx=upload(prior['rows'],self.torch.int64)
|
||||
change=upload(self.plan['plastic_delta_mv'][self.plan['plastic_delta_mv']!=np.float32(0)],self.torch.float64)*.001
|
||||
weights[idx]=weights[idx]+change
|
||||
require(self.helper.bit_equal(weights[idx].cpu().numpy(),prior['expected_si']),'Initial SI bridge mismatch')
|
||||
base_sha,before_sha=self.helper.expected_hashes(graph['weights'],apl_mask,prior)
|
||||
_,after_sha=self.helper.expected_hashes(graph['weights'],apl_mask,following)
|
||||
require(before_sha==self.parent['summary']['effective_weights_raw_sha256'] and self.tensor_sha(weights)==before_sha,
|
||||
'Oracle before weights differ from parent')
|
||||
auth=self.boundary['value']
|
||||
require(before_sha==auth['expected_effective_weight_before_sha256'] and after_sha==auth['expected_effective_weight_after_sha256'],
|
||||
'External expected weights differ')
|
||||
mask=self.plan['edge_id'];require(np.array_equal(graph['edge_id'][mask],mask),'Noncanonical candidate positions')
|
||||
expected=expected_candidate_values(graph['weights'],mask,self.boundary['after_plan']['plastic_delta_mv'])
|
||||
nz=self.boundary['after_plan']['plastic_delta_mv']!=np.float32(0)
|
||||
require(self.helper.bit_equal(expected[nz],following['expected_si']),'Independent after bridge differs')
|
||||
self.rows_gpu=upload(mask,self.torch.int64);self.after_gpu=upload(expected,self.torch.float64)
|
||||
self.before_sha,self.after_sha=before_sha,after_sha;self.effective_sha=before_sha
|
||||
self.observer=r.FiniteObserver(self.torch,device);self.installations=1
|
||||
for role,target in (('before_overlay','overlay-before-input.npz'),('before_manifest','overlay-before-manifest.json'),
|
||||
('after_overlay','overlay-after-input.npz'),('after_manifest','overlay-after-manifest.json')):
|
||||
source=self.boundary['paths'][role];r._copy_input(source,out_dir/target,r.digest(source))
|
||||
r._save(out_dir/'overlay-audit.json',dict(schema='conditioning-live-oracle-overlay-v1',complete=True,
|
||||
base_weights_raw_sha256=base_sha,initial_effective_weights_raw_sha256=before_sha,
|
||||
planned_final_effective_weights_raw_sha256=after_sha,weights_updated_during_run=True,
|
||||
one_explicit_epoch_boundary=True,existing_candidates_only=True,production_checkpoint=False))
|
||||
|
||||
def switch(self,tick,weights,v,g,ref,counts,ring,apl_ring,apl,out_dir):
|
||||
require(self.installations==1 and self.switches==0 and tick==self.boundary_tick,'Wrong/repeated boundary switch')
|
||||
arrays,checks=boundary_arrays(self.parent,tick,*[a.cpu().numpy().copy() for a in
|
||||
(v,g,ref,counts,ring,apl_ring,apl.state)])
|
||||
require(self.tensor_sha(weights)==self.before_sha,'Weights changed before authorized boundary')
|
||||
# Replacement from ORIGINAL base; never increment by delta-after again.
|
||||
weights[self.rows_gpu]=self.after_gpu
|
||||
require(self.tensor_sha(weights)==self.after_sha,'Live boundary after-weight mismatch')
|
||||
self.effective_sha=self.after_sha;self.switches=1
|
||||
with (out_dir/'boundary-snapshot.npz').open('xb') as f:np.savez_compressed(f,**arrays)
|
||||
r._save(out_dir/'boundary-comparison.json',dict(complete=True,boundary_tick=tick,checks=checks,
|
||||
parent_checkpoint_manifest_sha256=self.parent['manifest_sha256'],restore_called=False,
|
||||
initial_state_replaced=False,queues_replaced=False,existing_weights_replaced_once=True,
|
||||
before_effective_sha256=self.before_sha,after_effective_sha256=self.after_sha))
|
||||
|
||||
def finish(self,*args,**kwargs):
|
||||
require(self.switches==1,'Expected diagnostic boundary did not execute')
|
||||
return super().finish(*args,**kwargs)
|
||||
|
||||
def summary(self,value):
|
||||
result=super().summary(value)
|
||||
result.update(within_trial_weight_updates=True,diagnostic_live_boundary=True,
|
||||
boundary_tick=self.boundary_tick,explicit_weight_switches=self.switches,
|
||||
effective_weights_raw_sha256=self.after_sha,initial_effective_weights_raw_sha256=self.before_sha,
|
||||
restored_from_checkpoint=False,production_backend=False,
|
||||
pass_all_scope='One diagnostic live boundary and finite integrity; no learning/equivalence claim')
|
||||
return result
|
||||
return Oracle
|
||||
|
||||
|
||||
def run(authority_file,authority_sha,updated_source_sha,oracle_case,spec_sha,requests_sha,out_dir,build_root):
|
||||
require(sys.dont_write_bytecode,'Use Python -B')
|
||||
d=load('_conditioning_live_oracle_updated',Path(__file__).with_name('updated_continuation.py'),updated_source_sha)
|
||||
boundary=d.validate_authority(authority_file,authority_sha)
|
||||
c=d.C;r=c.R;parent=boundary['parent'];paths=boundary['paths'];value=boundary['value']
|
||||
require(value['transition']=='epoch_update' and parent['fresh'] is True,'Live oracle supports one verified fresh epoch update only')
|
||||
case=Path(oracle_case).resolve(strict=True)
|
||||
require(digest(case/'spec.json')==spec_sha and digest(case/'requests.npz')==requests_sha,'Combined oracle input differs from external pins')
|
||||
spec=r._read_json(case/'spec.json');previous=c._parent_spec(parent);suffix=boundary['spec']
|
||||
require(spec.get('within_trial_weight_updates') is True and spec.get('diagnostic_boundary_tick')==parent['steps'],
|
||||
'Oracle must explicitly declare its one within-run boundary')
|
||||
r.validate_spec({**spec,'within_trial_weight_updates':False},case)
|
||||
require(spec['steps']==parent['steps']+suffix['steps'],'Combined oracle clock differs')
|
||||
for key in ('dt_ms','model','apl','apl_delay_steps','graph_dir','apl_bundle_dir','coefficients_path'):
|
||||
require(spec[key]==previous[key]==suffix[key],'Oracle changes frozen input/dynamics: '+key)
|
||||
def requests(path):
|
||||
with np.load(path,allow_pickle=False) as f:
|
||||
require(set(f.files)=={'tick','neuron_idx'},'Invalid request archive')
|
||||
a={k:f[k].copy() for k in f.files}
|
||||
require(all(v.dtype==np.int32 and v.ndim==1 for v in a.values()),'Invalid request dtype')
|
||||
return a
|
||||
epoch=r._read_json(paths['epoch_authority'])
|
||||
old=requests(epoch['files']['requests']['path']);new=requests(paths['requests']);combined=requests(case/'requests.npz')
|
||||
expected={'tick':np.concatenate((old['tick'],new['tick']+parent['steps'])),
|
||||
'neuron_idx':np.concatenate((old['neuron_idx'],new['neuron_idx']))}
|
||||
require(all(np.array_equal(combined[k],expected[k]) for k in expected),'Oracle prefix/suffix requests are not exact')
|
||||
protected={*parent['ancestry_directories'],*[Path(p).parent for p in boundary['pins']]}
|
||||
case,out,build=r.execution_paths(case,out_dir,build_root,protected)
|
||||
inputs={**boundary['pins'],str(case/'spec.json'):spec_sha,str(case/'requests.npz'):requests_sha,str(Path(__file__).resolve()):digest(__file__)}
|
||||
aj_dir=Path(boundary['before_meta']['aj_model_dir']).resolve()
|
||||
r._load('timing_queue',aj_dir/'timing_queue.py',r.PINS['apl-timing-lab-v1/timing_queue.py'])
|
||||
aj=r._load('conditioning_live_oracle_AJ',aj_dir/'gpu_timing.py',r.AJ_SHA)
|
||||
runtime=runtime_class(c)('reference',spec,boundary['helper'],boundary['before_plan'],boundary['before_meta'],
|
||||
inputs,aj.torch,paths['before_overlay'],paths['before_manifest'],boundary=boundary)
|
||||
tree,audit=derive_oracle(c,Path(aj.__file__).read_bytes())
|
||||
namespace=dict(aj.__dict__);namespace.update(__name__=__name__+'.derived',__file__=str(Path(__file__).resolve()),
|
||||
_runtime=runtime,_oracle=runtime,write_json=runtime.write_json)
|
||||
exec(compile(tree,str(Path(__file__).resolve())+'::live-boundary-AST','exec'),namespace)
|
||||
inherited=namespace['run_gpu'](case,out,build)
|
||||
require(runtime.finished and runtime.switches==1 and inherited['complete'],'Incomplete live-boundary oracle')
|
||||
with np.load(out/'state.npz',allow_pickle=False) as state:
|
||||
prefix=state['step']<parent['steps']
|
||||
require(np.array_equal(state['step'][prefix],parent['state']['step']) and
|
||||
np.array_equal(state['neuron_idx'][prefix],parent['state']['neuron_idx']),'Oracle prefix events differ from actual parent')
|
||||
require(all(digest(p)==sha for p,sha in inputs.items()),'Oracle source/input drift')
|
||||
c.load_checkpoint(parent['directory'],parent['manifest_sha256'])
|
||||
summary=r._read_json(out/'summary.json');require(summary==runtime.summary(inherited),'Oracle summary mismatch')
|
||||
r._save(out/'oracle-provenance.json',dict(schema='conditioning-live-boundary-oracle-v1',complete=True,
|
||||
source_sha256=digest(__file__),updated_source_sha256=updated_source_sha,authority_sha256=authority_sha,
|
||||
input_sha256=inputs,ast=audit,restore_called=False,old_globals_patched=False,
|
||||
prefix_sparse_events_exact=True,production_checkpoint=False,learning_pass_claimed=False))
|
||||
files={p.relative_to(out).as_posix():digest(p) for p in out.rglob('*') if p.is_file()}
|
||||
r._save(out/'oracle-manifest.json',dict(schema='conditioning-live-oracle-files-v1',complete=True,files_sha256=files))
|
||||
return summary
|
||||
@@ -0,0 +1,249 @@
|
||||
"""Pure, finite boundary-validation proposal; no disk, sampling, runtime or GPU.
|
||||
|
||||
Pins and claimed array identities are descriptors, NOT verification of disk bytes,
|
||||
biological membership, registration or execution permission. The coordinator must
|
||||
authenticate them and safely materialize cases. This is not acquisition, a full
|
||||
retention experiment, or evidence of learning. No thresholds/model knobs change.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import deepcopy
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
SCHEMA = 'conditioning-boundary-plan-v1-draft'
|
||||
MASTER = 20260930
|
||||
BLOCK = 'physiological__PAM15__reinforce_A__rep01'
|
||||
COMPARTMENT = "y5B'2a"
|
||||
N, CANDIDATES = 166700, 14232
|
||||
AP_ROOT = '/data/digital-drosophila/experiments/phase4ap-conditioning-interface-v2'
|
||||
TEMPLATE_PAYLOAD_SHA256 = 'fbd892d6b05e93747f70b70051b36b43922b773633de9ad64bb00af6206a51e1'
|
||||
SOURCE_PINS = {
|
||||
'conditioning-interface-v2/coordinator.py': '7862fed19bcf3878f42783af6286574371a2d58c66719c99cabab8f18ec99a34',
|
||||
'conditioning-interface-v2/isolated_workers.py': 'e47651a8ea99d7c44115107ff6b5dc71312183609ae11c891db65bb21ed61e30',
|
||||
'conditioning-interface-v2/test_coordinator.py': 'ffd2951c2bf23ea1a4a8d598fa1be9f07f71e60ad28fe5a06eed17537946d900',
|
||||
'conditioning-interface-v2/test_isolated_workers.py': 'd72fcc10f32a1284fa49491cb19f29e83b37b472051985e2fda56799c14a2e60',
|
||||
'conditioning-interface-v2/PROTOCOL.md': '2a1c553e6be87df02db8d357f00eb88c9dea3c9b75b6ef670dd55f45492d7518',
|
||||
'olfactory-conditioning-lab-v1/seed_registry.py': '0da033b132095ec3087b5d9f64e53c2e391fa50ab0b7653b31296eeb84799b7e',
|
||||
'olfactory-conditioning-lab-v1/trial_plan.py': '6fed3f494d075339a7e5b001d43b2598640b189e038952fbd4d41200bacac587',
|
||||
}
|
||||
AP_ANCHORS = {
|
||||
'protocol/preregistered.json': '02a03b536a9f14196ad4b92fa9565b592732c6c863e72eeaee89b3b0ea8ed37d',
|
||||
'manifest.json': 'a40e433541a6c02f7ad95622e96646da9a90a93e4e43cb3abfde3846b2554f00',
|
||||
'audit/final-status.json': '26de8371867d55253358a4be698de896445712e49e6eee8d99ce852fd0bf43ab',
|
||||
'cases/D1--reference--epoch-001/spec.json': 'f0b8eddd78a2dc0e1d6fcae07489dcb24aa3c5bb14326367fa32cfdf960739ba',
|
||||
}
|
||||
PARENT_PINS = {
|
||||
'D1': 'df328eddff4c735e08fae377bbd7c4cd0df288de60c6ebd34965e28c369fc084',
|
||||
'D0': '6511e794c4f0f9929e81bd7363ad2314f0e44d9f95882883ab3644cf2b1a6fd9',
|
||||
'frozen': 'ebebf86480d6fe9facb4f08689783a1b78143f4794fa11694d68dd9efb806373',
|
||||
}
|
||||
STALE_INPUT_KEYS = frozenset(('CS_window', 'cs_input_seed', 'cs_input_seed_bits', 'expected_CS_requests',
|
||||
'mode', 'odor_id', 'odor_name', 'rate_sum_hz', 'source_panel_row', 'source_panel_split',
|
||||
'target_count', 'seed_scope', 'outer_arm', 'outer_epoch_id'))
|
||||
CASE_CHANGED_KEYS = frozenset(('name', 'steps', 'max_steps', 'duration_ms', 'budget_root',
|
||||
'output_budget_bytes', 'outer_protocol', 'within_trial_weight_updates'))
|
||||
CASE_ADDED_KEYS = frozenset(('boundary_diagnostic', 'input_policy', 'scientific_learning_claimed',
|
||||
'diagnostic_boundary_tick', 'evaluation_stream_id', 'cue', 'probe_fork_discard'))
|
||||
|
||||
|
||||
def _require(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def _canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
||||
|
||||
|
||||
def _sha(value):
|
||||
return hashlib.sha256(_canonical(value).encode('utf-8')).hexdigest()
|
||||
|
||||
|
||||
def evaluation_seeds():
|
||||
"""Exact frozen seed/stream rules; derive only, never draw random numbers."""
|
||||
result = {}
|
||||
for cue, odor in (('A', '4-ethylphenol'), ('B', '3-hexanone')):
|
||||
key = [BLOCK, 'evaluation', 'CS', cue, '00', 'base-probe']
|
||||
digest = _sha(['phase4an-seed-registry-v1', MASTER, 'evaluation', key])
|
||||
result[cue] = dict(cue=cue, odor=odor, master=MASTER, split='evaluation', key=key,
|
||||
seed=int(digest[:16], 16) & ((1 << 63)-1), seed_bits=63, derivation_sha256=digest,
|
||||
stream_id='evaluation:' + _sha(['phase4an-trial-plan-v1-draft', 'stream-id', MASTER, 'evaluation', key]))
|
||||
return result
|
||||
|
||||
|
||||
def build_plan():
|
||||
"""Fixed proposal; all future hashes and identity checks remain external."""
|
||||
calls = []
|
||||
|
||||
def add(name, runner, mode, steps, parent, offset, overlay, policy='empty_idle', **extra):
|
||||
group = name
|
||||
if '--updated--' in name or '--old-C--' in name:
|
||||
arm = name.split('--')[0]
|
||||
group = ('mechanical' if arm == 'mechanical' else 'AP-'+arm)+'-suffix'
|
||||
calls.append(dict(call_id=name, runner=runner, diagnostic_mode=mode, steps=steps,
|
||||
case_group=group,
|
||||
parent=parent, global_tick_offset=offset, global_next_tick=offset+steps,
|
||||
overlay_after_role=overlay, input_policy=policy, scientific_learning_claimed=False, **extra))
|
||||
|
||||
imports = {arm: dict(role=f'AP.{arm}.reference.epoch001',
|
||||
checkpoint_manifest=AP_ROOT+f'/runs/{arm}--reference--epoch-001/checkpoint-manifest.json',
|
||||
sha256=pin, steps_already_executed=1200) for arm, pin in PARENT_PINS.items()}
|
||||
for arm in ('D1', 'D0', 'frozen'):
|
||||
parent = imports[arm]['role']
|
||||
after = parent+'.original_E.after'
|
||||
for mode in ('reference', 'light'):
|
||||
add(f'{arm}--updated--{mode}', 'updated_continuation', mode, 1000, parent, 1200, after,
|
||||
transition='epoch_update', overlay_before_role=parent+'.recorded_overlay')
|
||||
if arm == 'D1':
|
||||
add('D1--live-oracle', 'boundary_oracle', 'reference', 2200, None, 0, after,
|
||||
policy='replay_AP_prefix_then_empty_idle', prefix_replay_parent=parent,
|
||||
overlay_before_role=parent+'.recorded_overlay', diagnostic_boundary_tick=1200,
|
||||
within_trial_weight_updates=True, restore_used=False)
|
||||
else:
|
||||
add(f'{arm}--old-C--reference', 'runtime_continuation', 'reference', 1000, parent,
|
||||
1200, parent+'.recorded_overlay', transition='same_weight')
|
||||
add('performance--natural-light-fresh', 'runtime_light', 'light', 1200, None, 0,
|
||||
'AP.D1.reference.epoch001.recorded_overlay', policy='replay_AP_D1_epoch001_input',
|
||||
input_replay_source='AP.D1.reference.epoch001', performance_training_cycle=True,
|
||||
regression_against='AP.D1.reference.epoch001', new_learning=False, input_sampled=False)
|
||||
add('performance--evaluation-A-light-fresh', 'fresh_probe', 'light', 1200, None, 0,
|
||||
'AP.initial_overlay', policy='externally_pinned_CS_probe', cue='A',
|
||||
performance_probe_cycle=True, probe_fork_discard=True, neural_reset=True,
|
||||
US=False, plastic_update=False, feedback_to_idle=False,
|
||||
evaluation_stream_id=evaluation_seeds()['A']['stream_id'])
|
||||
add('mechanical--fresh-parent', 'runtime_light', 'reference', 1200, None, 0,
|
||||
'AP.initial_overlay', policy='synthetic_one_KC_plus_four_PAM15_at_tick1199',
|
||||
inherited_learned_delta=False, olfactory_input=False)
|
||||
for mode in ('reference', 'light'):
|
||||
add(f'mechanical--updated--{mode}', 'updated_continuation', mode, 1000,
|
||||
'mechanical--fresh-parent', 1200, 'mechanical.original_E.after', transition='epoch_update',
|
||||
overlay_before_role='AP.initial_overlay')
|
||||
add('mechanical--live-oracle', 'boundary_oracle', 'reference', 2200, None, 0,
|
||||
'mechanical.original_E.after', policy='replay_mechanical_prefix_then_empty_idle',
|
||||
prefix_replay_parent='mechanical--fresh-parent', overlay_before_role='AP.initial_overlay',
|
||||
diagnostic_boundary_tick=1200, within_trial_weight_updates=True, restore_used=False)
|
||||
parent = imports['D1']['role']
|
||||
after = parent+'.original_E.after'
|
||||
add('D1--idle--1s', 'updated_continuation', 'light', 10000, parent, 1200, after,
|
||||
transition='epoch_update', overlay_before_role=parent+'.recorded_overlay')
|
||||
add('D1--idle--9s', 'updated_continuation', 'light', 90000, 'D1--idle--1s', 11200, after,
|
||||
transition='idle', overlay_before_role=after)
|
||||
for label, branch, offset, transition in (('t0', parent, 1200, 'epoch_update'),
|
||||
('t1', 'D1--idle--1s', 11200, 'idle'), ('t10', 'D1--idle--9s', 101200, 'idle')):
|
||||
for cue in ('A', 'B'):
|
||||
add(f'D1--probe--{label}--{cue}', 'updated_continuation', 'light', 1200, branch, offset,
|
||||
after, policy='externally_pinned_CS_probe', transition=transition, cue=cue,
|
||||
overlay_before_role=parent+'.recorded_overlay' if label == 't0' else after,
|
||||
probe_fork_discard=True, feedback_to_idle=False, neural_reset=False, US=False,
|
||||
plastic_update=False, evaluation_stream_id=evaluation_seeds()[cue]['stream_id'])
|
||||
zero_root = '/data/digital-drosophila/experiments/'
|
||||
return dict(schema=SCHEMA, status='DRAFT-NOT-REGISTERED', calls=calls, imported_parents=imports,
|
||||
initial_overlay=dict(role='AP.initial_overlay', registration_field='initial_overlay',
|
||||
overlay_file=dict(path=zero_root+'phase4am-wholebrain-plastic-interface/overlays/zero.npz',
|
||||
sha256='0b219eab09c30dc3af31fef7e6395a9bec1234090abbb72db096da833fed82c5'),
|
||||
overlay_manifest=dict(path=zero_root+'phase4an-engineering-validation/overlays/zero.json',
|
||||
sha256='11b668978f3070dad26d99d9310bebefa0731fa0d4e361e8dc0ef02a213277c2')),
|
||||
source_sha256=deepcopy(SOURCE_PINS), AP_anchors_sha256=deepcopy(AP_ANCHORS),
|
||||
AP_source_commit='0bcce983324ecfe1c75826a23e94ff932ad5e883', evaluation_streams=evaluation_seeds(),
|
||||
mechanical_update=dict(coordinator='original_E', update='original_U', parent='mechanical--fresh-parent',
|
||||
before_overlay_role='AP.initial_overlay', steps=1200, us_tick=1199, d_command=1.0,
|
||||
frozen=False, compartment=COMPARTMENT, trace_backend='torch'),
|
||||
performance_update=dict(coordinator='original_E', update='original_U', parent='performance--natural-light-fresh',
|
||||
before_overlay_role='AP.D1.reference.epoch001.recorded_overlay', steps=1200, us_tick=900,
|
||||
d_command=1.0, frozen=False, compartment=COMPARTMENT, trace_backend='torch',
|
||||
required_regression=['all_events', 'final_state', 'delta_after'],
|
||||
timing_scope='before_brain_spawn_through_original_E_exit_and_independent_CPU_validation'),
|
||||
cpu_children=[*[dict(role='verify_AP_original_E', parent=imports[a]['role']) for a in imports],
|
||||
dict(role='performance_original_E'), dict(role='verify_performance_original_E'),
|
||||
dict(role='mechanical_original_E'), dict(role='verify_mechanical_original_E')],
|
||||
sampler_child=dict(role='evaluation_sampler', execution='GPU_private_generator',
|
||||
uniform_batch_calls=2, cues=['A', 'B']),
|
||||
counts=dict(new_brain_calls=23, new_brain_ticks=125200, distinct_case_groups=17, imported_brain_calls=3,
|
||||
imported_brain_ticks=3600, covered_brain_ticks=128800, cpu_children=7, gpu_sampler_children=1, total_children=31,
|
||||
new_CS_uniform_batch_calls=2, raw_uniform_draw_count=None, raw_draw_count_known=False),
|
||||
budget_proposal=dict(output_bytes=4*2**30, free_reserve_bytes=10*2**30,
|
||||
child_timeout_seconds=1800, workflow_timeout_seconds=7200, approved=False,
|
||||
on_limit='stop_and_report_incomplete; never_shorten_trial_or_change_gate'),
|
||||
protected_contract=dict(brain_model='unchanged', APL='unchanged', delay='unchanged',
|
||||
sign='unchanged', threshold='unchanged', eta='unchanged', candidate_mask_count=14232),
|
||||
external_requirements=['authenticate_all_source_protocol_checkpoint_and_overlay_bytes',
|
||||
'authenticate_candidate_endpoints_KC_membership_and_exact_PAM15_membership',
|
||||
'bind_original_E_outputs_and_CPU_recomputation_receipts',
|
||||
'register_new_sources_cases_inputs_budget_and_exact_execution_authority',
|
||||
'sample_two_evaluation_CS_batches_with_pinned_real_generator_then_reuse_at_three_times'],
|
||||
brain_executed=False, inputs_sampled=False, acquisition_executed=False,
|
||||
full_retention_experiment=False, scientific_learning_claimed=False,
|
||||
external_identity_verified_here=False, execution_authorized=False)
|
||||
|
||||
|
||||
def validate_plan(plan):
|
||||
_require(_canonical(plan) == _canonical(build_plan()), 'Plan differs from fixed independent reconstruction')
|
||||
return True
|
||||
|
||||
|
||||
def derive_case_spec(template, call_id, *, budget_root):
|
||||
"""Narrow derivation of the actual AP D1 template; no claimed file checking."""
|
||||
_require(_sha(template) == TEMPLATE_PAYLOAD_SHA256, 'Not the pinned AP template payload')
|
||||
_require(type(budget_root) is str, 'Output root must be an absolute POSIX string')
|
||||
root = PurePosixPath(budget_root)
|
||||
_require(root.is_absolute() and '..' not in root.parts and
|
||||
str(root) not in ('/', AP_ROOT) and PurePosixPath(AP_ROOT) not in root.parents and
|
||||
root not in PurePosixPath(AP_ROOT).parents, 'Use a distinct absolute non-ancestor output root')
|
||||
call = next((c for c in build_plan()['calls'] if c['call_id'] == call_id), None)
|
||||
_require(call is not None, 'Unknown fixed call')
|
||||
result = {k: deepcopy(v) for k, v in template.items() if k not in STALE_INPUT_KEYS}
|
||||
result.update(name=call['case_group'], steps=call['steps'], max_steps=call['steps'], duration_ms=call['steps']*.1,
|
||||
budget_root=str(root), output_budget_bytes=4*2**30, outer_protocol=SCHEMA,
|
||||
within_trial_weight_updates=call.get('within_trial_weight_updates', False),
|
||||
boundary_diagnostic=call['case_group'], input_policy=call['input_policy'], scientific_learning_claimed=False)
|
||||
if 'diagnostic_boundary_tick' in call:
|
||||
result['diagnostic_boundary_tick'] = call['diagnostic_boundary_tick']
|
||||
if 'cue' in call:
|
||||
stream = evaluation_seeds()[call['cue']]
|
||||
result.update(mode='physiological', cue=call['cue'], odor_name=stream['odor'], CS_window=[0, 1000],
|
||||
cs_input_seed=stream['seed'], cs_input_seed_bits=63, evaluation_stream_id=stream['stream_id'],
|
||||
probe_fork_discard=True, seed_scope='reset seed unchanged; full63 evaluation CS seed used by external sampler')
|
||||
return result
|
||||
|
||||
|
||||
def mechanical_requests(candidate_map, pam15_ids, *, identity_binding):
|
||||
"""Caller authenticates mapping/DAN membership; only array schema checked here.
|
||||
|
||||
Select minimum canonical KC index, never based on outcome. Returned requests
|
||||
are synthetic deterministic force requests, not odor samples or accepted spikes.
|
||||
"""
|
||||
roles = {'edge_id', 'source_neuron_idx', 'target_neuron_idx', 'target_compartment_verbatim'}
|
||||
_require(type(candidate_map) is dict and set(candidate_map) == roles, 'Exact candidate map schema required')
|
||||
for key, array in candidate_map.items():
|
||||
_require(isinstance(array, np.ndarray) and array.shape == (CANDIDATES,), 'Full candidate arrays required')
|
||||
expected = np.int64 if key == 'edge_id' else np.int32
|
||||
_require(array.dtype.kind == 'U' if key == 'target_compartment_verbatim' else array.dtype == expected,
|
||||
'Candidate dtype changed')
|
||||
edge = candidate_map['edge_id']
|
||||
_require(np.all(edge >= 0) and np.all(edge < 25582938) and np.all(edge[1:] > edge[:-1]), 'Canonical edge order required')
|
||||
for key in ('source_neuron_idx', 'target_neuron_idx'):
|
||||
_require(np.all((candidate_map[key] >= 0) & (candidate_map[key] < N)), 'Neuron index out of range')
|
||||
_require(isinstance(pam15_ids, np.ndarray) and pam15_ids.dtype == np.int32 and pam15_ids.shape == (4,)
|
||||
and np.all((pam15_ids >= 0) & (pam15_ids < N)) and np.all(pam15_ids[1:] > pam15_ids[:-1]),
|
||||
'Four canonical sorted unique int32 PAM15 indices required')
|
||||
_require(type(identity_binding) is dict and set(identity_binding) == {'candidate_map_sha256', 'pam15_membership_sha256'}
|
||||
and all(type(v) is str and len(v) == 64 and all(c in '0123456789abcdef' for c in v)
|
||||
for v in identity_binding.values()), 'External identity digest descriptors required')
|
||||
sources = candidate_map['source_neuron_idx'][candidate_map['target_compartment_verbatim'] == COMPARTMENT]
|
||||
_require(len(sources) > 0, 'No exact y5B\'2a candidate rows')
|
||||
selected = int(sources.min())
|
||||
_require(selected not in pam15_ids, 'KC/DAN identity overlap')
|
||||
node = np.sort(np.concatenate((np.array([selected], dtype=np.int32), pam15_ids)))
|
||||
audit = dict(selected_KC_source_neuron_idx=selected, PAM15_neuron_idx=pam15_ids.tolist(), tick=1199,
|
||||
request_count=5, compartment=COMPARTMENT, identity_binding=deepcopy(identity_binding),
|
||||
selection='minimum canonical source_neuron_idx among exact compartment candidate rows',
|
||||
input_arrays={k: dict(dtype=a.dtype.str, shape=list(a.shape), raw_c_order_sha256=
|
||||
hashlib.sha256(a.tobytes(order='C')).hexdigest()) for k, a in candidate_map.items()},
|
||||
external_identity_verified_here=False, olfactory_input=False, sampled=False, accepted_spikes_verified=False,
|
||||
before_overlay_role='AP.initial_overlay', inherited_learned_delta=False, scientific_learning_claimed=False)
|
||||
return dict(tick=np.full(5, 1199, dtype=np.int32), neuron_idx=node), audit
|
||||
@@ -0,0 +1,75 @@
|
||||
"""Exactly two registered evaluation-input batches; no brain, US or learning."""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
import boundary_plan as PLAN
|
||||
import execution_authority as A
|
||||
|
||||
MODEL=Path(__file__).resolve().parent
|
||||
LAB=MODEL.parent/'olfactory-conditioning-lab-v1'
|
||||
PINS={
|
||||
'conditioning_inputs.py':'19382e066e450140bb653a3661f980ffe7cc62f412020ef57df0b6e6b3cbb8ba',
|
||||
'conditioning_preflight_inputs.py':'846d2141b472f18b1bb728eed4aa33876896d4b33dece364787c81204f62995f',
|
||||
'evaluation_plan.py':'991c813ff3322b230947f302b12b04ec382c3b632817f94b698101e4b17efa7d',
|
||||
'trial_plan.py':'6fed3f494d075339a7e5b001d43b2598640b189e038952fbd4d41200bacac587',
|
||||
'seed_registry.py':'0da033b132095ec3087b5d9f64e53c2e391fa50ab0b7653b31296eeb84799b7e',
|
||||
}
|
||||
|
||||
|
||||
def save(path,value):
|
||||
with Path(path).open('x',encoding='utf-8') as f:json.dump(value,f,sort_keys=True,indent=2,allow_nan=False)
|
||||
|
||||
|
||||
def run(authority_file,authority_sha,out_dir):
|
||||
A.require(sys.dont_write_bytecode and A.digest(authority_file)==authority_sha,'Use -B with external registration pin')
|
||||
reg=A.read(authority_file)
|
||||
A.require(reg['schema']=='conditioning-execution-registration-v1','Wrong input generation authority')
|
||||
PLAN.validate_plan(reg['plan'])
|
||||
for path,sha in {**reg['source_sha256'],**reg['input_sha256'],**reg['prepared_file_sha256']}.items():
|
||||
A.require(A.pin(path)['sha256']==sha,'Sampler source/input drift')
|
||||
for name,sha in PINS.items():
|
||||
A.require(A.digest(LAB/name)==sha and reg['input_sha256'].get(str(LAB/name))==sha,'Unpinned frozen input dependency: '+name)
|
||||
A.require(not any(name in sys.modules for name in ('conditioning_inputs','conditioning_preflight_inputs','evaluation_plan')),
|
||||
'Sampler needs fresh scientific imports')
|
||||
sys.path.insert(0,str(LAB))
|
||||
import conditioning_preflight_inputs as I
|
||||
import conditioning_inputs as CI
|
||||
import evaluation_plan as EP
|
||||
rates=I.load_rate_tables('/data/digital-drosophila')
|
||||
full=reg['original_full_plan'];A.require(A.digest(full['path'])==full['sha256'],'Full seed/trial plan changed')
|
||||
streams=EP._streams(A.read(full['path']))
|
||||
exp=Path(authority_file).parent.parent;out=Path(out_dir)
|
||||
A.require(not out.exists() and out.parent.is_dir() and out.is_relative_to(exp),'Exclusive new sampler output required')
|
||||
out.mkdir();rows=[]
|
||||
for cue in ('A','B'):
|
||||
declared=reg['plan']['evaluation_streams'][cue];actual=streams[(PLAN.BLOCK,cue)]
|
||||
for field in ('seed','seed_bits','stream_id','derivation_sha256'):
|
||||
A.require(declared[field]==actual[field],'Evaluation semantic stream differs')
|
||||
A.require(declared['key']==actual['semantic_key'] and actual['split']=='evaluation','Evaluation stream provenance differs')
|
||||
table=rates['tables'][cue]
|
||||
with np.load(exp/f'inputs/static/{cue}-rates.npz',allow_pickle=False) as saved:
|
||||
A.require(all(saved[k].dtype==table[k].dtype and saved[k].shape==table[k].shape and
|
||||
saved[k].tobytes()==table[k].tobytes() for k in ('targets','rates_hz')),'Registered original PN mapping changed')
|
||||
started=time.perf_counter()
|
||||
result=CI.generate_cs_requests(table['targets'],table['rates_hz'],seed=declared['seed'],steps=1200,
|
||||
cs_start_tick=0,cs_stop_tick=1000,device='cuda:0',max_uniform_draws=1200*len(table['targets']))
|
||||
with (out/f'{cue}-requests.npz').open('xb') as f:np.savez_compressed(f,**result['requests'])
|
||||
save(out/f'{cue}-sampler.json',result['audit'])
|
||||
rows.append(dict(cue=cue,stream=actual,requests=len(result['requests']['tick']),US_requests=0,
|
||||
uniform_draws=1200*len(table['targets']),wall_seconds=time.perf_counter()-started,
|
||||
saved_requests_sha256=A.digest(out/f'{cue}-requests.npz')))
|
||||
pins={p.name:A.digest(p) for p in out.iterdir() if p.is_file()}
|
||||
summary=dict(schema='conditioning-boundary-sampler-v1',complete=True,registration_sha256=authority_sha,
|
||||
uniform_batch_calls=2,uniform_draws=sum(r['uniform_draws'] for r in rows),rows=rows,files_sha256=pins,
|
||||
brain_executed=False,learning_executed=False,US_added=False,original_rate_mapping_preserved=True,
|
||||
inputs_sampled_once=True,planned_retention_reuse_checkpoints_seconds=[0,1,10],
|
||||
reuse_executed_here=False,seed_search=False,learning_success_claimed=False)
|
||||
save(out/'sampler-receipt.json',summary)
|
||||
return summary
|
||||
@@ -0,0 +1,277 @@
|
||||
"""Read-only actual boundary-cost accounting; never authorizes normal training.
|
||||
|
||||
Only the two registered fresh/light performance cycles are cost samples. Their
|
||||
next serial cycle start is a measured conservative tail-completion upper bound,
|
||||
not an invented postvalidation duration. All current compiled-cache bytes are
|
||||
charged to EACH sample (deliberate overcount); cache reuse is never free by fiat.
|
||||
No normal directory-hashing/finalization policy or reserves are registered yet,
|
||||
so the strict full-suite forecast remains INSUFFICIENT-MEASUREMENTS. This report
|
||||
does not independently re-observe historical OS exits or certify learning.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import deepcopy
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
import execution_authority as A
|
||||
import execution_budget as B
|
||||
import execution_workflow as F
|
||||
|
||||
|
||||
SCHEMA = 'conditioning-actual-budget-report-v1'
|
||||
TRAIN = 'performance--natural-light-fresh'
|
||||
PROBE = 'performance--evaluation-A-light-fresh'
|
||||
SELECTED = {TRAIN: [('brain',TRAIN),('original_E',TRAIN+'--original-E'),('cpu_validator',TRAIN+'--cpu-verify')],
|
||||
PROBE: [('brain',PROBE)]}
|
||||
POLICY = 'measured-fresh-light-1200-fullgraph-with-original-E-and-CPU-verification-for-training'
|
||||
require = A.require
|
||||
|
||||
|
||||
def _canonical(value):
|
||||
return json.dumps(value,sort_keys=True,separators=(',', ':'),ensure_ascii=False,allow_nan=False)
|
||||
|
||||
|
||||
def _sha(value):
|
||||
return hashlib.sha256(_canonical(value).encode()).hexdigest()
|
||||
|
||||
|
||||
def _same(a,b):
|
||||
return _canonical(a)==_canonical(b)
|
||||
|
||||
|
||||
def _number(value):
|
||||
return type(value) in (int,float) and math.isfinite(value) and value>=0
|
||||
|
||||
|
||||
class Evidence:
|
||||
def __init__(self):
|
||||
self.pins={}
|
||||
self.derived={}
|
||||
|
||||
def pin(self,path,expected=None):
|
||||
if not Path(path).exists():
|
||||
raise FileNotFoundError(2,'Missing measurement evidence',str(path))
|
||||
entry=A.pin(path);p=entry['path'];sha=entry['sha256']
|
||||
require(expected is None or sha==expected,'Evidence bytes changed: '+p)
|
||||
require(p not in self.pins or self.pins[p]==sha,'Conflicting evidence pin: '+p)
|
||||
self.pins[p]=sha
|
||||
return dict(receipt_id=p,sha256=sha)
|
||||
|
||||
def read(self,path,expected=None):
|
||||
self.pin(path,expected)
|
||||
return A.read(path)
|
||||
|
||||
def inventory(self,directory):
|
||||
result=F.tree(directory)
|
||||
for name,row in result.items():self.pin(Path(directory)/name,row['sha256'])
|
||||
return result
|
||||
|
||||
def derived_binding(self,name,value):
|
||||
key='derived:'+name
|
||||
self.derived[key]=deepcopy(value)
|
||||
return dict(receipt_id=key,sha256=_sha(value))
|
||||
|
||||
def authenticated(self):
|
||||
return {**self.pins,**{key:_sha(value) for key,value in self.derived.items()}}
|
||||
|
||||
|
||||
def _parent_process(name,reg,reg_sha,evidence):
|
||||
exp=F.EXP;process_path=exp/'receipts'/f'{name}.process.json'
|
||||
process=evidence.read(process_path)
|
||||
require(process['schema']=='conditioning-execution-process-v1' and process['complete'] is True and
|
||||
process['name']==name and process['registration_sha256']==reg_sha and
|
||||
type(process['exit_code']) is int and process['exit_code']==0 and process['timed_out'] is False,
|
||||
'Unsuccessful/unbound parent process: '+name)
|
||||
jobpath=exp/'jobs'/f'{name}.json';job=evidence.read(jobpath,process['job_sha256'])
|
||||
workerpath=exp/'receipts'/f'{name}.worker.json'
|
||||
worker=evidence.read(workerpath,process['worker_receipt_sha256'])
|
||||
ap=job['kind'] in ('brain','update');script=F.AP_WORKER if ap else F.MODEL/'isolated_execution.py'
|
||||
schema='phase4ap-isolated-worker-receipt-v1' if ap else 'conditioning-isolated-execution-receipt-v1'
|
||||
worker_sha=F.W.AP_SHA if ap else reg['source_sha256'][str(script)]
|
||||
require(worker['schema']==schema and worker['complete'] is True and job['worker_sha256']==worker_sha and
|
||||
all(worker[k]==job[k] for k in ('job_id','kind','registration_sha256','worker_sha256')) and
|
||||
job['job_id']==name and job['kind']==process['kind'] and job['registration_sha256']==reg_sha and
|
||||
worker['job_sha256']==process['job_sha256'] and job['receipt_file']==str(workerpath),
|
||||
'Worker/job/parent receipt identity differs')
|
||||
expected={**job['input_sha256'],str(jobpath):process['job_sha256'],str(script):worker_sha}
|
||||
if ap:expected.update({v['path']:v['sha256'] for v in job['sources'].values()})
|
||||
else:
|
||||
expected[str(F.AP_WORKER)]=F.W.AP_SHA
|
||||
expected.update({str(F.MODEL/n):s for n,s in job['source_sha256'].items()})
|
||||
require(expected.get(str(exp/'protocol/preregistered.json'))==reg_sha and
|
||||
worker['verified_input_sha256' if ap else 'input_sha256']==expected,'Actual input/source closure differs')
|
||||
for path,sha in expected.items():evidence.pin(path,sha)
|
||||
command=process['argv']
|
||||
require(type(command) is list and len(command)>3 and command[1:3]==['-B',str(script)] and
|
||||
command[3:]==(['brain' if job['kind']=='brain' else 'update'] if ap else [])+
|
||||
['--job',str(jobpath),'--job-sha256',process['job_sha256']], 'Observed child command differs')
|
||||
for side in ('stdout','stderr'):evidence.pin(exp/'logs'/f'{name}.{side}.log',process[side+'_sha256'])
|
||||
evidence.pin(str(workerpath)+'.attempt.json',worker['attempt_sha256'])
|
||||
output=Path(job['output_dir'])
|
||||
require(output.is_relative_to(exp) and worker['output_dir']==str(output),'Wrong child output root')
|
||||
inventory=evidence.inventory(output);hashes={k:v['sha256'] for k,v in inventory.items()}
|
||||
require(inventory and hashes==worker['output_files_sha256'] and
|
||||
process['output_bytes']==sum(v['bytes'] for v in inventory.values()) and
|
||||
process['output_inventory_sha256']==hashlib.sha256(json.dumps(hashes,sort_keys=True).encode()).hexdigest(),
|
||||
'Actual complete child output inventory differs')
|
||||
start,exit_,end=(process[k] for k in ('spawn_monotonic','exit_monotonic','validation_end_monotonic'))
|
||||
require(all(_number(v) for v in (start,exit_,end)) and start<exit_<=end and
|
||||
math.isclose(process['child_wall_seconds'],exit_-start,rel_tol=1e-12) and
|
||||
math.isclose(process['end_to_end_seconds'],end-start,rel_tol=1e-12) and
|
||||
math.isclose(process['validation_wall_seconds'],end-exit_,rel_tol=1e-12),'Parent timing layers differ')
|
||||
return dict(process=process,job=job,worker=worker,output_inventory=inventory,
|
||||
binding=evidence.pin(process_path))
|
||||
|
||||
|
||||
def _cycle_files(name,events,evidence):
|
||||
"""Exact newly generated scope of the frozen workflow performance branches."""
|
||||
paths=set()
|
||||
for row in events:
|
||||
job=row['job'];event=job['job_id'];output=Path(job['output_dir'])
|
||||
paths.update(output/key for key in row['output_inventory'])
|
||||
paths.update(F.EXP/f'{directory}/{event}{suffix}' for directory,suffix in
|
||||
(('jobs','.json'),('receipts','.worker.json'),('receipts','.worker.json.attempt.json'),
|
||||
('receipts','.process.json'),('logs','.stdout.log'),('logs','.stderr.log')))
|
||||
brain=events[0]['job'];case=Path(brain['case_dir'])
|
||||
require(case==F.EXP/'cases'/name,'Performance case must be separate, not a continuation/shared case')
|
||||
paths.update(case/n for n in ('spec.json','requests.npz'))
|
||||
if name==TRAIN:paths.add(F.EXP/'authorities'/f'{name}.epoch.json')
|
||||
result={}
|
||||
for path in paths:
|
||||
entry=evidence.pin(path)
|
||||
result[path.relative_to(F.EXP).as_posix()]=dict(sha256=entry['sha256'],bytes=path.stat().st_size)
|
||||
return result
|
||||
|
||||
|
||||
def _collect(reg,reg_sha,evidence):
|
||||
complete=evidence.read(F.EXP/'audit/execution-complete.json')
|
||||
calls=reg['plan']['calls'];ordered=[c['call_id'] for c in calls]
|
||||
require(complete['complete'] is True and complete['registration_sha256']==reg_sha and
|
||||
complete['scientific_learning_pass_claimed'] is False and complete['completed_calls']==ordered,
|
||||
'Actual complete fixed workflow required')
|
||||
names=set(ordered)|{'evaluation-inputs','AP-D1--cpu-verify','AP-D0--cpu-verify','AP-frozen--cpu-verify'}
|
||||
names|={base+suffix for base in (TRAIN,'mechanical--fresh-parent') for suffix in ('--original-E','--cpu-verify')}
|
||||
require(set(complete['processes'])==names and len(names)==reg['plan']['counts']['total_children'],
|
||||
'Actual finite process inventory differs')
|
||||
for name,path in complete['processes'].items():
|
||||
require(Path(path)==F.EXP/'receipts'/f'{name}.process.json','Unexpected process receipt location')
|
||||
processes={name:_parent_process(name,reg,reg_sha,evidence) for name in sorted(names)}
|
||||
attempt=evidence.read(F.EXP/'audit/execution-attempt.json')
|
||||
require(attempt['registration_sha256']==reg_sha and _number(attempt['monotonic_origin']), 'Missing parent clock origin')
|
||||
cycles={name:evidence.read(F.EXP/'receipts'/f'{name}.cycle.json') for name in ordered}
|
||||
for call in calls:
|
||||
cycle=cycles[call['call_id']]
|
||||
require(cycle['complete'] is True and cycle['learning_pass_claimed'] is False and
|
||||
cycle['source_registration_sha256']==reg_sha and _same(cycle['call'],call), 'Cycle/registration binding differs')
|
||||
final_build=evidence.inventory(F.EXP/'extension-build')
|
||||
require(_same(cycles[ordered[-1]]['mutable_build_inventory_after'],final_build), 'Final mutable cache inventory changed')
|
||||
build_bytes=sum(v['bytes'] for v in final_build.values())
|
||||
samples=[];accounts={};contexts=[]
|
||||
for name,roles in SELECTED.items():
|
||||
cycle=cycles[name];next_name=ordered[ordered.index(name)+1];tail_end=cycles[next_name]['start_monotonic']
|
||||
start,end=cycle['start_monotonic'],cycle['end_monotonic']
|
||||
require(all(_number(v) for v in (start,end,tail_end)) and attempt['monotonic_origin']<=start<end<=tail_end and
|
||||
math.isclose(cycle['wall_seconds'],end-start,rel_tol=1e-12),'Missing ordered adjacent-cycle tail bound')
|
||||
rows=[processes[n] for _,n in roles];brain=rows[0];job=brain['job']
|
||||
require(job['kind']=='brain' and job['diagnostic_mode']=='light','Only complete fresh light brain samples')
|
||||
summary=evidence.read(Path(job['output_dir'])/'summary.json')
|
||||
expected=dict(steps=1200,completed_ticks=1200,explicit_steps_executed=1200,max_steps=1200,nodes=B.N,edges=B.E,
|
||||
diagnostic_mode='light',entire_neural_trial_executed=True,within_trial_weight_updates=False,
|
||||
precision='float64',apl_precision='float32')
|
||||
require(all(_same(summary.get(k),v) for k,v in expected.items()) and
|
||||
brain['worker']['result']['complete_fresh_trial'] is True, 'Incomplete/different fresh neural trial')
|
||||
spec=evidence.read(Path(job['case_dir'])/'spec.json')
|
||||
require(spec['dt_ms']==.1 and spec['steps']==1200 and
|
||||
'parent_checkpoint_manifest_sha256' not in spec and 'global_tick_offset' not in spec,
|
||||
'Continuation or changed clock cannot estimate fresh normal costs')
|
||||
if name==TRAIN:
|
||||
epoch=evidence.read(rows[1]['job']['authority_file']);cpu=rows[2]['job']
|
||||
require(rows[1]['job']['kind']=='update' and cpu['kind']=='validate_cpu' and
|
||||
cpu['authority_file']==rows[1]['job']['authority_file'] and cpu['update_dir']==rows[1]['job']['output_dir'] and
|
||||
epoch['checkpoint_dir']==job['output_dir'] and epoch['command']==dict(steps=1200,compartment="y5B'2a",
|
||||
us_tick=900,d_command=1.,frozen=False,trace_backend='torch'), 'Training cycle E/CPU parts differ')
|
||||
else:
|
||||
call=cycle['call']
|
||||
require(call['US'] is False and call['plastic_update'] is False and call['parent'] is None and
|
||||
job['overlay_file']==reg['initial_overlay']['overlay_file'], 'Fresh probe must be zero-overlay no-US/no-update')
|
||||
sampler=processes['evaluation-inputs']['job']
|
||||
evidence.pin(Path(job['case_dir'])/'requests.npz',A.digest(Path(sampler['output_dir'])/'A-requests.npz'))
|
||||
context=dict(policy=POLICY,environment=brain['worker']['environment'],brain_sources=job['sources'],
|
||||
model={k:spec[k] for k in ('model','apl','dt_ms','precision','apl_precision','apl_delay_steps','graph_dir','apl_bundle_dir')},
|
||||
registered_sources_sha256=reg['source_sha256'],
|
||||
output_policy='retain_all_cycle_artifacts_plus_entire_final_cache_each_cycle; no amortization')
|
||||
contexts.append(context)
|
||||
observed=_cycle_files(name,rows,evidence)
|
||||
require(_same(cycle['output_inventory'],observed) and cycle['output_bytes']==sum(v['bytes'] for v in observed.values()),
|
||||
'Cycle created inventory is not actual complete fixed-branch scope')
|
||||
own=F.EXP/'receipts'/f'{name}.cycle.json';own_bytes=own.stat().st_size
|
||||
inventory=dict(created=observed,cycle_receipt=evidence.pin(own),cycle_receipt_bytes=own_bytes,
|
||||
full_current_build_cache=final_build,full_current_build_cache_bytes=build_bytes,
|
||||
total_bytes=cycle['output_bytes']+own_bytes+build_bytes)
|
||||
events=[]
|
||||
for (role,event_name),row in zip(roles,rows):
|
||||
p=row['process'];runtime=row['worker'].get('wall_seconds')
|
||||
require(_number(runtime) and runtime<=p['child_wall_seconds'],'Worker runtime duration missing/inconsistent')
|
||||
require(start<=p['spawn_monotonic'] and p['validation_end_monotonic']<=end,'Process outside actual cycle clock')
|
||||
events.append(dict(event_id=event_name,role=role,receipt_kind='parent-process',receipt=row['binding'],
|
||||
spawn_s=p['spawn_monotonic'],exit_s=p['exit_monotonic'],validated_s=p['validation_end_monotonic'],
|
||||
exit_code=0,core_seconds=None,runtime_seconds=runtime,child_wall_seconds=p['child_wall_seconds']))
|
||||
samples.append(dict(schema=B.SCHEMA,cycle_id=name,kind='training' if name==TRAIN else 'probe',
|
||||
diagnostic_mode='light',steps=1200,neurons=B.N,edges=B.E,dt_ms=.1,context_sha256=_sha(context),
|
||||
clock_id='registered-parent:'+reg_sha,started_s=start,validated_s=tail_end,
|
||||
authority=evidence.pin(own),events=events,outputs=dict(inventory=evidence.derived_binding(name,inventory),
|
||||
scope=B.OUTPUT_SCOPE,complete=True,total_bytes=inventory['total_bytes']),complete=True))
|
||||
accounts[name]=dict(recorded_cycle_seconds=end-start,tail_upper_bound_seconds=tail_end-end,
|
||||
conservative_complete_cycle_seconds=tail_end-start,tail_bound_from_next_cycle=next_name,
|
||||
tail_may_include_intervening_sampler=True,created_bytes=cycle['output_bytes'],cycle_receipt_bytes=own_bytes,
|
||||
repeated_full_cache_bytes=build_bytes,total_conservative_bytes=inventory['total_bytes'],
|
||||
core_timing=None,core_timing_reason='no unrounded authenticated core timing contract; never substituted for wall')
|
||||
require(_same(contexts[0],contexts[1]),'Train/probe machine/code/model/output policies differ')
|
||||
return samples,accounts,contexts[0]
|
||||
|
||||
|
||||
def report(reg_sha,save_report=True):
|
||||
"""Verify current bytes; optionally exclusively save audit/budget-report.json.
|
||||
|
||||
Missing evidence returns INSUFFICIENT; contradictory/tampered evidence raises.
|
||||
No full-suite numerical estimate is admitted without a future registered
|
||||
normal executor, growing-inventory hash policy and explicit complete reserves.
|
||||
"""
|
||||
require(type(save_report) is bool,'save_report must be Boolean')
|
||||
destination=F.EXP/'audit/budget-report.json'
|
||||
require(not save_report or not destination.exists(),'Budget report exists; never overwrite')
|
||||
reg=F.registration(reg_sha);evidence=Evidence();evidence.pin(F.EXP/'protocol/preregistered.json',reg_sha)
|
||||
samples=[];accounting={};context=None;missing=[]
|
||||
try:samples,accounting,context=_collect(reg,reg_sha,evidence)
|
||||
except FileNotFoundError as error:missing.append('Actual measurement evidence missing: '+str(error.filename))
|
||||
measured=[];used=set()
|
||||
for row in samples:measured.append(B._measure(row,evidence.authenticated(),used))
|
||||
# These explicit placeholders are supplied ONLY with zero admitted samples.
|
||||
# They are not assumptions of zero future cost and can never yield a total.
|
||||
blocked_reserves={role:dict(wall_seconds=0,output_bytes=0,basis='UNREGISTERED; not used for a projection') for role in B.RESERVE_ROLES}
|
||||
blocked_reserves['cycle_multiplier']=1
|
||||
projection=B.estimate_normal_suite([],authenticated_receipts={},target_context_sha256=reg_sha,
|
||||
reserves=blocked_reserves,limits=None)
|
||||
missing+=['FUTURE-POLICY-NOT-REGISTERED: normal executor/context and growing-output hashing/finalization policy',
|
||||
'FUTURE-POLICY-NOT-REGISTERED: explicit sampler/input, parent hash, final integrity, compiler/warmup and unknown-activity reserves',
|
||||
'FUTURE-POLICY-NOT-REGISTERED: normal wall/storage caps; engineering 4 GiB/7200 s is not a normal budget']
|
||||
value=dict(schema=SCHEMA,registration_sha256=reg_sha,status='INSUFFICIENT-MEASUREMENTS',
|
||||
policy_status='FUTURE-POLICY-NOT-REGISTERED',inventory=deepcopy(B.INVENTORY),measurements=measured,
|
||||
available_cost_cycles=samples,accounting=accounting,measured_context=context,
|
||||
measured_context_sha256=None if context is None else _sha(context),strict_projection=projection,
|
||||
estimated_wall_seconds=None,estimated_output_bytes=None,missing=missing,
|
||||
evidence_sha256=evidence.pins,derived_inventories=evidence.derived,
|
||||
verification_scope='registered parent receipts plus actual current bytes; historical OS exits are not re-observed',
|
||||
limitations=['only two fixed fresh light samples; no fitting, reference-to-light substitution or continuation extrapolation',
|
||||
'adjacent-cycle tail is a measured upper bound and may conservatively count intervening sampler work',
|
||||
'full final mutable cache is charged repeatedly for storage; compile/warmup wall for future policy remains unknown',
|
||||
'no assumption that activity/output volume remains constant after learning; no guaranteed full-suite bound',
|
||||
'shared registration/input preparation, final integrity and report own-file costs are not cycle costs'],
|
||||
engineering_scope=True,learning_pass_claimed=False,execution_authorized=False,
|
||||
assumptions_registered=False,normal_budget_authorized=False,no_new_brain_calls=True)
|
||||
F.verify(evidence.pins)
|
||||
if save_report:F.save(destination,value)
|
||||
return value
|
||||
@@ -0,0 +1,139 @@
|
||||
"""Build explicit file-bound authorities; does not run a brain or prove a process.
|
||||
|
||||
The registered coordinator authenticates source/input bytes and actual exits.
|
||||
All output here is a new dictionary; existing authority files are never edited.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def require(ok, message):
|
||||
if not ok: raise ValueError(message)
|
||||
|
||||
|
||||
def digest(path):
|
||||
h=hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for block in iter(lambda:stream.read(8<<20),b''):h.update(block)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def read(path):
|
||||
def unique(items):
|
||||
value={}
|
||||
for k,v in items:
|
||||
require(k not in value,'Duplicate JSON key');value[k]=v
|
||||
return value
|
||||
return json.loads(Path(path).read_text(encoding='utf-8'),object_pairs_hook=unique,
|
||||
parse_constant=lambda x: (_ for _ in ()).throw(ValueError('Nonfinite JSON')))
|
||||
|
||||
|
||||
def pin(path):
|
||||
p=Path(path)
|
||||
require(p.is_absolute() and p.is_file() and not any(x.is_symlink() for x in (p,*p.parents)),
|
||||
'Absolute unlinked regular source required')
|
||||
return dict(path=str(p.resolve()),sha256=digest(p))
|
||||
|
||||
|
||||
def files_from_authority(value):
|
||||
"""Exact direct closure. Parent full payload is additionally checked by loader."""
|
||||
result={}
|
||||
def add(path,sha):
|
||||
require(path not in result or result[path]==sha,'Conflicting input pin')
|
||||
result[path]=sha
|
||||
def visit(item):
|
||||
if type(item)is dict:
|
||||
if set(item)=={'path','sha256'}:add(item['path'],item['sha256'])
|
||||
else:
|
||||
for key,value in item.items():
|
||||
if key=='frozen_inputs':
|
||||
for path,sha in value.items():add(path,sha)
|
||||
else:visit(value)
|
||||
elif type(item)is list:
|
||||
for value in item:visit(value)
|
||||
visit(value)
|
||||
if 'parent' in value:
|
||||
p=value['parent'];add(str(Path(p['directory'])/'checkpoint-manifest.json'),p['checkpoint_manifest_sha256'])
|
||||
if 'checkpoint_dir' in value:
|
||||
add(str(Path(value['checkpoint_dir'])/'checkpoint-manifest.json'),value['checkpoint_manifest_sha256'])
|
||||
return result
|
||||
|
||||
|
||||
def effective_hash(spec,overlay_file):
|
||||
"""Independent original-base bridge, exact SI arithmetic and APL fast mask."""
|
||||
graph=Path(spec['graph_dir'])
|
||||
weights=np.load(graph/'weights.npy',allow_pickle=False)
|
||||
src=np.load(graph/'src.npy',allow_pickle=False,mmap_mode='r')
|
||||
ids=np.load(graph/'edge_id.npy',allow_pickle=False,mmap_mode='r')
|
||||
try:
|
||||
require(weights.dtype==np.float64 and weights.shape==(25582938,) and
|
||||
src.dtype==np.int32 and src.shape==weights.shape and ids.dtype==np.int64 and ids.shape==weights.shape,
|
||||
'Full canonical graph required')
|
||||
apl=np.load(Path(spec['apl_bundle_dir'])/'apl_globals.npy',allow_pickle=False)
|
||||
require(apl.dtype==np.int32 and apl.shape==(2,),'Two canonical APL IDs required')
|
||||
fast=np.isin(src,apl);require(int(fast.sum())==5845,'Original fast-APL mask differs')
|
||||
weights[fast]=np.float64(0)
|
||||
with np.load(overlay_file,allow_pickle=False) as f:
|
||||
require(set(f.files)=={'edge_id','plastic_delta_mv'},'Overlay array fields differ')
|
||||
mask=f['edge_id'];delta=f['plastic_delta_mv']
|
||||
require(mask.dtype==np.int64 and mask.shape==(14232,) and delta.dtype==np.float32 and delta.shape==mask.shape and
|
||||
np.all((mask>=0)&(mask<len(weights))) and np.all(mask[1:]>mask[:-1]) and
|
||||
np.array_equal(ids[mask],mask) and not fast[mask].any() and np.isfinite(delta).all() and np.all(delta<=0),
|
||||
'Original candidate overlay contract differs')
|
||||
nz=delta!=np.float32(0)
|
||||
rows=mask[nz]
|
||||
weights[rows]=np.add(weights[rows],np.multiply(delta[nz].astype(np.float64),np.float64(.001)))
|
||||
require(np.isfinite(weights).all() and np.all(weights[mask]>0),'Effective candidate sign/nonfinite failure')
|
||||
return hashlib.sha256(weights.astype('<f8',copy=False).tobytes()).hexdigest()
|
||||
finally:
|
||||
src._mmap.close();ids._mmap.close()
|
||||
|
||||
|
||||
def epoch_authority(template,*,case,checkpoint,overlay,epoch_id,us_tick,d_command=1.,frozen=False):
|
||||
value=copy.deepcopy(template)
|
||||
require(value['schema']=='phase4an-epoch-postprocess-authority-v1','Wrong epoch template')
|
||||
case,checkpoint=Path(case),Path(checkpoint)
|
||||
spec=read(case/'spec.json');summary=read(checkpoint/'summary.json')
|
||||
require(type(us_tick)is int and 0<=us_tick<spec['steps'] and summary['steps']==spec['steps'],'Invalid epoch clock')
|
||||
value.update(epoch_id=epoch_id,diagnostic_mode=summary['diagnostic_mode'],checkpoint_dir=str(checkpoint),
|
||||
checkpoint_manifest_sha256=digest(checkpoint/'checkpoint-manifest.json'))
|
||||
value['command']=dict(steps=spec['steps'],compartment="y5B'2a",us_tick=us_tick,
|
||||
d_command=d_command,frozen=frozen,trace_backend='torch')
|
||||
for role,path in dict(spec=case/'spec.json',requests=case/'requests.npz',state=checkpoint/'state.npz',
|
||||
overlay_before=overlay['overlay_file'],overlay_manifest_before=overlay['overlay_manifest']).items():
|
||||
value['files'][role]=pin(path)
|
||||
return value
|
||||
|
||||
|
||||
def boundary_authority(*,boundary_id,registration_sha256,case,parent,transition,input_policy,mode,
|
||||
before_overlay,after_overlay,source_files,frozen_inputs,epoch=None,update_dir=None,cpu_receipt=None):
|
||||
require(transition in ('epoch_update','idle') and mode in ('reference','light'),'Invalid transition/mode')
|
||||
case,parent=Path(case),Path(parent);spec=read(case/'spec.json');summary=read(parent/'summary.json')
|
||||
offset=summary.get('global_next_tick',summary['steps'])
|
||||
require(spec['global_tick_offset']==offset and spec['parent_checkpoint_manifest_sha256']==digest(parent/'checkpoint-manifest.json'),
|
||||
'Case does not identify exact parent/clock')
|
||||
before=effective_hash(spec,before_overlay['overlay_file']);after=effective_hash(spec,after_overlay['overlay_file'])
|
||||
require(before==summary['effective_weights_raw_sha256'],'Before effective weight is not parent installation')
|
||||
update=None
|
||||
if transition=='epoch_update':
|
||||
require(epoch is not None and update_dir is not None and cpu_receipt is not None,'Missing actual update evidence')
|
||||
update=dict(epoch_authority=pin(epoch),files={n:pin(Path(update_dir)/n) for n in
|
||||
('chain-receipt.json','update-receipt.json','delta-after.npz','overlay-manifest.json')})
|
||||
else:
|
||||
require(epoch is update_dir is cpu_receipt is None and before==after,'Idle cannot include a new update')
|
||||
return dict(schema='conditioning-updated-boundary-v1',boundary_id=boundary_id,registration_sha256=registration_sha256,
|
||||
transition=transition,diagnostic_mode=mode,input_policy=input_policy,
|
||||
case=dict(spec=pin(case/'spec.json'),requests=pin(case/'requests.npz')),
|
||||
parent=dict(directory=str(parent),checkpoint_manifest_sha256=digest(parent/'checkpoint-manifest.json')),
|
||||
global_tick_offset=offset,
|
||||
overlay_before=dict(file=pin(before_overlay['overlay_file']),manifest=pin(before_overlay['overlay_manifest'])),
|
||||
overlay_after=dict(file=pin(after_overlay['overlay_file']),manifest=pin(after_overlay['overlay_manifest'])),
|
||||
expected_effective_weight_before_sha256=before,expected_effective_weight_after_sha256=after,
|
||||
update=update,cpu_validation=None if cpu_receipt is None else pin(cpu_receipt),
|
||||
source_files=copy.deepcopy(source_files),frozen_inputs=copy.deepcopy(frozen_inputs))
|
||||
@@ -0,0 +1,168 @@
|
||||
"""Pure normal-suite cost proposal from externally authenticated parent receipts.
|
||||
|
||||
No process/file authentication occurs here. Every cycle, process event and full
|
||||
output inventory must be bound to a caller-authenticated receipt SHA. Parent
|
||||
monotonic stamps cover before-spawn through exit and independent postvalidation;
|
||||
worker slot/core timing is never an end-to-end measurement. All clocks within a
|
||||
cycle share its clock_id. Context SHA externally binds machine/code/runtime and
|
||||
the exact proposed execution/output-retention policy, not merely a GPU model.
|
||||
Observed maxima plus explicit reserves are conservative estimates, not guarantees
|
||||
for future learning-dependent activity. No fitting, shortening or authorization.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import deepcopy
|
||||
import math
|
||||
|
||||
|
||||
SCHEMA = 'conditioning-cost-cycle-v1'
|
||||
N, E = 166700, 25582938
|
||||
INVENTORY = dict(training_calls=30000, probe_calls=3920, brain_calls=33920,
|
||||
steps_per_call=1200, total_steps=40704000, biological_seconds=4070.4,
|
||||
original_E_calls=30000, CPU_validator_calls=30000)
|
||||
RESERVE_ROLES = {'sampler_input', 'parent_hash', 'final_integrity', 'compiler_warmup', 'unknown_activity'}
|
||||
OUTPUT_SCOPE = 'entire_cycle_tree_including_inputs_build_logs_receipts'
|
||||
CYCLE_FIELDS = {'schema','cycle_id','kind','diagnostic_mode','steps','neurons','edges','dt_ms',
|
||||
'context_sha256','clock_id','started_s','validated_s','authority','events','outputs','complete'}
|
||||
EVENT_FIELDS = {'event_id','role','receipt_kind','receipt','spawn_s','exit_s','validated_s',
|
||||
'exit_code','core_seconds','runtime_seconds','child_wall_seconds'}
|
||||
|
||||
|
||||
def _require(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def _sha(value):
|
||||
return type(value) is str and len(value) == 64 and all(c in '0123456789abcdef' for c in value)
|
||||
|
||||
|
||||
def _number(value):
|
||||
return type(value) in (int,float) and math.isfinite(value) and value >= 0
|
||||
|
||||
|
||||
def _text(value):
|
||||
return type(value) is str and bool(value) and value.strip() == value
|
||||
|
||||
|
||||
def _binding(value, authenticated):
|
||||
_require(type(value) is dict and set(value) == {'receipt_id','sha256'} and
|
||||
_text(value['receipt_id']) and _sha(value['sha256']) and
|
||||
authenticated.get(value['receipt_id']) == value['sha256'], 'Unauthenticated receipt descriptor')
|
||||
|
||||
|
||||
def _measure(row, authenticated, used):
|
||||
_require(type(row) is dict and set(row) == CYCLE_FIELDS and row['schema'] == SCHEMA and
|
||||
row['complete'] is True, 'Explicit complete authoritative cycle required; no worker-slot adapter')
|
||||
_require(_text(row['cycle_id']) and _text(row['clock_id']) and _sha(row['context_sha256']), 'Missing cycle identity/context/clock')
|
||||
_binding(row['authority'], authenticated)
|
||||
_require(row['kind'] in ('training','probe','state_only_idle') and
|
||||
row['diagnostic_mode'] in ('light','reference'), 'Unsupported cycle kind/mode')
|
||||
_require(type(row['steps']) is int and row['steps'] > 0 and type(row['neurons']) is int and
|
||||
row['neurons'] == N and type(row['edges']) is int and row['edges'] == E and
|
||||
type(row['dt_ms']) in (int,float) and row['dt_ms'] == .1, 'Full frozen graph/clock required')
|
||||
_require(all(_number(row[k]) for k in ('started_s','validated_s')) and
|
||||
row['validated_s'] > row['started_s'], 'Invalid whole-cycle timing')
|
||||
events = row['events']
|
||||
roles = ['brain','original_E','cpu_validator'] if row['kind'] == 'training' else ['brain']
|
||||
_require(type(events) is list and [e.get('role') for e in events if type(e) is dict] == roles,
|
||||
'Training requires brain + original E + CPU validator; probes/idle must not update')
|
||||
previous, totals = row['started_s'], dict(core_seconds=0.,runtime_seconds=0.,child_wall_seconds=0.)
|
||||
measured = {key: True for key in totals}
|
||||
receipt_ids = [row['authority']['receipt_id']]
|
||||
for event in events:
|
||||
_require(type(event) is dict and set(event) == EVENT_FIELDS and _text(event['event_id']) and
|
||||
('event',event['event_id']) not in used and event['receipt_kind'] == 'parent-process' and
|
||||
type(event['exit_code']) is int and event['exit_code'] == 0, 'Actual successful unique parent process required')
|
||||
used.add(('event',event['event_id']))
|
||||
_binding(event['receipt'], authenticated)
|
||||
receipt_ids.append(event['receipt']['receipt_id'])
|
||||
_require(all(_number(event[k]) for k in ('spawn_s','exit_s','validated_s')) and
|
||||
previous <= event['spawn_s'] < event['exit_s'] <= event['validated_s'] <= row['validated_s'],
|
||||
'Event clock ordering/whole-cycle binding failed')
|
||||
previous = event['validated_s']
|
||||
child = event['exit_s'] - event['spawn_s']
|
||||
_require(_number(event['child_wall_seconds']) and math.isclose(event['child_wall_seconds'],child,rel_tol=1e-12),
|
||||
'Child wall must be actual parent spawn-to-exit time')
|
||||
upper = child
|
||||
for key in ('runtime_seconds','core_seconds'):
|
||||
value = event[key]
|
||||
if value is not None:
|
||||
_require(_number(value) and value <= upper, 'Core/runtime/child timing layers inconsistent')
|
||||
upper = value
|
||||
for key in totals:
|
||||
if event[key] is None:
|
||||
measured[key] = False
|
||||
else:
|
||||
totals[key] += event[key]
|
||||
outputs = row['outputs']
|
||||
_require(type(outputs) is dict and set(outputs) == {'inventory','scope','complete','total_bytes'} and
|
||||
outputs['scope'] == OUTPUT_SCOPE and outputs['complete'] is True and
|
||||
type(outputs['total_bytes']) is int and outputs['total_bytes'] > 0, 'Actual complete cycle output inventory required')
|
||||
_binding(outputs['inventory'], authenticated)
|
||||
receipt_ids.append(outputs['inventory']['receipt_id'])
|
||||
_require(len(set(receipt_ids)) == len(receipt_ids), 'Cycle/event/output receipts must have distinct identities')
|
||||
_require(not any(('receipt',key) in used for key in receipt_ids), 'Receipt reused across purported independent cycles')
|
||||
used.update(('receipt',key) for key in receipt_ids)
|
||||
return dict(cycle_id=row['cycle_id'], kind=row['kind'], diagnostic_mode=row['diagnostic_mode'],
|
||||
steps=row['steps'], context_sha256=row['context_sha256'],
|
||||
timing={**{k: totals[k] if measured[k] else None for k in totals},
|
||||
'end_to_end_seconds':row['validated_s']-row['started_s']}, output_bytes=outputs['total_bytes'])
|
||||
|
||||
|
||||
def estimate_normal_suite(cycles, *, authenticated_receipts, target_context_sha256, reserves, limits=None):
|
||||
"""Return proposal or INSUFFICIENT-MEASUREMENTS, never permission to execute.
|
||||
|
||||
reserves requires cycle_multiplier>=1 plus all RESERVE_ROLES, each with
|
||||
wall_seconds/output_bytes/basis. Explicit zero is permitted with a stated
|
||||
basis (e.g. already included); none are silently assumed zero. limits, when
|
||||
supplied, must specify wall_seconds and output_bytes caps for this proposal.
|
||||
Only matched-context light complete 1200-tick cycles enter extrapolation.
|
||||
"""
|
||||
_require(type(cycles) is list and type(authenticated_receipts) is dict and
|
||||
all(_text(k) and _sha(v) for k,v in authenticated_receipts.items()) and
|
||||
_sha(target_context_sha256), 'Explicit authenticated receipt/context descriptors required')
|
||||
_require(type(reserves) is dict and set(reserves) == RESERVE_ROLES | {'cycle_multiplier'} and
|
||||
_number(reserves['cycle_multiplier']) and reserves['cycle_multiplier'] >= 1, 'Explicit complete reserves required')
|
||||
for role in RESERVE_ROLES:
|
||||
reserve = reserves[role]
|
||||
_require(type(reserve) is dict and set(reserve) == {'wall_seconds','output_bytes','basis'} and
|
||||
_number(reserve['wall_seconds']) and type(reserve['output_bytes']) is int and
|
||||
reserve['output_bytes'] >= 0 and _text(reserve['basis']), 'Invalid explicit reserve: '+role)
|
||||
if limits is not None:
|
||||
_require(type(limits) is dict and set(limits) == {'wall_seconds','output_bytes'} and
|
||||
_number(limits['wall_seconds']) and limits['wall_seconds'] > 0 and
|
||||
type(limits['output_bytes']) is int and limits['output_bytes'] > 0, 'Invalid resource caps')
|
||||
used = set()
|
||||
measured = [_measure(row,authenticated_receipts,used) for row in cycles]
|
||||
_require(len({r['cycle_id'] for r in measured}) == len(measured), 'Duplicate cycles')
|
||||
eligible = {kind:[r for r in measured if r['kind'] == kind and r['diagnostic_mode'] == 'light' and
|
||||
r['steps'] == 1200 and r['context_sha256'] == target_context_sha256] for kind in ('training','probe')}
|
||||
missing = [kind+' complete matched-context light 1200-tick cycle' for kind,rows in eligible.items() if not rows]
|
||||
result = dict(status='INSUFFICIENT-MEASUREMENTS' if missing else 'ESTIMATED-NOT-AUTHORIZED',
|
||||
inventory=deepcopy(INVENTORY), measured_cycles=measured, missing=missing,
|
||||
eligible_cycle_ids={kind:[r['cycle_id'] for r in rows] for kind,rows in eligible.items()},
|
||||
symbolic_wall='cycle_multiplier * (30000 * max(train_end_to_end) + 3920 * max(probe_end_to_end)) + explicit_reserves',
|
||||
symbolic_storage='cycle_multiplier * (30000 * max(train_full_bytes) + 3920 * max(probe_full_bytes)) + explicit_reserves',
|
||||
estimated_wall_seconds=None, estimated_output_bytes=None, caps=deepcopy(limits), caps_pass=None,
|
||||
reserves=deepcopy(reserves), basis='observed maxima; no fitted throughput, amortization or deletion assumptions',
|
||||
limitations=['caller authenticates receipt bytes, event identity, complete inventories and execution context',
|
||||
'reference and state-only idle are diagnostics only, never light training performance',
|
||||
'observed maxima cannot bound unobserved learning-dependent activity or contention',
|
||||
'retains every measured cycle output; no assumed cleanup/deduplication/compression gain',
|
||||
'reserve coverage and sufficiency remain caller responsibilities; no guarantee'],
|
||||
engineering_scope='measurement/interface evidence only, not learning PASS',
|
||||
external_identity_verified_here=False, scientific_learning_claimed=False, execution_authorized=False,
|
||||
on_limit='STOP; never_reduce_inventory_or_shorten_trials')
|
||||
if missing:
|
||||
return result
|
||||
count = {'training':30000,'probe':3920}
|
||||
wall = sum(count[k]*max(r['timing']['end_to_end_seconds'] for r in rows) for k,rows in eligible.items())
|
||||
size = sum(count[k]*max(r['output_bytes'] for r in rows) for k,rows in eligible.items())
|
||||
result['estimated_wall_seconds'] = math.ceil(reserves['cycle_multiplier']*wall + sum(reserves[k]['wall_seconds'] for k in RESERVE_ROLES))
|
||||
result['estimated_output_bytes'] = math.ceil(reserves['cycle_multiplier']*size + sum(reserves[k]['output_bytes'] for k in RESERVE_ROLES))
|
||||
if limits is not None:
|
||||
result['caps_pass'] = result['estimated_wall_seconds'] <= limits['wall_seconds'] and result['estimated_output_bytes'] <= limits['output_bytes']
|
||||
if not result['caps_pass']:
|
||||
result['status'] = 'STOP-BUDGET-EXCEEDED'
|
||||
return result
|
||||
@@ -0,0 +1,320 @@
|
||||
"""Finite, process-isolated boundary experiment; NOT the conditioning runner.
|
||||
|
||||
Requires external preregistration SHA and exclusive outputs. No automatic retry.
|
||||
The old AP worker is invoked as an executable only, never imported as a neural
|
||||
module into this coordinator. Every child exit and output inventory is checked.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import copy
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import numpy as np
|
||||
|
||||
import boundary_plan as PLAN
|
||||
import execution_authority as A
|
||||
import isolated_execution as W
|
||||
from prepare_execution import ROOT, MODEL, EXP, AP, LAB, save, save_npz, npz, verify, copy_exclusive
|
||||
|
||||
require,read,digest=A.require,A.read,A.digest
|
||||
AP_WORKER=MODEL.parent/'conditioning-interface-v2/isolated_workers.py'
|
||||
|
||||
|
||||
def registration(expected):
|
||||
file=EXP/'protocol/preregistered.json'
|
||||
require(digest(file)==expected,'External registration SHA changed')
|
||||
reg=read(file)
|
||||
require(reg['schema']=='conditioning-execution-registration-v1' and reg['engineering_only'] is True and
|
||||
reg['scientific_acquisition_authorized'] is False,'Wrong experiment authority')
|
||||
PLAN.validate_plan(reg['plan'])
|
||||
verify({**reg['source_sha256'],**reg['input_sha256'],**reg['prepared_file_sha256']})
|
||||
return reg
|
||||
|
||||
|
||||
def tree(directory,*,exclude_build=False):
|
||||
result={}
|
||||
for p in sorted(Path(directory).rglob('*')):
|
||||
require(not p.is_symlink(),'Linked output forbidden')
|
||||
if exclude_build and p.relative_to(directory).parts[0]=='extension-build':continue
|
||||
if p.is_file():result[p.relative_to(directory).as_posix()]=dict(sha256=digest(p),bytes=p.stat().st_size)
|
||||
else:require(p.is_dir(),'Nonregular output forbidden')
|
||||
return result
|
||||
|
||||
|
||||
class Workflow:
|
||||
def __init__(self,sha):
|
||||
self.started=time.perf_counter();self.sha=sha;self.reg=registration(sha)
|
||||
self.deadline=self.started+self.reg['budget']['workflow_timeout_seconds']
|
||||
self.parents=copy.deepcopy(self.reg['parent_records']);self.jobs={};self.boundaries={}
|
||||
self.completed=[];self.cycles=[];self.sampler=None
|
||||
self.h=W.ap_helpers()
|
||||
|
||||
def admission(self):
|
||||
require(time.perf_counter()<self.deadline,'Whole-workflow wall limit reached')
|
||||
require(not any((EXP/n).exists() for n in ('audit/stopped.json','audit/execution-complete.json','manifest.json')),
|
||||
'Stopped/completed workflow cannot be retried')
|
||||
budget=self.reg['budget'];used=sum(p.stat().st_size for p in EXP.rglob('*') if p.is_file())
|
||||
require(used<=budget['output_cap_bytes'] and shutil.disk_usage(EXP).free>=
|
||||
budget['minimum_free_reserve_bytes']+max(0,budget['output_cap_bytes']-used),'Finite disk cap/reserve exceeded')
|
||||
|
||||
def allpins(self):
|
||||
return {**self.reg['source_sha256'],**self.reg['input_sha256'],**self.reg['prepared_file_sha256'],
|
||||
str(EXP/'protocol/preregistered.json'):self.sha}
|
||||
|
||||
def launch(self,name,job,*,ap=False):
|
||||
self.admission()
|
||||
loc={n:EXP/f'{sub}/{name}{suffix}' for n,sub,suffix in
|
||||
(('job','jobs','.json'),('receipt','receipts','.worker.json'),('process','receipts','.process.json'),
|
||||
('stdout','logs','.stdout.log'),('stderr','logs','.stderr.log'))}
|
||||
require(not any(p.exists() for p in loc.values()),'Exclusive process record exists; no retry')
|
||||
require(job['receipt_file']==str(loc['receipt']),'Receipt location differs')
|
||||
save(loc['job'],job);jobsha=digest(loc['job'])
|
||||
script=AP_WORKER if ap else MODEL/'isolated_execution.py'
|
||||
command=[sys.executable,'-B',str(script)]
|
||||
if ap:command.append(job['kind'])
|
||||
command+=['--job',str(loc['job']),'--job-sha256',jobsha]
|
||||
start=time.perf_counter();started_utc=datetime.now(timezone.utc).isoformat()
|
||||
timeout=min(self.reg['budget']['child_timeout_seconds'],self.deadline-start)
|
||||
require(timeout>0,'No remaining workflow wall allowance')
|
||||
timed_out=False;exit_code=None
|
||||
with loc['stdout'].open('xb') as out,loc['stderr'].open('xb') as err:
|
||||
try:exit_code=subprocess.run(command,cwd=MODEL,stdout=out,stderr=err,timeout=timeout).returncode
|
||||
except subprocess.TimeoutExpired:timed_out=True
|
||||
exited=time.perf_counter()
|
||||
base=dict(schema='conditioning-execution-process-v1',name=name,kind=job['kind'],registration_sha256=self.sha,
|
||||
argv=command,job_sha256=jobsha,exit_code=exit_code,timed_out=timed_out,started_utc=started_utc,
|
||||
spawn_monotonic=start,exit_monotonic=exited,child_wall_seconds=exited-start,
|
||||
stdout_sha256=digest(loc['stdout']),stderr_sha256=digest(loc['stderr']))
|
||||
try:
|
||||
require(exit_code==0 and not timed_out and loc['receipt'].is_file(),'Child failed; preserve partial outputs')
|
||||
receipt=read(loc['receipt']);expected='phase4ap-isolated-worker-receipt-v1' if ap else 'conditioning-isolated-execution-receipt-v1'
|
||||
require(receipt['schema']==expected and receipt['complete'] is True and receipt['job_sha256']==jobsha and
|
||||
receipt['registration_sha256']==self.sha and receipt['kind']==job['kind'] and
|
||||
receipt['job_id']==job['job_id'] and receipt['worker_sha256']==job['worker_sha256'],
|
||||
'Real worker receipt identity differs')
|
||||
expectedpins={**job['input_sha256'],str(loc['job']):jobsha,str(script):job['worker_sha256']}
|
||||
if not ap:
|
||||
expectedpins[str(AP_WORKER)]=W.AP_SHA
|
||||
expectedpins.update({str(MODEL/n):s for n,s in job['source_sha256'].items()})
|
||||
else:expectedpins.update({v['path']:v['sha256'] for v in job['sources'].values()})
|
||||
require(receipt['verified_input_sha256' if ap else 'input_sha256']==expectedpins,
|
||||
'Child did not verify exact external source/input closure')
|
||||
actual={k:v['sha256'] for k,v in tree(Path(job['output_dir'])).items()}
|
||||
require(actual and actual==receipt['output_files_sha256'] and receipt['output_dir']==job['output_dir'],
|
||||
'Actual output inventory differs from successful worker')
|
||||
require(digest(str(loc['receipt'])+'.attempt.json')==receipt['attempt_sha256'],'Attempt record changed')
|
||||
verify(expectedpins);self.admission()
|
||||
end=time.perf_counter()
|
||||
record=dict(base,complete=True,worker_receipt_sha256=digest(loc['receipt']),
|
||||
validation_end_monotonic=end,end_to_end_seconds=end-start,validation_wall_seconds=end-exited,
|
||||
output_bytes=sum(v['bytes'] for v in tree(Path(job['output_dir'])).values()),
|
||||
output_inventory_sha256=hashlib.sha256(json.dumps(actual,sort_keys=True).encode()).hexdigest(),
|
||||
timing_scope='before child spawn through actual exit and independent parent file verification')
|
||||
save(loc['process'],record)
|
||||
except BaseException as exc:
|
||||
if not loc['process'].exists():save(loc['process'],dict(base,complete=False,error_type=type(exc).__name__,error=str(exc)))
|
||||
raise
|
||||
self.jobs[name]=dict(loc={k:str(v) for k,v in loc.items()},job=job,process=record,receipt=receipt)
|
||||
print(json.dumps(dict(child=name,complete=True,end_to_end_seconds=record['end_to_end_seconds']),sort_keys=True),flush=True)
|
||||
return receipt
|
||||
|
||||
def new_job(self,name,kind,authority,*,output=None,**extra):
|
||||
auth=read(authority);pins=self.allpins();pins[str(authority)]=digest(authority)
|
||||
if kind=='sample':pass
|
||||
else:pins.update(A.files_from_authority(auth))
|
||||
return dict(schema=W.SCHEMA,job_id=name,kind=kind,registration_sha256=self.sha,
|
||||
worker_sha256=self.reg['source_sha256'][str(MODEL/'isolated_execution.py')],
|
||||
source_sha256={n:self.reg['source_sha256'][str(MODEL/n)] for n in W.SOURCES[kind]},input_sha256=pins,
|
||||
output_dir=str(output or EXP/'runs'/name),receipt_file=str(EXP/'receipts'/f'{name}.worker.json'),
|
||||
budget={k:self.reg['budget'][k] for k in ('root','output_cap_bytes','minimum_free_reserve_bytes')},
|
||||
authority_file=str(authority),authority_sha256=digest(authority),**extra)
|
||||
|
||||
def ap_job(self,name,kind,*,case=None,overlay=None,authority=None,output):
|
||||
pins=self.allpins()
|
||||
job=dict(schema='phase4ap-isolated-worker-job-v1',job_id=name,kind=kind,registration_sha256=self.sha,
|
||||
worker_sha256=W.AP_SHA,output_dir=str(output),receipt_file=str(EXP/'receipts'/f'{name}.worker.json'))
|
||||
if kind=='brain':
|
||||
for path in (case/'spec.json',case/'requests.npz',overlay['overlay_file'],overlay['overlay_manifest']):pins[str(path)]=digest(path)
|
||||
job.update(case_dir=str(case),build_root=str(EXP/'extension-build'),**overlay,diagnostic_mode='light' if name.startswith('performance') else 'reference',
|
||||
admission=dict(gpu_uuid=self.h.GPU,comfy_queue_urls=list(self.h.COMFY_URLS)),
|
||||
sources={n:dict(path=str(LAB/(n+'.py')),sha256=self.h.SOURCE_PINS[n]) for n in ('runtime_light','runtime_continuation')})
|
||||
else:
|
||||
value=read(authority);pins.update(A.files_from_authority(value));pins[str(authority)]=digest(authority)
|
||||
job.update(authority_file=str(authority),authority_sha256=digest(authority),
|
||||
sources={'conditioning_epoch':dict(path=str(LAB/'conditioning_epoch.py'),sha256=self.h.SOURCE_PINS['conditioning_epoch'])})
|
||||
job['input_sha256']=pins
|
||||
return job
|
||||
|
||||
def cpu_verify(self,key,parent):
|
||||
name=key+'--cpu-verify';authority=Path(parent['epoch_authority']['path']);update=Path(parent['update_dir'])
|
||||
job=self.new_job(name,'validate_cpu',authority,update_dir=str(update),chain_sha256=digest(update/'chain-receipt.json'))
|
||||
# Original epoch authority doesn't include its future update files.
|
||||
job['input_sha256'].update({str(p):digest(p) for p in update.iterdir()})
|
||||
self.launch(name,job)
|
||||
parent['cpu_validation']=str(Path(job['output_dir'])/'validation.json')
|
||||
|
||||
def materialize(self,call,parent=None):
|
||||
group=call['case_group'];case=EXP/'cases'/group
|
||||
spec=read(self.reg['case_templates'][group])
|
||||
if parent is not None:
|
||||
spec.update(parent_checkpoint_manifest_sha256=parent['checkpoint_sha256'],global_tick_offset=call['global_tick_offset'])
|
||||
if call['runner']=='runtime_light' and call['call_id'].startswith('performance'):
|
||||
request=Path(self.parents[self.reg['plan']['imported_parents']['D1']['role']]['epoch_authority']['path'])
|
||||
source=Path(read(request)['files']['requests']['path']);arrays=None
|
||||
elif call['runner']=='runtime_light':source=EXP/'inputs/static/mechanical-requests.npz';arrays=None
|
||||
elif call['runner']=='boundary_oracle':
|
||||
pp=self.parents[call['prefix_replay_parent']]
|
||||
arrays=npz(read(pp['epoch_authority']['path'])['files']['requests']['path']);source=None
|
||||
elif call['input_policy']=='externally_pinned_CS_probe':
|
||||
require(self.sampler is not None,'Evaluation input not actually sampled')
|
||||
source=Path(self.sampler['output_dir'])/f"{call['cue']}-requests.npz";arrays=None
|
||||
else:source=None;arrays=dict(tick=np.empty(0,np.int32),neuron_idx=np.empty(0,np.int32))
|
||||
if case.exists():
|
||||
require(read(case/'spec.json')==spec,'Shared case metadata differs')
|
||||
if source:require(digest(case/'requests.npz')==digest(source),'Shared saved inputs differ')
|
||||
else:require(all(npz(case/'requests.npz')[k].tobytes()==v.tobytes() for k,v in arrays.items()),'Shared request arrays differ')
|
||||
else:
|
||||
case.mkdir();save(case/'spec.json',spec)
|
||||
if source:copy_exclusive(source,case/'requests.npz')
|
||||
else:save_npz(case/'requests.npz',arrays)
|
||||
return case
|
||||
|
||||
def sources(self,epoch):
|
||||
files=copy.deepcopy(epoch['files'])
|
||||
roles=('runtime_continuation_source','runtime_light_source','conditioning_update_source',
|
||||
'eligibility_bridge_source','phase4j_source','am_overlay_source')
|
||||
result={r:files[r] for r in roles}
|
||||
for role,name in (('conditioning_epoch_source','conditioning_epoch.py'),
|
||||
('conditioning_preflight_compare_source','conditioning_preflight_compare.py'),
|
||||
('engineering_compare_source','engineering_compare.py')):result[role]=A.pin(LAB/name)
|
||||
for role,name in (('updated_continuation_source','updated_continuation.py'),('cpu_validator_source','validate_update_cpu.py')):
|
||||
result[role]=A.pin(MODEL/name)
|
||||
return result
|
||||
|
||||
def boundary(self,call,case,parent):
|
||||
transition=call['transition'];epoch=read(parent['epoch_authority']['path'])
|
||||
before=parent['before_overlay'] if transition=='epoch_update' else parent['after_overlay']
|
||||
path=EXP/'authorities'/f"{call['call_id']}.json"
|
||||
value=A.boundary_authority(boundary_id=call['call_id'],registration_sha256=self.sha,case=case,parent=parent['directory'],
|
||||
transition=transition,input_policy=call['input_policy'],mode=call['diagnostic_mode'],
|
||||
before_overlay=before,after_overlay=parent['after_overlay'],source_files=self.sources(epoch),frozen_inputs=epoch['frozen_inputs'],
|
||||
epoch=parent['epoch_authority']['path'] if transition=='epoch_update' else None,
|
||||
update_dir=parent['update_dir'] if transition=='epoch_update' else None,
|
||||
cpu_receipt=parent['cpu_validation'] if transition=='epoch_update' else None)
|
||||
save(path,value);self.boundaries[call['call_id']]=path
|
||||
return path
|
||||
|
||||
def fresh(self,call):
|
||||
name=call['call_id'];case=self.materialize(call)
|
||||
performance=name.startswith('performance')
|
||||
prior=self.parents[self.reg['plan']['imported_parents']['D1']['role']]
|
||||
overlay=prior['before_overlay'] if performance else self.reg['initial_overlay']
|
||||
output=EXP/'runs'/name
|
||||
result=self.launch(name,self.ap_job(name,'brain',case=case,overlay=overlay,output=output),ap=True)
|
||||
auth=EXP/'authorities'/f'{name}.epoch.json'
|
||||
value=A.epoch_authority(read(prior['epoch_authority']['path']),case=case,checkpoint=output,overlay=overlay,
|
||||
epoch_id=name,us_tick=900 if performance else 1199)
|
||||
save(auth,value);update=EXP/'updates'/name
|
||||
self.launch(name+'--original-E',self.ap_job(name+'--original-E','update',authority=auth,output=update),ap=True)
|
||||
parent=dict(directory=str(output),checkpoint_sha256=result['result']['checkpoint_manifest_sha256'],
|
||||
epoch_authority=A.pin(auth),update_dir=str(update),before_overlay=overlay,
|
||||
after_overlay=dict(overlay_file=str(update/'delta-after.npz'),overlay_manifest=str(update/'overlay-manifest.json')))
|
||||
self.cpu_verify(name,parent);self.parents[name]=parent
|
||||
return result
|
||||
|
||||
def execute_call(self,call):
|
||||
name=call['call_id'];runner=call['runner']
|
||||
if runner=='runtime_light':return self.fresh(call)
|
||||
if runner=='fresh_probe':
|
||||
require(call.get('US') is False and call.get('plastic_update') is False and
|
||||
call.get('feedback_to_idle') is False and call['parent'] is None and
|
||||
call['overlay_after_role']=='AP.initial_overlay','Fresh probe scope differs')
|
||||
case=self.materialize(call)
|
||||
output=EXP/'runs'/name
|
||||
result=self.launch(name,self.ap_job(name,'brain',case=case,overlay=self.reg['initial_overlay'],output=output),ap=True)
|
||||
return result
|
||||
if runner=='boundary_oracle':
|
||||
ref='mechanical--updated--reference' if name.startswith('mechanical') else 'D1--updated--reference'
|
||||
authority=self.boundaries[ref];case=self.materialize(call)
|
||||
job=self.new_job(name,'oracle',authority,build_root=str(EXP/'extension-build'),oracle_case=str(case),
|
||||
oracle_spec_sha256=digest(case/'spec.json'),oracle_requests_sha256=digest(case/'requests.npz'))
|
||||
job['input_sha256'].update({str(case/n):digest(case/n) for n in ('spec.json','requests.npz')})
|
||||
else:
|
||||
parent=self.parents[call['parent']];case=self.materialize(call,parent)
|
||||
if runner=='runtime_continuation':
|
||||
authority=self.boundaries[name.split('--')[0]+'--updated--reference']
|
||||
job=self.new_job(name,'unchanged',authority,case_dir=str(case),build_root=str(EXP/'extension-build'),
|
||||
diagnostic_mode='reference',checkpoint_dir=parent['directory'],checkpoint_sha256=parent['checkpoint_sha256'],**parent['before_overlay'])
|
||||
else:
|
||||
if call['input_policy']=='externally_pinned_CS_probe':
|
||||
require(call.get('US') is False and call.get('plastic_update') is False and call.get('feedback_to_idle') is False,
|
||||
'Probe cannot request US, updates, or feed idle')
|
||||
authority=self.boundary(call,case,parent)
|
||||
job=self.new_job(name,'updated',authority,build_root=str(EXP/'extension-build'),diagnostic_mode=call['diagnostic_mode'])
|
||||
result=self.launch(name,job)
|
||||
if runner=='updated_continuation':
|
||||
parent=self.parents[call['parent']]
|
||||
self.parents[name]={**copy.deepcopy(parent), 'directory':job['output_dir'],
|
||||
'checkpoint_sha256':result['result']['checkpoint_manifest_sha256'],
|
||||
'before_overlay':parent['after_overlay']}
|
||||
return result
|
||||
|
||||
def run(self):
|
||||
attempt=EXP/'audit/execution-attempt.json'
|
||||
require(not attempt.exists(),'Workflow already attempted; no automatic retry')
|
||||
save(attempt,dict(registration_sha256=self.sha,started_utc=datetime.now(timezone.utc).isoformat(),
|
||||
pid=os.getpid(),monotonic_origin=self.started,no_automatic_retry=True))
|
||||
for arm,descriptor in self.reg['plan']['imported_parents'].items():self.cpu_verify('AP-'+arm,self.parents[descriptor['role']])
|
||||
for call in self.reg['plan']['calls']:
|
||||
if call['input_policy']=='externally_pinned_CS_probe' and self.sampler is None:
|
||||
job=self.new_job('evaluation-inputs','sample',EXP/'protocol/preregistered.json')
|
||||
self.sampler=self.launch('evaluation-inputs',job)
|
||||
started=time.perf_counter();before=tree(EXP,exclude_build=True)
|
||||
build_before=tree(EXP/'extension-build') if (EXP/'extension-build').is_dir() else {}
|
||||
self.execute_call(call)
|
||||
after=tree(EXP,exclude_build=True)
|
||||
build_after=tree(EXP/'extension-build') if (EXP/'extension-build').is_dir() else {}
|
||||
end=time.perf_counter()
|
||||
self.admission()
|
||||
require(all(k in after and after[k]==v for k,v in before.items()),'Earlier output was modified')
|
||||
created={k:v for k,v in after.items() if k not in before}
|
||||
record=dict(call=call,complete=True,start_monotonic=started,end_monotonic=end,wall_seconds=end-started,
|
||||
output_inventory=created,output_bytes=sum(v['bytes'] for v in created.values()),
|
||||
mutable_build_inventory_before=build_before,mutable_build_inventory_after=build_after,
|
||||
mutable_build_bytes_before=sum(v['bytes'] for v in build_before.values()),
|
||||
mutable_build_bytes_after=sum(v['bytes'] for v in build_after.values()),
|
||||
inventory_scope='all new immutable artifacts; separate actual mutable build before/after inventory; shared prior setup excluded',
|
||||
source_registration_sha256=self.sha,learning_pass_claimed=False)
|
||||
save(EXP/'receipts'/f"{call['call_id']}.cycle.json",record)
|
||||
self.cycles.append(record);self.completed.append(call['call_id'])
|
||||
self.admission()
|
||||
require(len(self.completed)==self.reg['plan']['counts']['new_brain_calls'] and
|
||||
len(self.jobs)==self.reg['plan']['counts']['total_children'],'Actual finite call inventory differs')
|
||||
self.admission()
|
||||
save(EXP/'audit/execution-complete.json',dict(complete=True,registration_sha256=self.sha,
|
||||
completed_calls=self.completed,processes={k:v['loc']['process'] for k,v in self.jobs.items()},
|
||||
boundary_authorities={k:str(v) for k,v in self.boundaries.items()},parents=self.parents,
|
||||
wall_seconds=time.perf_counter()-self.started,numerical_comparison_complete=False,
|
||||
scientific_learning_pass_claimed=False,candidate_generated=False))
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--registration-sha256',required=True)
|
||||
args=parser.parse_args()
|
||||
try:Workflow(args.registration_sha256).run()
|
||||
except BaseException as exc:
|
||||
stop=EXP/'audit/stopped.json'
|
||||
if stop.parent.is_dir() and not stop.exists():save(stop,dict(complete=False,error_type=type(exc).__name__,error=str(exc),
|
||||
registration_sha256=args.registration_sha256,retry_forbidden=True,traceback=traceback.format_exc()))
|
||||
raise
|
||||
@@ -0,0 +1,124 @@
|
||||
"""Exclusive finite engineering seal; never creates a learned candidate.
|
||||
|
||||
Run only after independent numerical/budget reports and a NEW integrity process.
|
||||
Report hashes are external arguments. Historical regression evidence is preserved,
|
||||
not relabeled as a newly executed five-trial numerical regression.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
from types import ModuleType
|
||||
|
||||
import execution_authority as A
|
||||
from prepare_execution import ROOT, EXP, MODEL, save, verify
|
||||
|
||||
HELPER = ROOT/'models/male-cns-lif/pn-recruitment-audit-v1/publication.py'
|
||||
HELPER_SHA = '7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016'
|
||||
require, read, digest = A.require, A.read, A.digest
|
||||
|
||||
|
||||
def helper():
|
||||
raw = HELPER.read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest() == HELPER_SHA, 'Frozen seal verifier changed')
|
||||
module = ModuleType('_execution_seal_pure_verifier')
|
||||
module.__file__ = str(HELPER)
|
||||
exec(compile(raw, str(HELPER), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def seal(directory):
|
||||
directory = Path(directory)
|
||||
require(directory.is_absolute() and directory.is_dir(), 'Exact real seal root required')
|
||||
require(not any((directory/n).exists() for n in ('manifest.json', 'checksums.sha256')), 'Never replace seal controls')
|
||||
paths = sorted(directory.rglob('*'))
|
||||
require(all(not p.is_symlink() and not (hasattr(p, 'is_junction') and p.is_junction()) and
|
||||
'__pycache__' not in p.parts and (p.is_file() or p.is_dir()) for p in (directory, *paths)),
|
||||
'Unsafe seal payload')
|
||||
files = [dict(path=p.relative_to(directory).as_posix(), bytes=p.stat().st_size, sha256=digest(p))
|
||||
for p in paths if p.is_file()]
|
||||
require(files, 'Empty seal forbidden')
|
||||
save(directory/'manifest.json', dict(root=str(directory), files=files))
|
||||
with (directory/'checksums.sha256').open('x', encoding='utf-8', newline='\n') as out:
|
||||
for row in files:
|
||||
out.write(row['sha256']+' '+row['path']+'\n')
|
||||
out.write(digest(directory/'manifest.json')+' manifest.json\n')
|
||||
return helper().verify_seal(directory)
|
||||
|
||||
|
||||
def finalize(reg_sha, numerical_sha, budget_sha, integrity_sha):
|
||||
require(sys.dont_write_bytecode and 'torch' not in sys.modules, 'Fresh CPU -B process required')
|
||||
require(not any((EXP/n).exists() for n in ('audit/final-status.json', 'manifest.json', 'checksums.sha256', 'audit/stopped.json')),
|
||||
'Stopped, finalized or partly sealed workflow requires a separate explicit failure audit')
|
||||
reg_path = EXP/'protocol/preregistered.json'
|
||||
require(digest(reg_path) == reg_sha, 'External registration changed')
|
||||
reg = read(reg_path)
|
||||
require(reg['schema'] == 'conditioning-execution-registration-v1' and reg['engineering_only'] is True and
|
||||
reg['scientific_acquisition_authorized'] is False, 'Wrong scope')
|
||||
verify({**reg['source_sha256'], **reg['input_sha256'], **reg['prepared_file_sha256']})
|
||||
reports = {}
|
||||
for key, relative, sha in (
|
||||
('numerical', 'audit/numerical-comparison.json', numerical_sha),
|
||||
('budget', 'audit/budget-report.json', budget_sha),
|
||||
('integrity', 'regression/integrity-after.json', integrity_sha)):
|
||||
path = EXP/relative
|
||||
require(A.pin(path)['sha256'] == sha, 'External '+key+' report changed')
|
||||
reports[key] = read(path)
|
||||
numerical, budget, integrity = (reports[n] for n in ('numerical', 'budget', 'integrity'))
|
||||
require(numerical['schema'] == 'conditioning-execution-numerical-audit-v1' and numerical['complete'] is True and
|
||||
numerical['registration_sha256'] == reg_sha and numerical['actual_new_brain_calls'] == 23 and
|
||||
numerical['actual_processes'] == 31 and numerical['actual_new_brain_ticks'] == 125200 and
|
||||
numerical['learning_pass_claimed'] is numerical['candidate_generated'] is False, 'Wrong numerical coverage/scope')
|
||||
status = numerical['status']
|
||||
require(status in ('PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING',
|
||||
'FAIL-NUMERICAL-OR-LINEAGE', 'INCOMPLETE-CHANGED-EDGE-COVERAGE'), 'Unknown engineering outcome')
|
||||
require(numerical['pass_all'] == status.startswith('PASS-'), 'Inconsistent engineering gate')
|
||||
require(budget['registration_sha256'] == reg_sha and budget['learning_pass_claimed'] is False,
|
||||
'Wrong budget authority or scientific overclaim')
|
||||
require(integrity['complete'] is True and integrity['AP']['pass_all'] is True and
|
||||
integrity['old_experiments_reexecuted'] is integrity['old_files_modified'] is False and
|
||||
integrity['five_frozen_reference_trials_rerun_here'] is integrity['scientific_learning_pass_claimed'] is False,
|
||||
'Historical integrity/scope not verified')
|
||||
# Recheck the actual file-bound evidence at sealing, not only old PASS flags.
|
||||
import audit_execution
|
||||
import budget_report
|
||||
require(audit_execution.same_json(audit_execution.audit(reg_sha, save_report=False), numerical),
|
||||
'Numerical evidence changed after the independent audit')
|
||||
require(audit_execution.same_json(budget_report.report(reg_sha, save_report=False), budget),
|
||||
'Budget evidence changed after the independent audit')
|
||||
# Historical integrity has a different frozen runtime import owner; isolate it.
|
||||
seal_integrity = EXP/'regression/integrity-at-seal.json'
|
||||
require(not seal_integrity.exists(), 'No automatic retry of partly completed finalization')
|
||||
command = [sys.executable, '-B', str(MODEL/'prepare_execution.py'), 'integrity', '--output', str(seal_integrity)]
|
||||
result = subprocess.run(command, cwd=MODEL, capture_output=True, text=True, timeout=1800)
|
||||
require(result.returncode == 0 and seal_integrity.is_file(),
|
||||
'Independent integrity-at-seal process failed: '+result.stderr[-2000:])
|
||||
require(audit_execution.same_json(read(seal_integrity), integrity), 'Frozen integrity changed before sealing')
|
||||
final = dict(schema='conditioning-execution-final-v1', status=status, registration_sha256=reg_sha,
|
||||
numerical_sha256=numerical_sha, budget_sha256=budget_sha, integrity_after_sha256=integrity_sha,
|
||||
integrity_at_seal_sha256=digest(seal_integrity), numerical_and_budget_recomputed_at_seal=True,
|
||||
actual_new_brain_calls=23, actual_new_brain_ticks=125200, actual_execution_child_processes=31,
|
||||
historical_integrity_after_pass=True, historical_five_trial_regression='AM sealed evidence preserved; not rerun here',
|
||||
scientific_acquisition_executed=False, scientific_acquisition_authorized=False,
|
||||
candidate_generated=False, learning_pass_claimed=False,
|
||||
source_code_commit=reg['source_code_commit'], entire_model_directory_sealed=False,
|
||||
source_scope='All registered source bytes and committed snapshot frozen by this experiment seal',
|
||||
bulk_data_git_backup_claimed=False)
|
||||
save(EXP/'audit/final-status.json', final)
|
||||
checked = seal(EXP)
|
||||
return dict(status=status, manifest_sha256=checked['manifest_sha256'], checksums_sha256=checked['checksums_sha256'],
|
||||
final_sha256=digest(EXP/'audit/final-status.json'), payload_files=checked['payload_file_count'],
|
||||
payload_bytes=checked['payload_bytes'], learning_pass_claimed=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
for name in ('registration', 'numerical', 'budget', 'integrity'):
|
||||
parser.add_argument('--'+name+'-sha256', required=True)
|
||||
args = parser.parse_args()
|
||||
print(json.dumps(finalize(args.registration_sha256, args.numerical_sha256, args.budget_sha256,
|
||||
args.integrity_sha256), sort_keys=True), flush=True)
|
||||
@@ -0,0 +1,240 @@
|
||||
"""Fresh exec workers for the NEW boundary-validation branch, not learning.
|
||||
|
||||
The unchanged AP worker supplies read-only path/hash/environment helpers.
|
||||
One worker imports exactly one new scientific entry point. The process parent
|
||||
must authenticate registration, record actual exit status and independently
|
||||
check the result. A worker receipt cannot prove its own future successful exit.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
|
||||
AP_SHA = 'e47651a8ea99d7c44115107ff6b5dc71312183609ae11c891db65bb21ed61e30'
|
||||
MODEL = Path(__file__).resolve().parent
|
||||
AP = MODEL.parent / 'conditioning-interface-v2' / 'isolated_workers.py'
|
||||
SCHEMA = 'conditioning-isolated-execution-job-v1'
|
||||
C_PATH = MODEL.parent/'olfactory-conditioning-lab-v1/runtime_continuation.py'
|
||||
C_SHA = '0b8e8e0a6a23a079dc62a88355ce355d53b3ae22f6665519a8f6aef2dcfc5aba'
|
||||
COMMON = {'schema', 'job_id', 'kind', 'registration_sha256', 'worker_sha256',
|
||||
'source_sha256', 'input_sha256', 'output_dir', 'receipt_file', 'budget'}
|
||||
FIELDS = {
|
||||
'updated': {'authority_file', 'authority_sha256', 'build_root', 'diagnostic_mode'},
|
||||
'oracle': {'authority_file', 'authority_sha256', 'build_root', 'oracle_case',
|
||||
'oracle_spec_sha256', 'oracle_requests_sha256'},
|
||||
'validate_cpu': {'authority_file', 'authority_sha256', 'update_dir', 'chain_sha256'},
|
||||
'unchanged': {'authority_file', 'authority_sha256', 'case_dir', 'build_root', 'diagnostic_mode',
|
||||
'overlay_file', 'overlay_manifest', 'checkpoint_dir', 'checkpoint_sha256'},
|
||||
'sample': {'authority_file', 'authority_sha256'},
|
||||
}
|
||||
SOURCES = {
|
||||
'updated': {'updated_continuation.py'},
|
||||
'oracle': {'updated_continuation.py', 'boundary_oracle.py'},
|
||||
'validate_cpu': {'validate_update_cpu.py'},
|
||||
'unchanged': set(),
|
||||
'sample': {'boundary_sampler.py','boundary_plan.py'},
|
||||
}
|
||||
|
||||
|
||||
def ap_helpers():
|
||||
raw = AP.read_bytes()
|
||||
if hashlib.sha256(raw).hexdigest() != AP_SHA:
|
||||
raise ValueError('Frozen AP helper SHA differs')
|
||||
name = '_conditioning_execution_AP_helpers'
|
||||
if name in sys.modules:
|
||||
raise ValueError('Fresh exec helper binding required')
|
||||
spec = importlib.util.spec_from_file_location(name, AP)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[name] = module
|
||||
exec(compile(raw, str(AP), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def validate_job(h, job_file, expected_sha):
|
||||
job_file = h.absolute_path(str(job_file), kind='file')
|
||||
h.require(h.valid_sha(expected_sha) and h.digest(job_file) == expected_sha, 'External job pin differs')
|
||||
job = h.read_json(job_file)
|
||||
kind = job.get('kind')
|
||||
h.require(kind in FIELDS and set(job) == COMMON | FIELDS[kind] and job['schema'] == SCHEMA,
|
||||
'Wrong job schema/fields')
|
||||
h.require(type(job['job_id']) is str and job['job_id'] and
|
||||
all(c.isascii() and (c.isalnum() or c in '-_') for c in job['job_id']), 'Unsafe job ID')
|
||||
h.require(h.valid_sha(job['registration_sha256']) and job['worker_sha256'] == h.digest(__file__),
|
||||
'Missing registration/worker binding')
|
||||
h.require(type(job['source_sha256']) is dict and set(job['source_sha256']) == SOURCES[kind] and
|
||||
type(job['input_sha256']) is dict and job['input_sha256'], 'Wrong source/input inventory')
|
||||
pins = {job_file: expected_sha, Path(__file__).resolve(): job['worker_sha256'], AP: AP_SHA}
|
||||
for path, sha in job['input_sha256'].items():
|
||||
h._put(pins, h.absolute_path(path, kind='file'), sha)
|
||||
for name, sha in job['source_sha256'].items():
|
||||
h._put(pins, h.absolute_path(str(MODEL / name), kind='file'), sha)
|
||||
authority = h.absolute_path(job['authority_file'], kind='file')
|
||||
h._required(pins, authority, job['authority_sha256'])
|
||||
if kind=='sample':
|
||||
h.require(job['authority_sha256']==job['registration_sha256'],'Sampler registration and authority differ')
|
||||
registered=h.read_json(authority)
|
||||
h.require(registered.get('schema')=='conditioning-execution-registration-v1','Wrong sampler registration')
|
||||
for field in ('source_sha256','input_sha256','prepared_file_sha256'):
|
||||
for path,sha in registered[field].items():h._required(pins,path,sha)
|
||||
output, receipt = (h.absolute_path(job[name]) for name in ('output_dir', 'receipt_file'))
|
||||
attempt = Path(str(receipt) + '.attempt.json')
|
||||
h.require(output.parent.is_dir() and receipt.parent.is_dir() and
|
||||
not any(p.exists() for p in (output, receipt, attempt)), 'Output/receipt exists; no automatic retry')
|
||||
protected = {p.parent for p in pins}
|
||||
h.require(not any(output.is_relative_to(p) or receipt.is_relative_to(p) for p in protected) and
|
||||
not receipt.is_relative_to(output) and not output.is_relative_to(receipt.parent),
|
||||
'Output/receipt overlaps protected input or each other')
|
||||
paths = dict(job=job_file, authority=authority, output=output, receipt=receipt, attempt=attempt)
|
||||
if kind in ('updated', 'oracle', 'unchanged'):
|
||||
build = h.absolute_path(job['build_root'])
|
||||
h.require(not any(build.is_relative_to(p) for p in protected) and not build.is_relative_to(output) and
|
||||
not output.is_relative_to(build), 'Build overlaps protected data')
|
||||
paths['build'] = build
|
||||
if kind in ('updated', 'unchanged'):
|
||||
h.require(job['diagnostic_mode'] in ('light', 'reference'), 'Unknown diagnostic mode')
|
||||
if kind == 'unchanged':
|
||||
h._required(pins, C_PATH, C_SHA)
|
||||
paths['case'] = h.absolute_path(job['case_dir'], kind='dir')
|
||||
paths['checkpoint'] = h.absolute_path(job['checkpoint_dir'], kind='dir')
|
||||
h._required(pins, paths['checkpoint']/'checkpoint-manifest.json', job['checkpoint_sha256'])
|
||||
for role in ('overlay_file', 'overlay_manifest'):
|
||||
paths[role] = h._required(pins, job[role])
|
||||
for name in ('spec.json', 'requests.npz'): h._required(pins, paths['case']/name)
|
||||
h.require(not output.is_relative_to(paths['checkpoint']) and not paths['build'].is_relative_to(paths['checkpoint']),
|
||||
'Execution overlaps frozen parent')
|
||||
elif kind == 'oracle':
|
||||
paths['case'] = h.absolute_path(job['oracle_case'], kind='dir')
|
||||
for name, key in (('spec.json', 'oracle_spec_sha256'), ('requests.npz', 'oracle_requests_sha256')):
|
||||
h._required(pins, paths['case'] / name, job[key])
|
||||
elif kind == 'validate_cpu':
|
||||
paths['update'] = h.absolute_path(job['update_dir'], kind='dir')
|
||||
h._required(pins, paths['update'] / 'chain-receipt.json', job['chain_sha256'])
|
||||
h.require(not output.is_relative_to(paths['update']), 'CPU receipt overlaps source update')
|
||||
budget = job['budget']
|
||||
h.require(type(budget) is dict and set(budget) == {'root', 'output_cap_bytes', 'minimum_free_reserve_bytes'},
|
||||
'Explicit bounded resource plan required')
|
||||
paths['budget'] = h.absolute_path(budget['root'], kind='dir')
|
||||
h.require(paths['budget'].name.startswith('phase4') and output.is_relative_to(paths['budget']) and
|
||||
receipt.is_relative_to(paths['budget']) and
|
||||
(kind in ('validate_cpu','sample') or paths['build'].is_relative_to(paths['budget'])), 'Execution leaves assigned experiment')
|
||||
for name in ('output_cap_bytes', 'minimum_free_reserve_bytes'):
|
||||
h.require(type(budget[name]) is int and budget[name] > 0, 'Positive resource limit required')
|
||||
h.verify_pins(pins)
|
||||
return job, paths, pins
|
||||
|
||||
|
||||
def budget_check(h, job, paths):
|
||||
used = 0
|
||||
for path in paths['budget'].rglob('*'):
|
||||
h.require(not path.is_symlink(), 'Linked output forbidden')
|
||||
if path.is_file():
|
||||
used += path.stat().st_size
|
||||
else:
|
||||
h.require(path.is_dir(), 'Nonregular output forbidden')
|
||||
cap = job['budget']['output_cap_bytes']
|
||||
free = shutil.disk_usage(paths['budget']).free
|
||||
h.require(used <= cap and free >= job['budget']['minimum_free_reserve_bytes'] + max(0, cap - used),
|
||||
'Resource budget exceeded; do not change protocol or retry')
|
||||
return dict(output_bytes=used, free_bytes=free, output_cap_bytes=cap)
|
||||
|
||||
|
||||
def bind_unchanged_authority(h, job, paths, pins):
|
||||
admitted=h.read_json(paths['authority'])
|
||||
h.require(admitted.get('schema')=='conditioning-updated-boundary-v1' and admitted.get('transition')=='epoch_update' and
|
||||
admitted['diagnostic_mode']==job['diagnostic_mode'] and admitted['registration_sha256']==job['registration_sha256'] and
|
||||
admitted['expected_effective_weight_before_sha256']==admitted['expected_effective_weight_after_sha256'],
|
||||
'Old C comparison requires its unchanged-weight registered authority')
|
||||
h.require(admitted['parent']==dict(directory=str(paths['checkpoint']),checkpoint_manifest_sha256=job['checkpoint_sha256']),
|
||||
'Old C job parent differs from authority')
|
||||
for pair,role in ((admitted['case']['spec'],'spec.json'),(admitted['case']['requests'],'requests.npz')):
|
||||
h.require(pair['path']==str(paths['case']/role) and pins[paths['case']/role]==pair['sha256'],
|
||||
'Old C case differs from authority')
|
||||
for role,key in (('file','overlay_file'),('manifest','overlay_manifest')):
|
||||
pair=admitted['overlay_before'][role]
|
||||
h.require(pair['path']==str(paths[key]) and pins[paths[key]]==pair['sha256'],
|
||||
'Old C must use actual before snapshot, not equal after data')
|
||||
def visit(value):
|
||||
if type(value)is dict:
|
||||
if set(value)=={'path','sha256'}:h._required(pins,value['path'],value['sha256'])
|
||||
else:
|
||||
for key,item in value.items():
|
||||
if key=='frozen_inputs':
|
||||
for path,sha in item.items():h._required(pins,path,sha)
|
||||
else:visit(item)
|
||||
elif type(value)is list:
|
||||
for item in value:visit(item)
|
||||
visit(admitted)
|
||||
return admitted
|
||||
|
||||
|
||||
def execute(job_file, expected_sha):
|
||||
started = time.perf_counter()
|
||||
h = ap_helpers()
|
||||
h.require(sys.dont_write_bytecode, 'Use Python -B')
|
||||
job, paths, pins = validate_job(h, job_file, expected_sha)
|
||||
kind = job['kind']
|
||||
h._clean_process('update' if kind == 'validate_cpu' else 'brain')
|
||||
before = budget_check(h, job, paths)
|
||||
h.save_json(paths['attempt'], dict(schema='conditioning-execution-attempt-v1', complete=False,
|
||||
job_sha256=expected_sha, pid=os.getpid(), started_utc=datetime.now(timezone.utc).isoformat(),
|
||||
no_automatic_retry=True))
|
||||
admission = None if kind == 'validate_cpu' else h._admit_brain()
|
||||
if kind == 'unchanged':
|
||||
module = h._load_source('_conditioning_execution_entry', C_PATH, C_SHA)
|
||||
bind_unchanged_authority(h, job, paths, pins)
|
||||
result = module.run_continued(paths['case'], paths['output'], paths['build'], paths['overlay_file'],
|
||||
paths['overlay_manifest'], paths['checkpoint'], mode=job['diagnostic_mode'])
|
||||
checked = module.load_checkpoint(paths['output'], result['checkpoint_manifest_sha256'])
|
||||
h.require(checked['summary'] == {k:v for k,v in result.items() if k!='checkpoint_manifest_sha256'},
|
||||
'Original C returned checkpoint differs')
|
||||
else:
|
||||
entry = {'updated': 'updated_continuation.py', 'oracle': 'boundary_oracle.py',
|
||||
'validate_cpu': 'validate_update_cpu.py', 'sample': 'boundary_sampler.py'}[kind]
|
||||
module = h._load_source('_conditioning_execution_entry', MODEL / entry, job['source_sha256'][entry])
|
||||
if kind == 'updated':
|
||||
result = module.run(paths['authority'], job['authority_sha256'], paths['output'], paths['build'],
|
||||
mode=job['diagnostic_mode'])
|
||||
elif kind == 'oracle':
|
||||
result = module.run(paths['authority'], job['authority_sha256'], job['source_sha256']['updated_continuation.py'],
|
||||
paths['case'], job['oracle_spec_sha256'], job['oracle_requests_sha256'], paths['output'], paths['build'])
|
||||
elif kind == 'validate_cpu':
|
||||
paths['output'].mkdir()
|
||||
result = module.validate(paths['authority'], job['authority_sha256'], paths['update'],
|
||||
job['chain_sha256'], paths['output'] / 'validation.json')
|
||||
elif kind == 'sample':
|
||||
result = module.run(paths['authority'], job['authority_sha256'], paths['output'])
|
||||
environment = h._environment('update' if kind == 'validate_cpu' else 'brain')
|
||||
if kind not in ('validate_cpu','sample'):
|
||||
h._verify_precision(environment, result['apl_component']['environment'])
|
||||
outputs = h.tree_hashes(paths['output'])
|
||||
h.verify_pins(pins)
|
||||
after = budget_check(h, job, paths)
|
||||
h.require(outputs == h.tree_hashes(paths['output']), 'Outputs changed during verification')
|
||||
receipt = dict(schema='conditioning-isolated-execution-receipt-v1', complete=True,
|
||||
job_id=job['job_id'], kind=kind, registration_sha256=job['registration_sha256'], job_sha256=expected_sha,
|
||||
worker_sha256=job['worker_sha256'], attempt_sha256=h.digest(paths['attempt']),
|
||||
input_sha256={str(p): sha for p, sha in pins.items()}, output_files_sha256=outputs,
|
||||
output_dir=str(paths['output']), result=result, environment=environment, admission=admission,
|
||||
resource_before=before, resource_after=after, wall_seconds=time.perf_counter()-started,
|
||||
wall_scope='entry through verification; parent separately measures spawn/exit/parent validation',
|
||||
process_exit_independently_observed=False, registration_authority_independently_proven=False,
|
||||
scientific_learning_pass_claimed=False, candidate_generated=False, old_source_globals_patched=False)
|
||||
h.save_json(paths['receipt'], receipt)
|
||||
return receipt
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--job', required=True)
|
||||
parser.add_argument('--job-sha256', required=True)
|
||||
args = parser.parse_args()
|
||||
receipt = execute(args.job, args.job_sha256)
|
||||
print(json.dumps(dict(complete=True, job_id=receipt['job_id'], kind=receipt['kind'])), flush=True)
|
||||
@@ -0,0 +1,562 @@
|
||||
"""Pure, pre-registration conditioning gates; never an execution authority.
|
||||
|
||||
The numeric rules come from PROTOCOL_DRAFT sections 6-8 and the fixed
|
||||
EVALUATION_POLICY_DRAFT. Two explicit pre-outcome operationalizations require
|
||||
the caller's policy descriptor: reversal/retention downstream means the exact
|
||||
nonMBONDownstream set, with legacyDownstream also reported; the old H mean
|
||||
predicate is evaluated twice per (mode, original cue), using each DAN branch's
|
||||
own complete control vectors, and both results must pass that separate audit.
|
||||
Neither choice is described as the original H data layout.
|
||||
|
||||
All evaluation functions are CPU/pure: descriptors and raw arrays are checked,
|
||||
but disk receipts, anatomical identities, seed derivation, actual execution,
|
||||
registration authority and full numerical/integrity audits remain EXTERNAL.
|
||||
A supplied SHA or Boolean is not proof of any of those facts. Consequently no
|
||||
return value claims scientific learning, execution approval or a candidate.
|
||||
The only file read is the pinned Python dependency at module import time.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
import types
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
METRICS_SHA256 = '47319e21db3c8b030b1bafbf0703cd86fb588d23bb29436accbacdba73d08c3c'
|
||||
_path = Path(__file__).resolve().parent.parent / 'olfactory-conditioning-lab-v1' / 'metrics.py'
|
||||
_source = _path.read_bytes()
|
||||
if hashlib.sha256(_source).hexdigest() != METRICS_SHA256:
|
||||
raise ValueError('Frozen metrics source SHA256 differs')
|
||||
M = types.ModuleType('conditioning_execution_frozen_metrics')
|
||||
M.__file__ = str(_path)
|
||||
exec(compile(_source, str(_path), 'exec'), M.__dict__)
|
||||
del _source
|
||||
|
||||
SCHEMA = 'conditioning-learning-gates-v1'
|
||||
REGISTRY_SCHEMA = 'conditioning-gate-registry-descriptor-v1'
|
||||
AUTHORITY_SCHEMA = 'conditioning-data-authority-descriptor-v1'
|
||||
PAIR_SCHEMA = 'conditioning-probe-pair-descriptor-v1'
|
||||
DOWNSTREAM_POLICY = 'nonMBONDownstream-pre-outcome-operationalization-v1'
|
||||
H_MAPPING = 'each-DAN-control-source-separately-both-pass-v1'
|
||||
ASSAYS = ('normal', 'delayed', 'reversal', 'retention')
|
||||
DAN_COMPARTMENTS = {'PAM15': "y5B'2a", 'PPL103': "y2a'1"}
|
||||
CARRY = ('v', 'g', 'ref', 'spike_ring', 'apl_state', 'apl_pending', 'absolute_tick', 'delta', 'relevant_rng_state')
|
||||
EXTERNAL = ('registration/source authority', 'anatomical membership', 'full seed derivation and alias inventory',
|
||||
'actual input/receipt files and completed trajectories', 'continuous state/queue/RNG restoration',
|
||||
'full finite/integrity/resource audits')
|
||||
|
||||
|
||||
def require(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def _keys(value, fields, label):
|
||||
require(isinstance(value, Mapping) and set(value) == set(fields), 'Wrong ' + label + ' fields')
|
||||
|
||||
|
||||
def _sha(value, label):
|
||||
require(M._sha(value), 'Invalid SHA256: ' + label)
|
||||
return value
|
||||
|
||||
|
||||
def _token(value, label):
|
||||
return M._token(value, label)
|
||||
|
||||
|
||||
def descriptor_sha256(value):
|
||||
"""Canonical descriptor hash; this does NOT establish external authority."""
|
||||
return hashlib.sha256(json.dumps(value, sort_keys=True, separators=(',', ':'),
|
||||
ensure_ascii=False, allow_nan=False).encode('utf-8')).hexdigest()
|
||||
|
||||
|
||||
def _scope():
|
||||
return dict(external_authority_verified=False, scientific_learning_pass_claimed=False,
|
||||
candidate_generated=False, execution_authorized=False, data_backed_claimed=False,
|
||||
external_requirements=list(EXTERNAL), frozen_metrics_source_sha256=METRICS_SHA256)
|
||||
|
||||
|
||||
def validate_registry(registry, *, expected_sha256):
|
||||
"""Check all 40 declared blocks and actual 63-bit seeds, never just labels.
|
||||
|
||||
training_sources lists independent training/design source streams, excluding
|
||||
counterfactual aliases. The external registrar must prove that this list is
|
||||
complete and agrees with the frozen full trial/seed inventory. Evaluation is
|
||||
one original A/B input pair per block, reused within that block across assays.
|
||||
"""
|
||||
_keys(registry, ('schema', 'protocol_sha256', 'population_binding_sha256',
|
||||
'nodes_raw_sha256', 'population_membership_sha256', 'blocks'), 'registry')
|
||||
require(registry['schema'] == REGISTRY_SCHEMA, 'Wrong registry schema')
|
||||
require(descriptor_sha256(registry) == _sha(expected_sha256, 'external registry'), 'Registry descriptor changed')
|
||||
for field in ('protocol_sha256', 'population_binding_sha256', 'nodes_raw_sha256', 'population_membership_sha256'):
|
||||
_sha(registry[field], field)
|
||||
require(isinstance(registry['blocks'], Mapping) and len(registry['blocks']) == 40, 'Exactly 40 registered blocks required')
|
||||
identities, streams, seeds = set(), set(), set()
|
||||
for block_id, block in registry['blocks'].items():
|
||||
_token(block_id, 'block_id')
|
||||
_keys(block, ('mode', 'dan_type', 'compartment_verbatim', 'conditioned_cue', 'replicate',
|
||||
'training_sources', 'evaluation_sources', 'evaluation_input_sha256'), 'block')
|
||||
require(block['mode'] in M.MODES and block['dan_type'] in DAN_COMPARTMENTS and
|
||||
block['compartment_verbatim'] == DAN_COMPARTMENTS[block['dan_type']] and
|
||||
block['conditioned_cue'] in M.CUES and type(block['replicate']) is int and 1 <= block['replicate'] <= 5,
|
||||
'Unknown cell/compartment/replicate')
|
||||
identity = (block['mode'], block['dan_type'], block['conditioned_cue'], block['replicate'])
|
||||
require(identity not in identities, 'Duplicate cell/replicate')
|
||||
identities.add(identity)
|
||||
require(type(block['training_sources']) is list and block['training_sources'], 'Missing independent training/design sources')
|
||||
_keys(block['evaluation_sources'], M.CUES, 'evaluation sources')
|
||||
_keys(block['evaluation_input_sha256'], M.CUES, 'evaluation input hashes')
|
||||
for cue in M.CUES:
|
||||
_sha(block['evaluation_input_sha256'][cue], 'evaluation input')
|
||||
entries = [(x, ('training', 'design')) for x in block['training_sources']]
|
||||
entries += [(block['evaluation_sources'][cue], ('evaluation',)) for cue in M.CUES]
|
||||
for source, allowed in entries:
|
||||
_keys(source, ('stream_id', 'seed', 'split'), 'independent source')
|
||||
_token(source['stream_id'], 'stream_id')
|
||||
require(source['split'] in allowed and type(source['seed']) is int and 0 <= source['seed'] < 2**63,
|
||||
'Wrong source split or full63bit seed')
|
||||
require(source['stream_id'] not in streams and source['seed'] not in seeds,
|
||||
'Independent source ID/seed collision, including training/evaluation overlap')
|
||||
streams.add(source['stream_id']); seeds.add(source['seed'])
|
||||
require(len(identities) == 40, 'Incomplete eight-cell/five-replicate inventory')
|
||||
return dict(schema=SCHEMA, registry_sha256=expected_sha256, blocks=40,
|
||||
independent_declared_streams=len(streams), **_scope())
|
||||
|
||||
|
||||
def _context(registry, authority, nodes=None, populations=None):
|
||||
_keys(authority, ('schema', 'registry_sha256', 'verification_receipt_sha256',
|
||||
'execution_inventory_sha256', 'population_binding_sha256'), 'external data authority descriptor')
|
||||
require(authority['schema'] == AUTHORITY_SCHEMA, 'Wrong data authority schema')
|
||||
for field in ('registry_sha256', 'verification_receipt_sha256', 'execution_inventory_sha256', 'population_binding_sha256'):
|
||||
_sha(authority[field], field)
|
||||
validate_registry(registry, expected_sha256=authority['registry_sha256'])
|
||||
require(authority['population_binding_sha256'] == registry['population_binding_sha256'], 'Population authority binding differs')
|
||||
if nodes is not None:
|
||||
membership = M.validate_populations(nodes, populations)
|
||||
require(M._hash(nodes) == registry['nodes_raw_sha256'] and
|
||||
membership['membership_sha256'] == registry['population_membership_sha256'], 'Raw population binding differs')
|
||||
|
||||
|
||||
def _cell_rows(rows, registry, mode, dan_type, conditioned_cue):
|
||||
require(mode in M.MODES and dan_type in DAN_COMPARTMENTS and conditioned_cue in M.CUES, 'Unknown cell')
|
||||
require(type(rows) is list and len(rows) == 5, 'Exactly five independent training rows required')
|
||||
expected = {key for key, value in registry['blocks'].items()
|
||||
if (value['mode'], value['dan_type'], value['conditioned_cue']) == (mode, dan_type, conditioned_cue)}
|
||||
require(len(expected) == 5 and {row['replicate_id'] for row in rows} == expected, 'Missing/duplicate/wrong-cell training rows')
|
||||
for row in rows:
|
||||
block = registry['blocks'][row['replicate_id']]
|
||||
require(row['replicate_unit'] == 'independent_training', 'Evaluation draws are not training replicates')
|
||||
require(row['training_stream_ids'] == [x['stream_id'] for x in block['training_sources']], 'Training source lineage differs')
|
||||
require(row['evaluation_stream_ids'] == [block['evaluation_sources'][cue]['stream_id'] for cue in M.CUES],
|
||||
'Both registered evaluation inputs required; no extra evaluation replication')
|
||||
return expected
|
||||
|
||||
|
||||
def _pair(pair, block_id, registry, nodes, populations, used, *, policy, delta=None, checkpoint=None):
|
||||
fields = ('schema', 'block_id', 'snapshot_id', 'receipt_sha256', 'probe_receipt_sha256',
|
||||
'evaluation_input_sha256', 'state_raw_sha256', 'states', 'state_policy', 'source_checkpoint_sha256',
|
||||
'delta_sha256', 'probe_steps', 'cs_start_tick', 'cs_stop_tick_exclusive', 'US_requested',
|
||||
'weight_updates_enabled', 'feedback_to_training_or_idle')
|
||||
_keys(pair, fields, 'probe pair')
|
||||
require(pair['schema'] == PAIR_SCHEMA and pair['block_id'] == block_id and pair['state_policy'] == policy,
|
||||
'Probe identity/state policy differs')
|
||||
_token(pair['snapshot_id'], 'snapshot_id')
|
||||
for field in ('receipt_sha256', 'source_checkpoint_sha256', 'delta_sha256'):
|
||||
_sha(pair[field], field)
|
||||
require(type(pair['probe_steps']) is int and pair['probe_steps'] == 1200 and
|
||||
type(pair['cs_start_tick']) is int and pair['cs_start_tick'] == 0 and
|
||||
type(pair['cs_stop_tick_exclusive']) is int and pair['cs_stop_tick_exclusive'] == 1000 and
|
||||
pair['US_requested'] is False and pair['weight_updates_enabled'] is False and
|
||||
pair['feedback_to_training_or_idle'] is False, 'Probe timing/US/update/feedback differs')
|
||||
require(delta is None or pair['delta_sha256'] == delta, 'Probe delta source differs')
|
||||
require(checkpoint is None or pair['source_checkpoint_sha256'] == checkpoint, 'Probe checkpoint source differs')
|
||||
for field in ('probe_receipt_sha256', 'evaluation_input_sha256', 'state_raw_sha256', 'states'):
|
||||
_keys(pair[field], M.CUES, field)
|
||||
require(pair['evaluation_input_sha256'] == registry['blocks'][block_id]['evaluation_input_sha256'],
|
||||
'Probe must use the exact registered evaluation inputs')
|
||||
for cue in M.CUES:
|
||||
_sha(pair['probe_receipt_sha256'][cue], 'probe receipt')
|
||||
checked = M.validate_state(pair['states'][cue], nodes=nodes, steps=1200)
|
||||
require(pair['state_raw_sha256'][cue] == checked['hashes'], 'Probe raw arrays differ from descriptor hashes')
|
||||
# Re-referencing one baseline is permitted, but a new snapshot cannot claim
|
||||
# that it executed a probe by reusing another snapshot's receipt.
|
||||
fingerprint = descriptor_sha256({key: value for key, value in pair.items() if key != 'states'})
|
||||
identity = pair['snapshot_id']
|
||||
require(identity not in used['snapshots'] or used['snapshots'][identity] == fingerprint, 'Snapshot identity reused with changed data')
|
||||
for receipt in (pair['receipt_sha256'], *pair['probe_receipt_sha256'].values()):
|
||||
require(receipt not in used['receipts'] or used['receipts'][receipt] == identity, 'Probe execution receipt reused across snapshots')
|
||||
used['receipts'][receipt] = identity
|
||||
require(len({pair['receipt_sha256'], *pair['probe_receipt_sha256'].values()}) == 3, 'A/B probes require distinct actual receipts')
|
||||
used['snapshots'][identity] = fingerprint
|
||||
return pair['states']
|
||||
|
||||
|
||||
def _arm_execution(value, *, assay, arm, used):
|
||||
_keys(value, ('receipt_sha256', 'recording_verified', 'complete', 'completed_epochs',
|
||||
'reinforcement_opportunities', 'terminal_pairings', 'epoch_duration_ms', 'cs_duration_ms', 'us_tick',
|
||||
'initial_delta_sha256', 'terminal_delta_sha256', 'terminal_checkpoint_sha256',
|
||||
'neural_state_policy', 'weight_rule', 'reinforced_cue'), 'training execution descriptor')
|
||||
for key in ('receipt_sha256', 'initial_delta_sha256', 'terminal_delta_sha256', 'terminal_checkpoint_sha256'):
|
||||
_sha(value[key], key)
|
||||
require(value['receipt_sha256'] not in used, 'Training receipt reused across arms/replicates')
|
||||
used.add(value['receipt_sha256'])
|
||||
require(value['complete'] is True and value['recording_verified'] is True,
|
||||
'Caller must supply a completed, externally verified execution descriptor')
|
||||
for field, expected in (('completed_epochs', 150 if arm == 'unpaired' else 100),
|
||||
('reinforcement_opportunities', 0 if arm == 'CS-only' else 50), ('terminal_pairings', 50),
|
||||
('us_tick', 1500 if assay == 'delayed' else 900)):
|
||||
require(type(value[field]) is int and value[field] == expected, 'Wrong terminal inventory: ' + field)
|
||||
require(value['epoch_duration_ms'] == (180. if assay == 'delayed' else 120.) and value['cs_duration_ms'] == 100. and
|
||||
value['neural_state_policy'] == 'fresh_epoch_delta_only' and value['weight_rule'] == 'frozen_temporal_eligibility_v2',
|
||||
'Frozen training timing/state/update policy differs')
|
||||
|
||||
|
||||
def _report(assay, rows, registry, authority, mode, dan_type, conditioned_cue):
|
||||
rows = sorted(rows, key=lambda row: row['replicate_id'])
|
||||
count = sum(row['conjunction_pass'] for row in rows)
|
||||
return dict(schema=SCHEMA, status='CONDITIONAL-PREDICATES-PASS' if count >= 3 else 'CONDITIONAL-PREDICATES-FAIL',
|
||||
assay=assay, mode=mode, dan_type=dan_type, conditioned_cue=conditioned_cue,
|
||||
predicate_pass=count >= 3, successful_same_replicate_conjunctions=count, required_majority=3,
|
||||
training_replicates=5, replicates=rows, registry_sha256=authority['registry_sha256'],
|
||||
external_data_authority_descriptor_sha256=descriptor_sha256(authority),
|
||||
downstream_policy=DOWNSTREAM_POLICY, policy_scope='pre-outcome additional operationalization', **_scope())
|
||||
|
||||
|
||||
def evaluate_acquisition(replicates, *, assay, mode, dan_type, conditioned_cue, registry, authority):
|
||||
"""Reuse the pinned normal/delayed gate, preserving every six-control rule.
|
||||
|
||||
replicates has the original frozen metrics schema. recording_verified is the
|
||||
external caller's descriptor assertion, NOT a verification done by this call.
|
||||
"""
|
||||
_context(registry, authority)
|
||||
_cell_rows(replicates, registry, mode, dan_type, conditioned_cue)
|
||||
registered = {row['replicate_id']: row['training_stream_ids'] for row in replicates}
|
||||
for row in replicates:
|
||||
for arm in row['arms'].values():
|
||||
for cue in M.CUES:
|
||||
summary = arm['metrics']['cues'][cue]
|
||||
require(summary['nodes_raw_sha256'] == registry['nodes_raw_sha256'] and
|
||||
summary['membership']['membership_sha256'] == registry['population_membership_sha256'], 'Population metric binding differs')
|
||||
frozen = M.evaluate_acquisition(replicates, assay=assay, mode=mode, dan_type=dan_type,
|
||||
conditioned_cue=conditioned_cue, registered_training_streams=registered)
|
||||
result = _report(assay, frozen['replicates'], registry, authority, mode, dan_type, conditioned_cue)
|
||||
result.update(frozen_acquisition_result=frozen, acquisition_controls=list(M.CONTROLS),
|
||||
downstream_policy='unchanged acquisition requires both legacyDownstream and nonMBONDownstream positive gains',
|
||||
acquisition_metric_inputs=json.loads(json.dumps(replicates, allow_nan=False)),
|
||||
legacy_control_MBON_gains={name: {row['replicate_id']: row['arms'][name]['metrics']['separation']['MBON']['gain']
|
||||
for row in replicates} for name in ('D=0', 'random reward', 'frozen')})
|
||||
return result
|
||||
|
||||
|
||||
def evaluate_reversal(replicates, *, mode, dan_type, conditioned_cue, registry, authority,
|
||||
nodes, populations, downstream_policy):
|
||||
"""Original pre/orientation, strict nonzero sign crossing, fixed 50 count."""
|
||||
require(downstream_policy == DOWNSTREAM_POLICY, 'Explicit preregistered downstream operationalization required')
|
||||
_context(registry, authority, nodes, populations)
|
||||
_cell_rows(replicates, registry, mode, dan_type, conditioned_cue)
|
||||
reports, execution_used = [], set()
|
||||
used = dict(snapshots={}, receipts={})
|
||||
neutral = next(cue for cue in M.CUES if cue != conditioned_cue)
|
||||
for row in replicates:
|
||||
_keys(row, ('replicate_id', 'replicate_unit', 'training_stream_ids', 'evaluation_stream_ids',
|
||||
'pre', 'acquisition', 'reversal', 'no_reversal', 'execution'), 'reversal row')
|
||||
block_id = row['replicate_id']
|
||||
_keys(row['execution'], ('acquisition', 'reversal', 'no_reversal'), 'reversal executions')
|
||||
for arm, execution in row['execution'].items():
|
||||
_arm_execution(execution, assay='normal', arm=arm, used=execution_used)
|
||||
require(execution['reinforced_cue'] == (neutral if arm == 'reversal' else conditioned_cue), 'Reversal cue assignment differs')
|
||||
acq = row['execution']['acquisition']
|
||||
for arm in ('reversal', 'no_reversal'):
|
||||
require(row['execution'][arm]['initial_delta_sha256'] == acq['terminal_delta_sha256'], 'Reversal must fork exact acquisition delta')
|
||||
pre = _pair(row['pre'], block_id, registry, nodes, populations, used, policy='common_frozen_reset', delta=acq['initial_delta_sha256'])
|
||||
metrics, states = {}, {}
|
||||
for arm in ('acquisition', 'reversal', 'no_reversal'):
|
||||
execution = row['execution'][arm]
|
||||
states[arm] = _pair(row[arm], block_id, registry, nodes, populations, used, policy='common_frozen_reset',
|
||||
delta=execution['terminal_delta_sha256'], checkpoint=execution['terminal_checkpoint_sha256'])
|
||||
metrics[arm] = M.arm_metrics(pre, states[arm], conditioned_cue=conditioned_cue, nodes=nodes, populations=populations)
|
||||
changes = {cue: M.functional_summary(states['acquisition'][cue], states['reversal'][cue],
|
||||
nodes=nodes, populations=populations, steps=1200) for cue in M.CUES}
|
||||
s = {arm: metric['rawS'] for arm, metric in metrics.items()}
|
||||
expected = (s['acquisition'] > 0 and s['no_reversal'] > 0 and s['reversal'] < 0) if dan_type == 'PAM15' else (
|
||||
s['acquisition'] < 0 and s['no_reversal'] < 0 and s['reversal'] > 0)
|
||||
mbon, down = (changes[neutral]['populations'][name] for name in ('MBON', 'nonMBONDownstream'))
|
||||
predicates = dict(strict_three_signed_relations=bool(expected),
|
||||
former_neutral_MBON_count_or_defined_first_latency=bool(mbon['spike_count_l1'] > 0 or mbon['defined_first_latency_changed']),
|
||||
former_neutral_nonMBONDownstream_event_or_count=bool(down['events_changed'] or down['spike_count_l1'] > 0))
|
||||
reports.append(dict(replicate_id=block_id, rawS=s, predicates=predicates, conjunction_pass=all(predicates.values()),
|
||||
metrics=metrics, acquisition_to_reversal_changes_by_cue=changes,
|
||||
legacy_style_sign_inequality_on_registered_S=bool(np.sign(s['acquisition']) != np.sign(s['reversal'])),
|
||||
exact_historical_H_readout_equivalence_claimed=False))
|
||||
return _report('reversal', reports, registry, authority, mode, dan_type, conditioned_cue)
|
||||
|
||||
|
||||
def _idle(branch, used, *, arm, conditioned_cue):
|
||||
_keys(branch, ('source_checkpoint_sha256', 'delta_sha256', 'idle_lineage_id', 'idle_receipt_sha256',
|
||||
'total_idle_ticks', 'no_input', 'updates_disabled', 'reset_state', 'analytic_time_advance',
|
||||
'one_second_is_prefix_of_ten_second', 'checkpoints', 'source_execution'), 'idle branch')
|
||||
_arm_execution(branch['source_execution'], assay='normal', arm=arm, used=used)
|
||||
source = branch['source_execution']
|
||||
require(source['terminal_checkpoint_sha256'] == branch['source_checkpoint_sha256'] and
|
||||
source['terminal_delta_sha256'] == branch['delta_sha256'] and source['reinforced_cue'] == conditioned_cue,
|
||||
'Idle source must bind the complete terminal normal paired/frozen execution')
|
||||
require(arm != 'frozen' or source['initial_delta_sha256'] == source['terminal_delta_sha256'],
|
||||
'Frozen training cannot change delta')
|
||||
for field in ('source_checkpoint_sha256', 'delta_sha256', 'idle_receipt_sha256'):
|
||||
_sha(branch[field], field)
|
||||
_token(branch['idle_lineage_id'], 'idle lineage')
|
||||
require(branch['idle_receipt_sha256'] not in used and branch['idle_lineage_id'] not in used, 'Idle branch/receipt reused')
|
||||
used.update((branch['idle_receipt_sha256'], branch['idle_lineage_id']))
|
||||
require(type(branch['total_idle_ticks']) is int and branch['total_idle_ticks'] == 100000 and
|
||||
branch['no_input'] is True and branch['updates_disabled'] is True and branch['reset_state'] is False and
|
||||
branch['analytic_time_advance'] is False and branch['one_second_is_prefix_of_ten_second'] is True,
|
||||
'Retention must be actual continuous 10-second idle with a 1-second prefix')
|
||||
_keys(branch['checkpoints'], ('0', '1', '10'), 'idle checkpoints')
|
||||
previous, start = None, None
|
||||
for second in (0, 1, 10):
|
||||
checkpoint = branch['checkpoints'][str(second)]
|
||||
_keys(checkpoint, ('checkpoint_sha256', 'parent_checkpoint_sha256', 'elapsed_ticks',
|
||||
'absolute_tick', 'delta_sha256', 'carry_sha256'), 'idle checkpoint')
|
||||
for field in ('checkpoint_sha256', 'parent_checkpoint_sha256', 'delta_sha256'):
|
||||
_sha(checkpoint[field], field)
|
||||
require(type(checkpoint['elapsed_ticks']) is int and checkpoint['elapsed_ticks'] == second * 10000 and
|
||||
type(checkpoint['absolute_tick']) is int and checkpoint['absolute_tick'] >= 0,
|
||||
'Retention clock differs')
|
||||
start = checkpoint['absolute_tick'] if second == 0 else start
|
||||
require(checkpoint['absolute_tick'] == start + second * 10000 and checkpoint['delta_sha256'] == branch['delta_sha256'],
|
||||
'Absolute clock or idle delta changed')
|
||||
require(checkpoint['parent_checkpoint_sha256'] == (branch['source_checkpoint_sha256'] if previous is None else previous),
|
||||
'Idle checkpoint chain does not preserve the same 1-to-10-second trajectory')
|
||||
_keys(checkpoint['carry_sha256'], CARRY, 'complete carried-state hashes')
|
||||
for field, value in checkpoint['carry_sha256'].items():
|
||||
_sha(value, field)
|
||||
previous = checkpoint['checkpoint_sha256']
|
||||
|
||||
|
||||
def evaluate_retention(replicates, *, mode, dan_type, conditioned_cue, registry, authority,
|
||||
nodes, populations, downstream_policy):
|
||||
"""One conjunction per training replicate at BOTH 1 and 10 real seconds."""
|
||||
require(downstream_policy == DOWNSTREAM_POLICY, 'Explicit preregistered downstream operationalization required')
|
||||
_context(registry, authority, nodes, populations)
|
||||
_cell_rows(replicates, registry, mode, dan_type, conditioned_cue)
|
||||
reports, idle_used = [], set()
|
||||
used = dict(snapshots={}, receipts={})
|
||||
for row in replicates:
|
||||
_keys(row, ('replicate_id', 'replicate_unit', 'training_stream_ids', 'evaluation_stream_ids',
|
||||
'pre', 'checkpoints', 'execution'), 'retention row')
|
||||
_keys(row['pre'], ('trained', 'frozen'), 'retention pre')
|
||||
_keys(row['execution'], ('trained', 'frozen'), 'retention branches')
|
||||
_keys(row['checkpoints'], ('0', '1', '10'), 'retention time inventory')
|
||||
block_id = row['replicate_id']
|
||||
pre = {}
|
||||
for branch in ('trained', 'frozen'):
|
||||
execution = row['execution'][branch]
|
||||
_idle(execution, idle_used, arm='paired' if branch == 'trained' else 'frozen', conditioned_cue=conditioned_cue)
|
||||
pre[branch] = _pair(row['pre'][branch], block_id, registry, nodes, populations, used, policy='common_frozen_reset',
|
||||
delta=execution['source_execution']['initial_delta_sha256'])
|
||||
times, complete = {}, []
|
||||
for second in (0, 1, 10):
|
||||
pairs = row['checkpoints'][str(second)]
|
||||
_keys(pairs, ('trained', 'frozen'), 'time-matched trained/frozen probes')
|
||||
states, metrics = {}, {}
|
||||
for branch in ('trained', 'frozen'):
|
||||
execution = row['execution'][branch]
|
||||
checkpoint = execution['checkpoints'][str(second)]
|
||||
states[branch] = _pair(pairs[branch], block_id, registry, nodes, populations, used,
|
||||
policy='continuous_checkpoint', delta=execution['delta_sha256'], checkpoint=checkpoint['checkpoint_sha256'])
|
||||
metrics[branch] = M.arm_metrics(pre[branch], states[branch], conditioned_cue=conditioned_cue, nodes=nodes, populations=populations)
|
||||
differences = {cue: M.functional_summary(states['frozen'][cue], states['trained'][cue],
|
||||
nodes=nodes, populations=populations, steps=1200) for cue in M.CUES}
|
||||
trained, frozen = (metrics[branch]['rawS'] for branch in ('trained', 'frozen'))
|
||||
mbon, down = (differences[conditioned_cue]['populations'][name] for name in ('MBON', 'nonMBONDownstream'))
|
||||
predicates = dict(raw_signed_direction=bool(trained > 0 if dan_type == 'PAM15' else trained < 0),
|
||||
beyond_time_matched_frozen=bool(trained > frozen if dan_type == 'PAM15' else trained < frozen),
|
||||
conditioned_MBON_count_or_defined_first_latency=bool(mbon['spike_count_l1'] > 0 or mbon['defined_first_latency_changed']),
|
||||
conditioned_nonMBONDownstream_event_or_count=bool(down['events_changed'] or down['spike_count_l1'] > 0))
|
||||
times[str(second)] = dict(rawS_trained=trained, rawS_frozen=frozen, rawS_trained_minus_frozen=trained - frozen,
|
||||
metrics=metrics, frozen_to_trained_differences_by_cue=differences, predicates=predicates,
|
||||
contributes_to_gate=second in (1, 10), conjunction_pass=all(predicates.values()))
|
||||
if second in (1, 10):
|
||||
complete.append(all(predicates.values()))
|
||||
reports.append(dict(replicate_id=block_id, times=times, conjunction_pass=all(complete),
|
||||
legacy_style_last_MBON_separation_exceeds_pre=bool(times['10']['metrics']['trained']['separation']['MBON']['gain'] > 0),
|
||||
legacy_reset_retention_equivalence_claimed=False))
|
||||
return _report('retention', reports, registry, authority, mode, dan_type, conditioned_cue)
|
||||
|
||||
|
||||
def _checked_difference(summary, before, after, cue):
|
||||
"""Rebind reported differences to raw vectors in their two source metrics.
|
||||
|
||||
The event-change bit comes from raw-event comparison in evaluate_*; a summary
|
||||
does not contain the event files. It remains externally bound evidence, never
|
||||
an independent disk/event verification performed by this cohort function.
|
||||
"""
|
||||
left, right = before['cues'][cue], after['cues'][cue]
|
||||
require(summary['membership'] == left['membership'] == right['membership'] and
|
||||
summary['nodes_raw_sha256'] == left['nodes_raw_sha256'] == right['nodes_raw_sha256'] and
|
||||
summary['pre_state_raw_sha256'] == left['post_state_raw_sha256'] and
|
||||
summary['post_state_raw_sha256'] == right['post_state_raw_sha256'], 'Difference source binding changed')
|
||||
for name in M.POPULATIONS:
|
||||
value, a, b = summary['populations'][name], left['populations'][name], right['populations'][name]
|
||||
for field in ('counts', 'first_latency_ms_per_neuron', 'final_v', 'final_g', 'final_ref'):
|
||||
require(value['pre_' + field] == a['post_' + field] and value['post_' + field] == b['post_' + field],
|
||||
'Difference population vectors changed')
|
||||
count = sum(abs(x - y) for x, y in zip(value['pre_counts'], value['post_counts']))
|
||||
first = []
|
||||
for phase in ('pre', 'post'):
|
||||
defined = [x for x in value[phase + '_first_latency_ms_per_neuron'] if x is not None]
|
||||
first.append(min(defined) if defined else None)
|
||||
changed = first[0] is not None and first[1] is not None and first[0] != first[1]
|
||||
require(type(value['spike_count_l1']) is int and value['spike_count_l1'] == count and
|
||||
value['defined_first_latency_changed'] is changed and type(value['events_changed']) is bool,
|
||||
'Difference predicate contradicts its raw count/defined-latency vectors')
|
||||
require(count == 0 or value['events_changed'], 'Changed counts require changed events')
|
||||
same_events = all(summary['pre_state_raw_sha256'][key] == summary['post_state_raw_sha256'][key]
|
||||
for key in ('step', 'neuron_idx'))
|
||||
require(not same_events or not value['events_changed'], 'Identical complete event arrays cannot change population events')
|
||||
return summary['populations']
|
||||
|
||||
|
||||
def _validate_followup_report(row, assay, dan, cue):
|
||||
neutral = next(x for x in M.CUES if x != cue)
|
||||
if assay == 'reversal':
|
||||
_keys(row['metrics'], ('acquisition', 'reversal', 'no_reversal'), 'reversal report metrics')
|
||||
metrics = {name: M._bound_metric(value, cue) for name, value in row['metrics'].items()}
|
||||
for odor in M.CUES:
|
||||
require(len({tuple(sorted(metric['cues'][odor]['pre_state_raw_sha256'].items())) for metric in metrics.values()}) == 1,
|
||||
'Reversal reports changed original pre baseline')
|
||||
s = {name: value['rawS'] for name, value in metrics.items()}
|
||||
require(row['rawS'] == s, 'Reversal raw signed result differs from source metrics')
|
||||
_keys(row['acquisition_to_reversal_changes_by_cue'], M.CUES, 'reversal cue changes')
|
||||
groups = {odor: _checked_difference(row['acquisition_to_reversal_changes_by_cue'][odor],
|
||||
metrics['acquisition'], metrics['reversal'], odor) for odor in M.CUES}
|
||||
mbon, down = (groups[neutral][name] for name in ('MBON', 'nonMBONDownstream'))
|
||||
signed = (s['acquisition'] > 0 and s['no_reversal'] > 0 and s['reversal'] < 0) if dan == 'PAM15' else (
|
||||
s['acquisition'] < 0 and s['no_reversal'] < 0 and s['reversal'] > 0)
|
||||
predicates = dict(strict_three_signed_relations=bool(signed),
|
||||
former_neutral_MBON_count_or_defined_first_latency=bool(mbon['spike_count_l1'] > 0 or mbon['defined_first_latency_changed']),
|
||||
former_neutral_nonMBONDownstream_event_or_count=bool(down['events_changed'] or down['spike_count_l1'] > 0))
|
||||
require(row['predicates'] == predicates and all(type(x) is bool for x in row['predicates'].values()),
|
||||
'Reversal predicates differ from source metrics')
|
||||
return all(predicates.values())
|
||||
_keys(row['times'], ('0', '1', '10'), 'retention report times')
|
||||
baselines, conjunctions = {}, []
|
||||
for second in ('0', '1', '10'):
|
||||
value = row['times'][second]
|
||||
_keys(value['metrics'], ('trained', 'frozen'), 'retention report metrics')
|
||||
metrics = {name: M._bound_metric(metric, cue) for name, metric in value['metrics'].items()}
|
||||
for branch, metric in metrics.items():
|
||||
baseline = {odor: metric['cues'][odor]['pre_state_raw_sha256'] for odor in M.CUES}
|
||||
require(branch not in baselines or baselines[branch] == baseline, 'Retention changed original pre baseline across time')
|
||||
baselines[branch] = baseline
|
||||
trained, frozen = (metrics[branch]['rawS'] for branch in ('trained', 'frozen'))
|
||||
require(value['rawS_trained'] == trained and value['rawS_frozen'] == frozen and
|
||||
value['rawS_trained_minus_frozen'] == trained - frozen, 'Retention signed contrast differs from source metrics')
|
||||
_keys(value['frozen_to_trained_differences_by_cue'], M.CUES, 'retention cue differences')
|
||||
groups = {odor: _checked_difference(value['frozen_to_trained_differences_by_cue'][odor],
|
||||
metrics['frozen'], metrics['trained'], odor) for odor in M.CUES}
|
||||
mbon, down = (groups[cue][name] for name in ('MBON', 'nonMBONDownstream'))
|
||||
predicates = dict(raw_signed_direction=bool(trained > 0 if dan == 'PAM15' else trained < 0),
|
||||
beyond_time_matched_frozen=bool(trained > frozen if dan == 'PAM15' else trained < frozen),
|
||||
conditioned_MBON_count_or_defined_first_latency=bool(mbon['spike_count_l1'] > 0 or mbon['defined_first_latency_changed']),
|
||||
conditioned_nonMBONDownstream_event_or_count=bool(down['events_changed'] or down['spike_count_l1'] > 0))
|
||||
require(value['predicates'] == predicates and all(type(x) is bool for x in value['predicates'].values()) and
|
||||
value['conjunction_pass'] is all(predicates.values()) and value['contributes_to_gate'] is (second != '0'),
|
||||
'Retention predicates differ from source metrics')
|
||||
if second != '0':
|
||||
conjunctions.append(all(predicates.values()))
|
||||
return all(conjunctions)
|
||||
|
||||
|
||||
def summarize_cohort(reports, *, registry, authority, required_assays):
|
||||
"""Exact eight-cell inventory; each assay keeps its own same-replicate 3/5.
|
||||
|
||||
Use ('normal',) for the staged acquisition decision or ASSAYS for the full
|
||||
functional table. The function does not silently intersect successful seeds
|
||||
across assays, pool cells, or incorporate legacy H/integrity gates. Those are
|
||||
separately registered coordinator decisions. Missing assays remain NOT-RUN.
|
||||
"""
|
||||
_context(registry, authority)
|
||||
require(tuple(required_assays) in (('normal',), ASSAYS), 'Only staged normal or full fixed assay scope supported')
|
||||
expected = {(m, d, c, a) for m in M.MODES for d in M.DAN_TYPES for c in M.CUES for a in required_assays}
|
||||
actual, table = set(), []
|
||||
for report in reports:
|
||||
require(report.get('schema') == SCHEMA and report.get('registry_sha256') == authority['registry_sha256'] and
|
||||
report.get('external_data_authority_descriptor_sha256') == descriptor_sha256(authority), 'Report authority binding differs')
|
||||
identity = (report['mode'], report['dan_type'], report['conditioned_cue'], report['assay'])
|
||||
require(identity in expected and identity not in actual, 'Duplicate/unexpected cohort cell/assay')
|
||||
expected_ids = {key for key, value in registry['blocks'].items()
|
||||
if (value['mode'], value['dan_type'], value['conditioned_cue']) == identity[:3]}
|
||||
rows = report['replicates']
|
||||
require(len(rows) == 5 and {row['replicate_id'] for row in rows} == expected_ids and
|
||||
all(type(row['conjunction_pass']) is bool for row in rows), 'Cohort replicate coverage differs')
|
||||
if report['assay'] in ('normal', 'delayed'):
|
||||
inputs = report.get('acquisition_metric_inputs')
|
||||
require(isinstance(inputs, list), 'Missing original normal/delayed metric inputs')
|
||||
rebuilt = evaluate_acquisition(inputs, assay=identity[3], mode=identity[0], dan_type=identity[1],
|
||||
conditioned_cue=identity[2], registry=registry, authority=authority)
|
||||
require(rebuilt == report,
|
||||
'Normal/delayed report differs from frozen gate reconstruction')
|
||||
else:
|
||||
for row in rows:
|
||||
require(report['downstream_policy'] == DOWNSTREAM_POLICY, 'Follow-up downstream policy changed')
|
||||
conjunction = _validate_followup_report(row, report['assay'], report['dan_type'], report['conditioned_cue'])
|
||||
require(row['conjunction_pass'] is conjunction, 'Replicate conjunction differs from its predicates')
|
||||
count = sum(row['conjunction_pass'] for row in rows)
|
||||
require(report['successful_same_replicate_conjunctions'] == count and report['predicate_pass'] is (count >= 3),
|
||||
'Cohort summary disagrees with replicate conjunctions')
|
||||
require(all(report.get(key) is False for key in ('external_authority_verified', 'scientific_learning_pass_claimed',
|
||||
'candidate_generated', 'execution_authorized', 'data_backed_claimed')), 'Conditional report contains an unsupported authority claim')
|
||||
actual.add(identity)
|
||||
table.append(dict(mode=identity[0], dan_type=identity[1], conditioned_cue=identity[2], assay=identity[3],
|
||||
status='CONDITIONAL-PASS' if count >= 3 else 'CONDITIONAL-FAIL', successful_replicates=count))
|
||||
for identity in sorted(expected - actual):
|
||||
table.append(dict(mode=identity[0], dan_type=identity[1], conditioned_cue=identity[2], assay=identity[3], status='NOT-RUN', successful_replicates=None))
|
||||
complete = actual == expected
|
||||
return dict(schema=SCHEMA, status='COMPLETE' if complete else 'NOT-RUN', required_assays=list(required_assays),
|
||||
complete_inventory=complete, all_functional_predicates_pass=(all(row['status'] == 'CONDITIONAL-PASS' for row in table) if complete else None),
|
||||
table=sorted(table, key=lambda row: (row['mode'], row['dan_type'], row['conditioned_cue'], row['assay'])),
|
||||
legacy_H_and_integrity_gates_included=False, **_scope())
|
||||
|
||||
|
||||
def legacy_h_cohort_audit(normal_reports, *, registry, authority, declared_mapping):
|
||||
"""Four groups, two frozen H calls each; no branch/control pooling.
|
||||
|
||||
Both stricter control-source mapping and both_pass aggregate are new explicit
|
||||
pre-outcome operationalizations, NOT a reproduced complete original H gate.
|
||||
"""
|
||||
if declared_mapping is None:
|
||||
return dict(schema=SCHEMA, status='NOT-TESTABLE', both_pass=None,
|
||||
reason='Missing explicit pre-outcome control-source mapping', **_scope())
|
||||
require(declared_mapping == H_MAPPING, 'Unknown declared H control-source mapping')
|
||||
inventory = summarize_cohort(normal_reports, registry=registry, authority=authority, required_assays=('normal',))
|
||||
if not inventory['complete_inventory']:
|
||||
return dict(schema=SCHEMA, status='NOT-RUN', both_pass=None, reason='Complete eight normal cells required', **_scope())
|
||||
lookup = {(r['mode'], r['dan_type'], r['conditioned_cue']): r for r in normal_reports}
|
||||
groups = []
|
||||
for mode in M.MODES:
|
||||
for cue in M.CUES:
|
||||
reports = {dan: lookup[(mode, dan, cue)] for dan in M.DAN_TYPES}
|
||||
outcomes = {}
|
||||
for source in M.DAN_TYPES:
|
||||
# The normal report must retain all raw arm metrics; gains are
|
||||
# taken from their validated source payload, not a selected mean.
|
||||
gains = {}
|
||||
for dan, label in (('PAM15', 'appetitive-conditioning'), ('PPL103', 'aversive-conditioning')):
|
||||
gains[label] = [row['population_separation_gains']['MBON'] for row in reports[dan]['replicates']]
|
||||
controls = reports[source].get('legacy_control_MBON_gains')
|
||||
require(isinstance(controls, Mapping) and set(controls) == {'D=0', 'random reward', 'frozen'},
|
||||
'Normal report lacks complete branch-bound legacy control gains')
|
||||
for name, label in (('D=0', 'd-zero-control'), ('random reward', 'random-reward-control'), ('frozen', 'frozen-brain-control')):
|
||||
require(set(controls[name]) == {row['replicate_id'] for row in reports[source]['replicates']}, 'Legacy control replicate mapping differs')
|
||||
gains[label] = [controls[name][row['replicate_id']] for row in reports[source]['replicates']]
|
||||
outcomes[source] = M.legacy_h_mean_control_audit(gains)
|
||||
groups.append(dict(mode=mode, conditioned_cue=cue, control_sources=outcomes,
|
||||
both_pass=all(value['predicate_pass'] for value in outcomes.values())))
|
||||
return dict(schema=SCHEMA, status='CONDITIONAL-AUDIT', declared_mapping=declared_mapping, groups=groups,
|
||||
both_pass=all(group['both_pass'] for group in groups), original_H_data_layout_reproduced=False,
|
||||
new_stricter_control_source_mapping=True, **_scope())
|
||||
@@ -0,0 +1,178 @@
|
||||
"""Exclusive preregistration for a finite NEW execution-boundary experiment.
|
||||
|
||||
No sampler, brain, update or historical experiment is executed by preparation.
|
||||
Frozen checksums are read. Future outputs are derived later from explicit rules,
|
||||
never given fabricated preregistered hashes. Real learning is NOT authorized.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
import boundary_plan as PLAN
|
||||
import execution_authority as A
|
||||
|
||||
ROOT=Path('/data/digital-drosophila')
|
||||
MODEL=Path(__file__).resolve().parent
|
||||
EXP=ROOT/'experiments/phase4aq-conditioning-execution'
|
||||
AP=ROOT/'experiments/phase4ap-conditioning-interface-v2'
|
||||
AO=ROOT/'experiments/phase4ao-conditioning-interface'
|
||||
LAB=MODEL.parent/'olfactory-conditioning-lab-v1'
|
||||
require,read,digest=A.require,A.read,A.digest
|
||||
|
||||
|
||||
def save(path,value):
|
||||
with Path(path).open('x',encoding='utf-8') as f:
|
||||
json.dump(value,f,sort_keys=True,indent=2,allow_nan=False,ensure_ascii=False);f.write('\n')
|
||||
|
||||
|
||||
def copy_exclusive(source,target):
|
||||
with Path(source).open('rb') as inp,Path(target).open('xb') as out:shutil.copyfileobj(inp,out)
|
||||
require(digest(source)==digest(target),'Exclusive source copy differs')
|
||||
|
||||
|
||||
def npz(path):
|
||||
with np.load(path,allow_pickle=False) as f:return {n:f[n].copy() for n in f.files}
|
||||
|
||||
|
||||
def save_npz(path,values):
|
||||
with Path(path).open('xb') as f:np.savez_compressed(f,**values)
|
||||
|
||||
|
||||
def verify(pins):
|
||||
for path,sha in pins.items():require(A.pin(path)['sha256']==sha,'Pinned input changed: '+str(path))
|
||||
|
||||
|
||||
def old_context():
|
||||
pins={str(AP/k):v for k,v in PLAN.AP_ANCHORS.items()}
|
||||
pins.update({str(MODEL.parent/k):v for k,v in PLAN.SOURCE_PINS.items()})
|
||||
verify(pins)
|
||||
apreg=read(AP/'protocol/preregistered.json')
|
||||
verify({**apreg['input_sha256'],**apreg['source_sha256'],**apreg['prepared_file_sha256']})
|
||||
path=MODEL.parent/'conditioning-interface-v2/coordinator.py'
|
||||
raw=path.read_bytes();name='_conditioning_execution_prior_integrity'
|
||||
require(name not in sys.modules,'Fresh preparation/integrity process required')
|
||||
spec=importlib.util.spec_from_file_location(name,path);module=importlib.util.module_from_spec(spec)
|
||||
sys.modules[name]=module;exec(compile(raw,str(path),'exec'),module.__dict__)
|
||||
return module,apreg,pins
|
||||
|
||||
|
||||
def integrity():
|
||||
old,apreg,pins=old_context()
|
||||
earlier=old.previous_integrity();current=old.helper().verify_seal(AP)
|
||||
require(read(AP/'audit/final-status.json')['status']=='PASS-EXACT-PROCESS-ISOLATED-DELTA-INTERFACE-NOT-LEARNING',
|
||||
'AP interface gate changed')
|
||||
return dict(complete=True,AP=current,prior=earlier,anchors=pins,
|
||||
old_experiments_reexecuted=False,old_files_modified=False,
|
||||
five_frozen_reference_trials_rerun_here=False,
|
||||
historical_reference_evidence_scope='Preserved AM numerical regression evidence; checksums now reverified',
|
||||
scientific_learning_pass_claimed=False)
|
||||
|
||||
|
||||
def source_inventory():
|
||||
entries=list(MODEL.iterdir())
|
||||
require(entries and all(p.is_file() and not p.is_symlink() and p.suffix in ('.py','.md') for p in entries),
|
||||
'Source directory may contain only explicit unlinked Python/Markdown source files')
|
||||
return {str(p):digest(p) for p in sorted(entries)}
|
||||
|
||||
|
||||
def prepare():
|
||||
require(sys.dont_write_bytecode and EXP.is_dir() and not any(EXP.iterdir()),'Use -B and exact new empty experiment directory')
|
||||
old,apreg,anchors=old_context()
|
||||
before=dict(complete=True,AP=old.helper().verify_seal(AP),prior=old.previous_integrity(),
|
||||
five_frozen_reference_trials_rerun_here=False,old_files_modified=False)
|
||||
plan=PLAN.build_plan();PLAN.validate_plan(plan)
|
||||
source=source_inventory();commit=subprocess.check_output(['git','-C',str(ROOT),'rev-parse','HEAD']).decode().strip()
|
||||
require(len(commit)==40,'Missing actual code commit')
|
||||
for path,sha in source.items():
|
||||
raw=subprocess.check_output(['git','-C',str(ROOT),'show',commit+':'+Path(path).relative_to(ROOT).as_posix()])
|
||||
require(hashlib.sha256(raw).hexdigest()==sha,'Source not equal to committed blob: '+path)
|
||||
budget=dict(root=str(EXP),output_cap_bytes=4*1024**3,minimum_free_reserve_bytes=10*1024**3,
|
||||
child_timeout_seconds=1800,workflow_timeout_seconds=7200)
|
||||
require(shutil.disk_usage(EXP).free>=budget['output_cap_bytes']+budget['minimum_free_reserve_bytes'],
|
||||
'Insufficient space for finite validation budget')
|
||||
pins={**anchors,**apreg['input_sha256'],**apreg['source_sha256'],**apreg['prepared_file_sha256']}
|
||||
parents={}
|
||||
for arm,descriptor in plan['imported_parents'].items():
|
||||
directory=Path(descriptor['checkpoint_manifest']).parent
|
||||
record=old.C.load_checkpoint(directory,descriptor['sha256'])
|
||||
require(record['fresh'] and record['steps']==1200,'Imported parent is not the declared fresh epoch')
|
||||
authority=AP/'jobs'/f'{arm}--reference--epoch-001.authority.json'
|
||||
update=AP/'updates'/f'{arm}--reference--epoch-001'
|
||||
ea=read(authority)
|
||||
require(ea['checkpoint_dir']==str(directory) and ea['checkpoint_manifest_sha256']==descriptor['sha256'],
|
||||
'Original update authority is not bound to selected parent')
|
||||
for path in (directory/'checkpoint-manifest.json',authority,*update.iterdir()):pins[str(path)]=digest(path)
|
||||
parents[descriptor['role']]=dict(directory=str(directory),checkpoint_sha256=descriptor['sha256'],
|
||||
epoch_authority=A.pin(authority),update_dir=str(update),update_sha256={p.name:digest(p) for p in update.iterdir()},
|
||||
before_overlay=dict(overlay_file=ea['files']['overlay_before']['path'],overlay_manifest=ea['files']['overlay_manifest_before']['path']),
|
||||
after_overlay=dict(overlay_file=str(update/'delta-after.npz'),overlay_manifest=str(update/'overlay-manifest.json')))
|
||||
zero=apreg['initial_overlay']
|
||||
require(A.pin(zero['overlay_file'])==plan['initial_overlay']['overlay_file'] and
|
||||
A.pin(zero['overlay_manifest'])==plan['initial_overlay']['overlay_manifest'],'Initial zero reference differs')
|
||||
require(not np.any(npz(zero['overlay_file'])['plastic_delta_mv'].view(np.uint32)),'Initial delta is not positive zero')
|
||||
template=read(AP/'cases/D1--reference--epoch-001/spec.json')
|
||||
for name in ('protocol/source-snapshot','protocol/case-templates','inputs/static','cases','runs','updates',
|
||||
'jobs','authorities','receipts','logs','audit','regression'):(EXP/name).mkdir(parents=True)
|
||||
for path in source:copy_exclusive(path,EXP/'protocol/source-snapshot'/Path(path).name)
|
||||
save(EXP/'regression/integrity-before.json',before)
|
||||
templates={}
|
||||
for call in plan['calls']:
|
||||
group=call.get('case_group',call['call_id'])
|
||||
spec=PLAN.derive_case_spec(template,call['call_id'],budget_root=str(EXP))
|
||||
if group in templates:require(spec==read(templates[group]),'Shared comparison case templates differ')
|
||||
else:
|
||||
dest=EXP/'protocol/case-templates'/f'{group}.json';save(dest,spec);templates[group]=str(dest)
|
||||
ea=read(parents[plan['imported_parents']['D1']['role']]['epoch_authority']['path'])
|
||||
candidate=npz(ea['files']['candidate_map']['path'])
|
||||
population_file=AO/'inputs/static/populations.npz'
|
||||
require(str(population_file) in pins,'Original anatomical population inventory not pinned by AP')
|
||||
populations=npz(population_file);dan=populations['PAM15']
|
||||
requests,selection=PLAN.mechanical_requests(candidate,dan,identity_binding=dict(
|
||||
candidate_map_sha256=ea['files']['candidate_map']['sha256'],
|
||||
pam15_membership_sha256=hashlib.sha256(dan.tobytes()).hexdigest()))
|
||||
require(np.isin(candidate['source_neuron_idx'],populations['Kenyon_Cell']).all(),'Candidate source outside original KC population')
|
||||
save_npz(EXP/'inputs/static/mechanical-requests.npz',requests)
|
||||
save(EXP/'inputs/static/mechanical-selection.json',selection)
|
||||
# Original physiological PN mapping is recomputed without stochastic sampling.
|
||||
import conditioning_preflight_inputs as I
|
||||
rates=I.load_rate_tables(ROOT)
|
||||
for cue,table in rates['tables'].items():
|
||||
existing=npz(AO/f'inputs/static/{cue}-rates.npz')
|
||||
require(all(table[k].dtype==existing[k].dtype and table[k].shape==existing[k].shape and
|
||||
table[k].tobytes()==existing[k].tobytes() for k in ('targets','rates_hz')),
|
||||
'Prior physiological PN mapping differs')
|
||||
copy_exclusive(AO/f'inputs/static/{cue}-rates.npz',EXP/f'inputs/static/{cue}-rates.npz')
|
||||
save(EXP/'inputs/static/rate-audit.json',rates['audit'])
|
||||
fullplan=AO/'protocol/full-trial-plan.json'
|
||||
require(str(fullplan) in pins,'Original full seed/trial plan not pinned')
|
||||
prepared={str(p):digest(p) for sub in ('protocol','inputs/static','regression') for p in (EXP/sub).rglob('*') if p.is_file()}
|
||||
reg=dict(schema='conditioning-execution-registration-v1',engineering_only=True,scientific_acquisition_authorized=False,
|
||||
scope='bounded updated-state boundary, fixed functional-gate code, complete-process budget measurement',
|
||||
plan=plan,source_sha256=source,source_code_commit=commit,input_sha256=pins,prepared_file_sha256=prepared,
|
||||
parent_records=parents,initial_overlay=zero,case_templates=templates,budget=budget,original_full_plan=A.pin(fullplan),
|
||||
old_source_changes=False,old_experiments_reexecuted=False,brain_or_sampler_run_during_preparation=False,
|
||||
future_hashes_fabricated=False,learning_success_claimed=False,
|
||||
failure_policy='stop and preserve partials; never automatic retry, tuning, seed search, or trial truncation')
|
||||
verify({**pins,**source,**prepared})
|
||||
save(EXP/'protocol/preregistered.json',reg)
|
||||
return digest(EXP/'protocol/preregistered.json')
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('mode',choices=('prepare','integrity'))
|
||||
parser.add_argument('--output')
|
||||
args=parser.parse_args()
|
||||
if args.mode=='prepare':print('REGISTRATION_SHA256',prepare(),flush=True)
|
||||
else:
|
||||
require(args.output and not Path(args.output).exists(),'Exclusive integrity report required')
|
||||
save(args.output,integrity());print('INTEGRITY_SHA256',digest(args.output),flush=True)
|
||||
@@ -0,0 +1,299 @@
|
||||
"""Synthetic file-chain/dispatch tests; never a brain or historical audit."""
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
from contextlib import ExitStack
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
|
||||
import audit_execution as T
|
||||
|
||||
|
||||
def write(path, value):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(value, sort_keys=True), encoding='utf-8')
|
||||
|
||||
|
||||
def npz(path, **values):
|
||||
with path.open('wb') as stream:
|
||||
np.savez(stream, **values)
|
||||
|
||||
|
||||
class PlanTests(unittest.TestCase):
|
||||
def test_exact_fixed_process_budget_and_kinds(self):
|
||||
plan = T.PLAN.build_plan(); values = T.expected_processes(plan)
|
||||
self.assertEqual(len(values), 31)
|
||||
self.assertEqual(sum(k in ('updated', 'oracle', 'unchanged', 'brain') for k in values.values()), 23)
|
||||
self.assertEqual(sum(k in ('update', 'validate_cpu') for k in values.values()), 7)
|
||||
self.assertEqual(list(values.values()).count('sample'), 1)
|
||||
self.assertEqual(sum(c['steps'] for c in plan['calls']), 125200)
|
||||
|
||||
def test_duplicate_call_and_wrong_budget_rejected(self):
|
||||
plan = T.PLAN.build_plan(); plan['calls'].append(copy.deepcopy(plan['calls'][0]))
|
||||
with self.assertRaisesRegex(ValueError, 'Duplicate'): T.expected_processes(plan)
|
||||
plan = T.PLAN.build_plan(); plan['counts']['total_children'] += 1
|
||||
with self.assertRaisesRegex(ValueError, 'inventory'): T.expected_processes(plan)
|
||||
|
||||
def test_D1_zero_coverage_does_not_deny_mechanical_witness(self):
|
||||
pending = {'D1': {'accepted_changed_edge_witness_verified': False},
|
||||
'mechanical': {'accepted_changed_edge_witness_verified': True}}
|
||||
exact, coverage, status = T.outcome({'all_numeric': True}, pending)
|
||||
self.assertTrue(exact and coverage)
|
||||
self.assertEqual(status, 'PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING')
|
||||
pending['mechanical']['accepted_changed_edge_witness_verified'] = False
|
||||
self.assertEqual(T.outcome({'all_numeric': True}, pending)[2], 'INCOMPLETE-CHANGED-EDGE-COVERAGE')
|
||||
self.assertEqual(T.outcome({'all_numeric': False}, pending)[2], 'FAIL-NUMERICAL-OR-LINEAGE')
|
||||
with self.assertRaises(ValueError): T.outcome({}, pending)
|
||||
with self.assertRaises(ValueError): T.outcome({'impostor_bool': 1}, pending)
|
||||
|
||||
|
||||
class ProcessTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory(); self.exp = Path(self.temp.name).resolve() / 'phase4aq-synthetic'
|
||||
self.patch = patch.object(T, 'EXP', self.exp); self.patch.start()
|
||||
self.name = 'performance--natural-light-fresh'; self.kind = 'brain'
|
||||
self.regfile = self.exp / 'protocol/preregistered.json'; write(self.regfile, {'synthetic': True})
|
||||
self.reg_sha = T.digest(self.regfile)
|
||||
self.h = T._helpers()
|
||||
self.reg = dict(source_sha256={str(T.MODEL / 'isolated_execution.py'): T.digest(T.MODEL / 'isolated_execution.py')},
|
||||
input_sha256={}, prepared_file_sha256={})
|
||||
case = self.exp / 'cases' / self.name; write(case / 'spec.json', {'synthetic': True})
|
||||
(case / 'requests.npz').write_bytes(b'not-scientific-requests')
|
||||
overlay = self.exp / 'inputs/before.npz'; overlay.parent.mkdir(); overlay.write_bytes(b'not-scientific-overlay')
|
||||
om = self.exp / 'inputs/before.json'; write(om, {})
|
||||
self.output = self.exp / 'runs' / self.name; write(self.output / 'summary.json', {'synthetic': True})
|
||||
self.jobpath = self.exp / 'jobs' / (self.name + '.json')
|
||||
self.workerpath = self.exp / 'receipts' / (self.name + '.worker.json')
|
||||
self.processpath = self.exp / 'receipts' / (self.name + '.process.json')
|
||||
self.stdout = self.exp / 'logs' / (self.name + '.stdout.log'); self.stdout.parent.mkdir()
|
||||
self.stdout.write_bytes(b'fixture'); self.stderr = self.stdout.with_name(self.name + '.stderr.log'); self.stderr.write_bytes(b'')
|
||||
self.sources = {n: dict(path=str(T.LAB / (n + '.py')), sha256=self.h.SOURCE_PINS[n])
|
||||
for n in ('runtime_light', 'runtime_continuation')}
|
||||
inputs = T._closure(self.reg, self.reg_sha)
|
||||
inputs.update({str(p): T.digest(p) for p in (case / 'spec.json', case / 'requests.npz', overlay, om)})
|
||||
self.job = dict(schema='phase4ap-isolated-worker-job-v1', job_id=self.name, kind='brain', registration_sha256=self.reg_sha,
|
||||
worker_sha256=T.W.AP_SHA, case_dir=str(case), overlay_file=str(overlay), overlay_manifest=str(om),
|
||||
output_dir=str(self.output), receipt_file=str(self.workerpath), input_sha256=inputs, sources=self.sources)
|
||||
self.seal_records()
|
||||
|
||||
def tearDown(self):
|
||||
self.patch.stop(); self.temp.cleanup()
|
||||
|
||||
def seal_records(self):
|
||||
write(self.jobpath, self.job); job_sha = T.digest(self.jobpath)
|
||||
attempt = Path(str(self.workerpath) + '.attempt.json')
|
||||
write(attempt, dict(complete=False, job_sha256=job_sha, no_automatic_retry=True))
|
||||
hashes = {k: v['sha256'] for k, v in T.tree(self.output).items()}
|
||||
pins = {**self.job['input_sha256'], str(self.jobpath): job_sha, str(T.W.AP): T.W.AP_SHA,
|
||||
**{v['path']: v['sha256'] for v in self.sources.values()}}
|
||||
receipt = dict(schema='phase4ap-isolated-worker-receipt-v1', complete=True, job_id=self.name, kind='brain',
|
||||
registration_sha256=self.reg_sha, worker_sha256=T.W.AP_SHA, job_sha256=job_sha,
|
||||
process_exit_independently_observed=False, scientific_gate_pass_claimed=False, source_files=self.sources,
|
||||
verified_input_sha256=pins, output_dir=str(self.output), output_files_sha256=hashes,
|
||||
attempt_sha256=T.digest(attempt), result={'synthetic': True})
|
||||
write(self.workerpath, receipt)
|
||||
process = dict(schema='conditioning-execution-process-v1', name=self.name, kind='brain', registration_sha256=self.reg_sha,
|
||||
complete=True, exit_code=0, timed_out=False, job_sha256=job_sha, worker_receipt_sha256=T.digest(self.workerpath),
|
||||
stdout_sha256=T.digest(self.stdout), stderr_sha256=T.digest(self.stderr),
|
||||
argv=['/synthetic/python', '-B', str(T.W.AP), 'brain', '--job', str(self.jobpath), '--job-sha256', job_sha],
|
||||
output_bytes=sum(v['bytes'] for v in T.tree(self.output).values()),
|
||||
output_inventory_sha256=hashlib.sha256(json.dumps(hashes, sort_keys=True).encode()).hexdigest(),
|
||||
child_wall_seconds=.1, end_to_end_seconds=.2, validation_wall_seconds=.1)
|
||||
write(self.processpath, process)
|
||||
|
||||
def verify(self):
|
||||
return T.verify_process(self.name, self.kind, self.reg, self.reg_sha, self.processpath, self.h)
|
||||
|
||||
def test_actual_file_chain_not_working_memory_flags(self):
|
||||
result = self.verify()
|
||||
self.assertEqual(result['kind'], 'brain'); self.assertEqual(result['output'], self.output)
|
||||
|
||||
def test_nonzero_exit_and_bool_exit_rejected(self):
|
||||
original = T.read(self.processpath)
|
||||
for value in (1, False, None):
|
||||
changed = copy.deepcopy(original); changed['exit_code'] = value; write(self.processpath, changed)
|
||||
with self.subTest(value=value), self.assertRaisesRegex(ValueError, 'recorded process exit'): self.verify()
|
||||
|
||||
def test_log_mutation_and_unknown_output_rejected(self):
|
||||
self.stderr.write_bytes(b'changed')
|
||||
with self.assertRaisesRegex(ValueError, 'file chain'): self.verify()
|
||||
self.stderr.write_bytes(b''); (self.output / 'unreported.json').write_text('{}')
|
||||
with self.assertRaisesRegex(ValueError, 'inventory'): self.verify()
|
||||
|
||||
def test_missing_registration_source_closure_even_rehashed_rejected(self):
|
||||
del self.job['input_sha256'][str(T.MODEL / 'isolated_execution.py')]; self.seal_records()
|
||||
with self.assertRaisesRegex(ValueError, 'closure omitted'): self.verify()
|
||||
|
||||
def test_extra_self_authorized_input_even_rehashed_rejected(self):
|
||||
extra = self.exp / 'arbitrary.txt'; extra.write_text('extra')
|
||||
self.job['input_sha256'][str(extra)] = T.digest(extra); self.seal_records()
|
||||
with self.assertRaisesRegex(ValueError, 'undeclared input'): self.verify()
|
||||
|
||||
def test_wrong_command_and_process_path_rejected(self):
|
||||
p = T.read(self.processpath); p['argv'][2] = '/unregistered/worker.py'; write(self.processpath, p)
|
||||
with self.assertRaisesRegex(ValueError, 'command differs'): self.verify()
|
||||
with self.assertRaisesRegex(ValueError, 'fixed process record'):
|
||||
T.verify_process(self.name, self.kind, self.reg, self.reg_sha, self.stdout, self.h)
|
||||
|
||||
def test_changed_source_snapshot_and_attempt_rejected(self):
|
||||
worker = T.read(self.workerpath); worker['attempt_sha256'] = '0' * 64; write(self.workerpath, worker)
|
||||
p = T.read(self.processpath); p['worker_receipt_sha256'] = T.digest(self.workerpath); write(self.processpath, p)
|
||||
with self.assertRaisesRegex(ValueError, 'Attempt record changed'): self.verify()
|
||||
|
||||
|
||||
class ComparisonTests(unittest.TestCase):
|
||||
def test_light_missing_perstep_is_reported_not_fabricated(self):
|
||||
state = {k: np.zeros(3, np.int32) for k in T.B.C.STATE_KEYS}
|
||||
terminal = {k: np.zeros(3, np.int32) for k in ('spike_ring', 'apl_state', 'apl_pending', 'next_tick')}
|
||||
left = dict(steps=1, global_tick_offset=0, state=state, terminal=terminal, requests=np.empty((0, 5), np.int64),
|
||||
summary={'effective_weights_raw_sha256': '1'*64}, traces={}, state_hashes=None, queues=None)
|
||||
right = copy.deepcopy(left)
|
||||
with patch.object(T.B, '_complete'):
|
||||
report = T._pair(left, right)
|
||||
self.assertTrue(report['numerical_exact']); self.assertFalse(any(report['observed'].values()))
|
||||
right['state']['v'][0] = 1
|
||||
report = T._pair(left, right)
|
||||
self.assertFalse(report['numerical_exact'])
|
||||
self.assertIn('pair.state.v', report['failed_checks'])
|
||||
|
||||
def test_imported_parent_fields_cannot_be_rebound(self):
|
||||
reg = {'parent_records': {'p': {'directory': '/original', 'checkpoint_sha256': '1'*64}}}
|
||||
complete = {'parents': {'p': {**reg['parent_records']['p'], 'cpu_validation': '/new/check.json'}}}
|
||||
self.assertEqual(T._parent(reg, complete, 'p')['directory'], '/original')
|
||||
complete['parents']['p']['directory'] = '/other'
|
||||
with self.assertRaisesRegex(ValueError, 'Imported parent'): T._parent(reg, complete, 'p')
|
||||
|
||||
def test_output_tree_nonfiles_and_pins_are_actual_bytes(self):
|
||||
with tempfile.TemporaryDirectory() as name:
|
||||
p = Path(name).resolve() / 'payload'; p.write_bytes(b'abc')
|
||||
T.verify_pins({str(p): T.digest(p)})
|
||||
with self.assertRaisesRegex(ValueError, 'Pinned file changed'): T.verify_pins({str(p): '0'*64})
|
||||
|
||||
|
||||
class OrchestrationTests(unittest.TestCase):
|
||||
"""Dispatch fixture: deliberately mocked physics/loaders, no scientific PASS."""
|
||||
def fixture(self, exp):
|
||||
plan = T.PLAN.build_plan(); parents = {}; imports = {}; records = {}; verified = {}; templates = {}
|
||||
delta = dict(edge_id=np.array([0], np.int64), plastic_delta_mv=np.array([0], np.float32))
|
||||
def parent(directory, name):
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
write(directory / 'summary.json', {'synthetic': True})
|
||||
write(directory / 'checkpoint-manifest.json', {'synthetic': True})
|
||||
update = exp / 'updates' / name; update.mkdir(parents=True, exist_ok=True)
|
||||
npz(update / 'delta-after.npz', **delta); write(update / 'update-receipt.json', {'same': 'synthetic-U'})
|
||||
write(update / 'overlay-manifest.json', {'synthetic': True})
|
||||
auth = exp / 'authorities' / (name + '.epoch.json'); write(auth, {'synthetic': True})
|
||||
return dict(directory=str(directory), checkpoint_sha256=T.digest(directory / 'checkpoint-manifest.json'),
|
||||
epoch_authority=T.A.pin(auth), update_dir=str(update),
|
||||
after_overlay=dict(overlay_file=str(update / 'delta-after.npz'), overlay_manifest=str(update / 'overlay-manifest.json')))
|
||||
for arm, desc in plan['imported_parents'].items():
|
||||
p = parent(exp / 'old-AP' / arm, 'old-' + arm)
|
||||
desc['checkpoint_manifest'] = str(Path(p['directory']) / 'checkpoint-manifest.json')
|
||||
desc['sha256'] = p['checkpoint_sha256']; parents[desc['role']] = p; imports[arm] = p
|
||||
registered_parents = copy.deepcopy(parents)
|
||||
for call in plan['calls']:
|
||||
name = call['call_id']; out = exp / 'runs' / name
|
||||
if call['runner'] != 'boundary_oracle':
|
||||
p = parent(out, name); parents[name] = p
|
||||
else:
|
||||
out.mkdir(parents=True); write(out / 'summary.json', {'synthetic': True})
|
||||
write(out / 'oracle-manifest.json', dict(schema='conditioning-live-oracle-files-v1', complete=True,
|
||||
files_sha256={'summary.json': T.digest(out / 'summary.json')}))
|
||||
group = call['case_group']; template = exp / 'protocol/case-templates' / (group + '.json')
|
||||
spec = {'synthetic': group, 'steps': call['steps']}
|
||||
if group not in templates: write(template, spec); templates[group] = str(template)
|
||||
if call['parent'] is not None:
|
||||
spec.update(parent_checkpoint_manifest_sha256=parents[call['parent']]['checkpoint_sha256'],
|
||||
global_tick_offset=call['global_tick_offset'])
|
||||
case = exp / 'cases' / group; write(case / 'spec.json', spec)
|
||||
npz(case / 'requests.npz', tick=np.empty(0, np.int32), neuron_idx=np.empty(0, np.int32))
|
||||
record = dict(source=str(out), steps=call['steps'], global_tick_offset=call['global_tick_offset'],
|
||||
summary=dict(nodes=1, edges=1, diagnostic_mode=call['diagnostic_mode'], apl_component={'environment': {}}),
|
||||
state={'v': np.array([0.], np.float64)})
|
||||
if call['runner'] != 'boundary_oracle': record['manifest_sha256'] = parents[name]['checkpoint_sha256']
|
||||
records[str(out)] = record
|
||||
cycle = dict(complete=True, call=call, source_registration_sha256='placeholder', output_inventory={})
|
||||
write(exp / 'receipts' / (name + '.cycle.json'), cycle)
|
||||
for arm, p in imports.items():
|
||||
records[p['directory']] = dict(source=p['directory'], summary={}, manifest_sha256=p['checkpoint_sha256'])
|
||||
reg = dict(schema='conditioning-execution-registration-v1', engineering_only=True, scientific_acquisition_authorized=False,
|
||||
plan=plan, source_sha256={}, input_sha256={}, prepared_file_sha256={}, parent_records=registered_parents,
|
||||
case_templates=templates)
|
||||
regfile = exp / 'protocol/preregistered.json'; write(regfile, reg); sha = T.digest(regfile)
|
||||
kinds = T.expected_processes(plan)
|
||||
for name, kind in kinds.items():
|
||||
out = exp / ('updates' if kind == 'update' else 'runs') / name.removesuffix('--original-E')
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
if not any(out.iterdir()): write(out / 'payload.json', {'synthetic': True})
|
||||
job = {'kind': kind}
|
||||
call = next((c for c in plan['calls'] if c['call_id'] == name), None)
|
||||
if call is not None:
|
||||
case = exp / 'cases' / call['case_group']
|
||||
if kind in ('brain', 'unchanged'): job['case_dir'] = str(case)
|
||||
elif kind == 'oracle': job['oracle_case'] = str(case)
|
||||
else:
|
||||
p = parents[call['parent']]
|
||||
auth = dict(case=dict(spec=T.A.pin(case / 'spec.json'), requests=T.A.pin(case / 'requests.npz')),
|
||||
boundary_id=name, registration_sha256=sha, diagnostic_mode=call['diagnostic_mode'],
|
||||
input_policy=call['input_policy'], transition=call['transition'],
|
||||
parent=dict(directory=p['directory'], checkpoint_manifest_sha256=p['checkpoint_sha256']),
|
||||
expected_effective_weight_before_sha256='a'*64, expected_effective_weight_after_sha256='b'*64)
|
||||
path = exp / 'authorities' / (name + '.json'); write(path, auth); job['authority_file'] = str(path)
|
||||
cyclefile = exp / 'receipts' / (name + '.cycle.json'); cycle = T.read(cyclefile)
|
||||
cycle['source_registration_sha256'] = sha; write(cyclefile, cycle)
|
||||
result = {}
|
||||
if kind in ('brain', 'unchanged', 'updated'): result['checkpoint_manifest_sha256'] = parents[name]['checkpoint_sha256']
|
||||
if kind == 'update':
|
||||
write(out / 'chain-receipt.json', {'synthetic': True}); result['chain_receipt_sha256'] = T.digest(out / 'chain-receipt.json')
|
||||
paths = {key: exp / folder / (name + suffix) for key, folder, suffix in
|
||||
(('process', 'receipts', '.process.json'), ('worker', 'receipts', '.worker.json'), ('job', 'jobs', '.json'))}
|
||||
for p in paths.values(): write(p, {'synthetic': name})
|
||||
verified[name] = dict(name=name, kind=kind, job=job, paths=paths, output=out,
|
||||
output_inventory=T.tree(out), receipt={'result': result, 'environment': {}}, input_pins={},
|
||||
evidence_sha256={str(p): T.digest(p) for p in paths.values()})
|
||||
complete = dict(complete=True, registration_sha256=sha, completed_calls=[c['call_id'] for c in plan['calls']],
|
||||
processes={k: str(v['paths']['process']) for k, v in verified.items()}, parents=parents,
|
||||
scientific_learning_pass_claimed=False, candidate_generated=False)
|
||||
write(exp / 'audit/execution-complete.json', complete)
|
||||
return sha, records, verified
|
||||
|
||||
def test_all_predetermined_calls_compared_and_numeric_failure_not_hidden(self):
|
||||
with tempfile.TemporaryDirectory() as name, ExitStack() as stack:
|
||||
exp = Path(name).resolve() / 'phase4aq-mock'; sha, records, verified = self.fixture(exp)
|
||||
stack.enter_context(patch.object(T, 'EXP', exp))
|
||||
stack.enter_context(patch.object(T, 'N', 1)); stack.enter_context(patch.object(T, 'EDGES', 1))
|
||||
stack.enter_context(patch.object(T.PLAN, 'validate_plan'))
|
||||
stack.enter_context(patch.object(T, '_helpers', return_value=SimpleNamespace(_verify_precision=lambda *a: None)))
|
||||
verifier = stack.enter_context(patch.object(T, 'verify_process', side_effect=lambda n, *args: verified[n]))
|
||||
stack.enter_context(patch.object(T.D, 'load_checkpoint')); stack.enter_context(patch.object(T.D.C, 'load_checkpoint'))
|
||||
stack.enter_context(patch.object(T.B, 'load_record', side_effect=lambda d, **kw: records[str(d)]))
|
||||
stack.enter_context(patch.object(T.B, '_complete')); stack.enter_context(patch.object(T.B, 'close_record'))
|
||||
stack.enter_context(patch.object(T, '_update_check', return_value={'pass_all': True}))
|
||||
live = stack.enter_context(patch.object(T.B, 'compare_boundary', return_value={'numerical_exact': True}))
|
||||
pair = stack.enter_context(patch.object(T, '_pair', return_value={'numerical_exact': True}))
|
||||
pending = dict(conditional_ref_request_queue_exact=True, reference_queue_and_ref_coverage_complete=True,
|
||||
accepted_changed_edge_witness_verified=True)
|
||||
stack.enter_context(patch.object(T, '_pending', return_value=pending))
|
||||
stack.enter_context(patch.object(T, '_lineage', return_value={'pass_all': True}))
|
||||
report = T.audit(sha, save_report=False)
|
||||
self.assertTrue(report['pass_all']); self.assertEqual(report['actual_new_brain_calls'], 23)
|
||||
self.assertEqual(report['actual_new_brain_ticks'], 125200); self.assertEqual(report['actual_processes'], 31)
|
||||
self.assertEqual(verifier.call_count, 31); self.assertEqual(live.call_count, 4); self.assertEqual(pair.call_count, 5)
|
||||
self.assertFalse(report['brain_executed_here']); self.assertFalse(report['learning_pass_claimed'])
|
||||
self.assertFalse((exp / 'audit/numerical-comparison.json').exists())
|
||||
pair.return_value = {'numerical_exact': False}
|
||||
report = T.audit(sha)
|
||||
self.assertEqual(report['status'], 'FAIL-NUMERICAL-OR-LINEAGE'); self.assertFalse(report['pass_all'])
|
||||
self.assertTrue((exp / 'audit/numerical-comparison.json').is_file())
|
||||
with self.assertRaises(FileExistsError): T.audit(sha)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,281 @@
|
||||
"""Tiny synthetic arrays / temporary read fixtures; no brain or GPU execution."""
|
||||
import copy
|
||||
import csv
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
import boundary_compare as m
|
||||
|
||||
|
||||
Q=m._load('engineering_queue_audit.py',m.PINS['engineering_queue_audit.py'])
|
||||
|
||||
|
||||
def raw(a):return __import__('hashlib').sha256(np.ascontiguousarray(a).tobytes()).hexdigest()
|
||||
|
||||
|
||||
def save(path,value):path.write_text(json.dumps(value,allow_nan=False),encoding='utf-8')
|
||||
|
||||
|
||||
class Fixture:
|
||||
def __init__(self,cut=20,total=61,reject=False,delta=None):
|
||||
self.cut,self.total=cut,total
|
||||
self.graph=dict(ptr=np.array([0,2,4,5,6],np.int64),src=np.array([0,0,1,1,2,3],np.int32),
|
||||
dst=np.array([1,2,2,3,3,0],np.int32),edge_id=np.arange(6,dtype=np.int64),
|
||||
base_weights=np.full(6,.000275,np.float64),apl_mask=np.zeros(6,np.bool_),
|
||||
candidate_edge_id=np.array([0],np.int64),delta_before=np.array([0.],np.float32),
|
||||
delta_after=np.array([-.00275 if delta is None else delta],np.float32))
|
||||
g=self.graph
|
||||
_,_,rows,before,after=m._candidates(g['ptr'],g['src'],g['dst'],g['edge_id'],g['base_weights'],g['apl_mask'],
|
||||
g['candidate_edge_id'],g['delta_before'],g['delta_after'],Q)
|
||||
self.before_sha=m._effective_hash(g['base_weights'],g['apl_mask'],rows,before)
|
||||
self.after_sha=m._effective_hash(g['base_weights'],g['apl_mask'],rows,after)
|
||||
self.effective=g['base_weights'].copy();self.effective[rows]=after
|
||||
pairs=[(0,3),(cut-2,2),(cut-1,0),(cut+23,0),(total-1,2)]
|
||||
if reject:pairs.append((cut+17,1))
|
||||
pairs=sorted(pairs);self.tick=np.array([t for t,n in pairs],np.int32);self.node=np.array([n for t,n in pairs],np.int32)
|
||||
self.requests=np.column_stack((self.tick,self.node,np.ones(len(pairs),np.int32),np.ones(len(pairs),np.int32),np.zeros(len(pairs),np.int32))).astype(np.int64)
|
||||
refs=[];ref=np.zeros(4,np.int32);self.queues=[]
|
||||
for t in range(total):
|
||||
ref=np.maximum(ref-1,0).astype(np.int32);ref[self.node[self.tick==t]]=22;refs.append(ref.copy())
|
||||
sources=self.node[self.tick==t-18] if t>=18 else self.node[:0]
|
||||
qr,_,_=Q._queue(t,t if t<cut else t-cut,sources,ref,g['ptr'],g['dst'],g['edge_id'],self.effective,[])
|
||||
self.queues.append(qr)
|
||||
self.refs=np.asarray(refs)
|
||||
self.v=np.full((total,4),-.052,np.float64)+np.arange(total)[:,None]*np.float64(1e-7)
|
||||
self.g=np.zeros((total,4),np.float64)+np.arange(total)[:,None]*np.float64(1e-6)
|
||||
self.traces={'drive':np.arange(total*2,dtype=np.float32).reshape(total,2)*np.float32(.001),
|
||||
'state':np.arange(total*2,dtype=np.float32).reshape(total,2)*np.float32(.002),
|
||||
'generated':np.arange(total*3,dtype=np.float32).reshape(total,3)*np.float32(.003)}
|
||||
self.traces['applied']=np.zeros((total,3),np.float32);self.traces['applied'][18:]=self.traces['generated'][:-18]
|
||||
self.parent=self.record(0,cut,'reference');self.parent['manifest_sha256']='d'*64
|
||||
self.child=self.record(cut,total,'reference');self.oracle=self.record(0,total,'reference')
|
||||
self.parent['summary']['effective_weights_raw_sha256']=self.before_sha
|
||||
self.child['summary'].update(within_trial_weight_updates=False,checkpoint_continuation_used=True,
|
||||
updated_boundary_schema='conditioning-updated-boundary-v1',parent_checkpoint_manifest_sha256='d'*64,
|
||||
global_next_tick=total,boundary_transition='epoch_update',boundary_authority_sha256='e'*64,global_tick_offset=cut)
|
||||
self.oracle['summary'].update(diagnostic_live_boundary=True,within_trial_weight_updates=True,explicit_weight_switches=1,
|
||||
boundary_tick=cut,restored_from_checkpoint=False,production_backend=False,initial_effective_weights_raw_sha256=self.before_sha)
|
||||
self.oracle['boundary_snapshot']={**{k:self.parent['state'][k].copy() for k in ('v','g','ref','counts')},
|
||||
**{k:self.parent['terminal'][k].copy() for k in ('spike_ring','apl_state','apl_pending')}}
|
||||
self.oracle['boundary_report']=dict(complete=True,boundary_tick=cut,parent_checkpoint_manifest_sha256='d'*64,
|
||||
restore_called=False,initial_state_replaced=False,queues_replaced=False,existing_weights_replaced_once=True,
|
||||
before_effective_sha256=self.before_sha,after_effective_sha256=self.after_sha)
|
||||
self.oracle['oracle_provenance']=dict(schema='conditioning-live-boundary-oracle-v1',complete=True,
|
||||
restore_called=False,prefix_sparse_events_exact=True,learning_pass_claimed=False,authority_sha256='e'*64)
|
||||
|
||||
def record(self,start,stop,mode):
|
||||
selection=(self.tick>=start)&(self.tick<stop);tick=self.tick[selection]-np.int32(start);node=self.node[selection]
|
||||
ring=np.zeros((19,4),np.uint8)
|
||||
if start:
|
||||
for t in range(max(0,start-19),start):ring[t%19,self.node[self.tick==t]]=1
|
||||
ring=ring[(np.arange(19)+start%19)%19].copy()
|
||||
for t in range(stop-start):ring[t%19]=0;ring[t%19,node[tick==t]]=1
|
||||
pending=np.zeros((18,3),np.float32)
|
||||
available=min(stop,18);pending[-available:]=self.traces['generated'][stop-available:stop]
|
||||
state=dict(step=tick,neuron_idx=node,counts=np.bincount(node,minlength=4).astype(np.int32),
|
||||
v=self.v[stop-1].copy(),g=self.g[stop-1].copy(),ref=self.refs[stop-1].copy())
|
||||
req=self.requests[(self.requests[:,0]>=start)&(self.requests[:,0]<stop)].copy();req[:,0]-=start
|
||||
hashes=[dict(tick=t-start,v_sha256=raw(self.v[t]),g_sha256=raw(self.g[t]),ref_sha256=raw(self.refs[t])) for t in range(start,stop)]
|
||||
queues=[self.queues[t][0 if start==0 else 1].copy() for t in range(start,stop)]
|
||||
summary=dict(steps=stop-start,completed_ticks=stop-start,complete=True,pass_all=True,all_finite=True,nodes=4,edges=6,
|
||||
precision='float64',apl_precision='float32',apl_delay_steps=18,diagnostic_mode=mode,
|
||||
within_trial_weight_updates=False,effective_weights_raw_sha256=self.after_sha,checkpoint_continuation_used=start>0,
|
||||
global_tick_offset=start,global_next_tick=stop)
|
||||
return dict(steps=stop-start,global_tick_offset=start,state=state,
|
||||
terminal=dict(spike_ring=ring,apl_state=self.traces['state'][stop-1].copy(),apl_pending=pending,next_tick=np.asarray(stop-start,np.int64)),
|
||||
requests=req,summary=summary,traces={k:v[start:stop].copy() for k,v in self.traces.items()},state_hashes=hashes,queues=queues,
|
||||
terminal_origin='recorded_terminal_queues')
|
||||
|
||||
def compare(self,paired_authorities=None):
|
||||
return m.compare_boundary(self.oracle,self.child,parent=self.parent,
|
||||
expected_before_sha256=self.before_sha,expected_after_sha256=self.after_sha,paired_authorities=paired_authorities)
|
||||
|
||||
def audit(self):
|
||||
return m.audit_changed_pending(self.parent,self.child,**self.graph,input_pins={'synthetic-input-authority':'a'*64})
|
||||
|
||||
|
||||
class ComparisonTests(unittest.TestCase):
|
||||
def test_exact_reference_suffix_and_different_raw_ring_phase(self):
|
||||
f=Fixture();result=f.compare()
|
||||
self.assertTrue(result['numerical_exact'],result['failed_checks'])
|
||||
self.assertTrue(result['suffix_reference_diagnostics_compared'])
|
||||
self.assertFalse(np.array_equal(f.child['terminal']['spike_ring'],f.oracle['terminal']['spike_ring']))
|
||||
self.assertFalse(result['learning_pass_claimed'])
|
||||
self.assertFalse(result['changed_candidate_pending_arrival_coverage_verified'])
|
||||
|
||||
def test_light_reports_only_observed_scope(self):
|
||||
f=Fixture();f.child.update(traces={},state_hashes=None,queues=None);f.child['summary']['diagnostic_mode']='light'
|
||||
result=f.compare();self.assertTrue(result['numerical_exact']);self.assertFalse(result['suffix_reference_diagnostics_compared'])
|
||||
self.assertFalse(result['light_per_tick_identity_claimed'])
|
||||
self.assertNotIn('suffix.state_hashes',result['checks'])
|
||||
|
||||
def test_signed_zero_final_change_is_detected(self):
|
||||
f=Fixture();f.child['state']['g'][0]=0.;f.oracle['state']['g'][0]=-0.
|
||||
f.child['state_hashes'][-1]['g_sha256']=raw(f.child['state']['g'])
|
||||
f.oracle['state_hashes'][-1]['g_sha256']=raw(f.oracle['state']['g'])
|
||||
result=f.compare();self.assertFalse(result['pass_all']);self.assertIn('final.g',result['failed_checks'])
|
||||
|
||||
def test_tick_shift_ref_and_event_counts_are_not_interchangeable(self):
|
||||
f=Fixture();old=int(f.child['state']['step'][0]);f.child['state']['step'][0]-=1
|
||||
f.child['terminal']['spike_ring'][old%19,0]=0
|
||||
f.child['terminal']['spike_ring'][(old-1)%19,0]=1
|
||||
result=f.compare();self.assertFalse(result['numerical_exact']);self.assertIn('suffix.events.absolute_tick',result['failed_checks'])
|
||||
|
||||
def test_reference_missing_history_is_rejected_not_false_pass(self):
|
||||
f=Fixture();f.child['state_hashes']=None
|
||||
with self.assertRaisesRegex(ValueError,'diagnostics missing'):f.compare()
|
||||
|
||||
def test_queue_joint_header_exclusion_is_only_comparison_not_audit(self):
|
||||
f=Fixture();f.child['queues'][17]['joint_sha256']='1'*64
|
||||
self.assertTrue(f.compare()['pass_all'])
|
||||
self.assertFalse(f.audit()['pass_all'])
|
||||
|
||||
def test_wrong_live_prefix_parent_cannot_pass_suffix_only(self):
|
||||
f=Fixture();f.oracle['boundary_snapshot']['g'][0]+=1e-12
|
||||
result=f.compare();self.assertFalse(result['pass_all']);self.assertIn('boundary.live_parent.g',result['failed_checks'])
|
||||
|
||||
def test_original_authority_and_weight_scope_are_checked(self):
|
||||
f=Fixture();f.oracle['oracle_provenance']['authority_sha256']='a'*64
|
||||
self.assertFalse(f.compare()['pass_all'])
|
||||
|
||||
def pair(self,f,changed=None):
|
||||
original={key:{'synthetic':1} for key in m.AUTHORITY_FIELDS}
|
||||
original.update(schema='conditioning-updated-boundary-v1',boundary_id='reference-boundary',diagnostic_mode='reference')
|
||||
other=copy.deepcopy(original);other.update(boundary_id='light-boundary',diagnostic_mode='light')
|
||||
if changed:other.update(changed)
|
||||
pair=(json.dumps(original,sort_keys=True,indent=2).encode(),json.dumps(other,sort_keys=True,indent=2).encode())
|
||||
f.oracle['oracle_provenance']['authority_sha256']=__import__('hashlib').sha256(pair[0]).hexdigest()
|
||||
f.child['summary']['boundary_authority_sha256']=__import__('hashlib').sha256(pair[1]).hexdigest()
|
||||
f.child.update(traces={},state_hashes=None,queues=None);f.child['summary']['diagnostic_mode']='light'
|
||||
return pair
|
||||
|
||||
def test_separately_pinned_ref_light_authorities_allow_only_mode_and_id(self):
|
||||
f=Fixture();pair=self.pair(f)
|
||||
self.assertFalse(f.compare()['pass_all'])
|
||||
result=f.compare(pair);self.assertTrue(result['pass_all'],result['failed_checks'])
|
||||
audit=result['paired_authority_audit'];self.assertTrue(audit['checks']['actual_raw_file_SHA_bound'])
|
||||
self.assertNotEqual(audit['raw_sha256'][0],audit['canonical_sha256'][0])
|
||||
self.assertEqual(audit['common_content_canonical_sha256'][0],audit['common_content_canonical_sha256'][1])
|
||||
|
||||
def test_paired_authority_cannot_change_parent_after_requests_or_registration(self):
|
||||
for key in ('parent','overlay_after','case','registration_sha256','cpu_validation','source_files','frozen_inputs'):
|
||||
with self.subTest(key=key):
|
||||
f=Fixture();pair=self.pair(f,{key:{'different':True}})
|
||||
result=f.compare(pair);self.assertFalse(result['pass_all'])
|
||||
self.assertIn(key,result['paired_authority_audit']['disallowed_different_fields'])
|
||||
|
||||
def test_paired_authority_raw_sha_extra_field_and_duplicate_key_are_rejected(self):
|
||||
f=Fixture();pair=self.pair(f)
|
||||
self.assertFalse(f.compare((pair[0]+b' ',pair[1]))['pass_all'])
|
||||
extra=json.loads(pair[1]);extra['unapproved']=True
|
||||
with self.assertRaisesRegex(ValueError,'exact boundary schema'):f.compare((pair[0],json.dumps(extra).encode()))
|
||||
duplicate=pair[1][:-1]+b',"boundary_id":"duplicate"}'
|
||||
with self.assertRaisesRegex(ValueError,'Duplicate authority'):f.compare((pair[0],duplicate))
|
||||
f=Fixture();f.child['summary']['effective_weights_raw_sha256']='a'*64
|
||||
self.assertFalse(f.compare()['pass_all'])
|
||||
|
||||
|
||||
class CoverageTests(unittest.TestCase):
|
||||
def test_actual_changed_accepted_crossing_witness(self):
|
||||
f=Fixture();result=f.audit();self.assertTrue(result['pass_all'],result['differences'])
|
||||
w=result['coverage']['first_witness'];self.assertEqual(w['global_edge_id'],0)
|
||||
self.assertEqual(w['source_spike_global_tick'],19);self.assertEqual(w['arrival_global_tick'],37)
|
||||
self.assertEqual(w['arrival_child_local_tick'],17);self.assertEqual(w['post_threshold_target_ref'],0)
|
||||
self.assertNotEqual(w['before_weight_f64_le_hex'],w['after_weight_f64_le_hex'])
|
||||
|
||||
def test_fixed18_delay_across_all_nearby_ring_phases(self):
|
||||
for cut in (17,18,19,20,21):
|
||||
with self.subTest(cut=cut):
|
||||
result=Fixture(cut=cut,total=cut+41).audit()
|
||||
self.assertTrue(result['pass_all'],result['differences'])
|
||||
self.assertEqual(result['coverage']['first_witness']['arrival_child_local_tick'],17)
|
||||
|
||||
def test_changed_candidate_without_pending_source_is_incomplete(self):
|
||||
f=Fixture();g=f.graph;g['candidate_edge_id'][0]=2 # source1 never spikes in this fixture
|
||||
_,_,rows,_,after=m._candidates(g['ptr'],g['src'],g['dst'],g['edge_id'],g['base_weights'],g['apl_mask'],
|
||||
g['candidate_edge_id'],g['delta_before'],g['delta_after'],Q)
|
||||
f.child['summary']['effective_weights_raw_sha256']=m._effective_hash(g['base_weights'],g['apl_mask'],rows,after)
|
||||
result=f.audit();self.assertTrue(result['conditional_ref_request_queue_exact'])
|
||||
self.assertEqual(result['changed_effective_numeric_count'],1)
|
||||
self.assertIsNone(result['coverage']['first_witness']);self.assertFalse(result['pass_all'])
|
||||
|
||||
def test_target_spike_same_arrival_tick_rejects_changed_edge(self):
|
||||
f=Fixture(reject=True);result=f.audit()
|
||||
self.assertTrue(result['conditional_ref_request_queue_exact']);self.assertFalse(result['pass_all'])
|
||||
self.assertEqual(result['coverage']['rejected_changed_candidate_crossing_arrivals'],1)
|
||||
self.assertIsNone(result['coverage']['first_witness'])
|
||||
|
||||
def test_zero_delta_and_signed_zero_delta_are_not_changed_edge_coverage(self):
|
||||
for delta in (np.float32(0.),np.float32(-0.)):
|
||||
f=Fixture(delta=delta);result=f.audit()
|
||||
self.assertFalse(result['pass_all']);self.assertEqual(result['changed_effective_numeric_count'],0)
|
||||
self.assertEqual(result['status'],'INCOMPLETE-CHANGED-EDGE-COVERAGE')
|
||||
self.assertEqual(result['changed_delta_bit_count'],1)
|
||||
|
||||
def test_wrong_delta_rejected_against_effective_runtime_hash(self):
|
||||
f=Fixture();f.graph['delta_after'][0]=np.float32(-.003)
|
||||
with self.assertRaisesRegex(ValueError,'effective SHA'):f.audit()
|
||||
|
||||
def test_source_array_shuffle_and_queue_order_shuffle_rejected(self):
|
||||
f=Fixture();f.graph['src'][0],f.graph['src'][2]=f.graph['src'][2],f.graph['src'][0]
|
||||
with self.assertRaisesRegex(ValueError,'CSR ordering'):f.audit()
|
||||
f=Fixture();f.child['queues'][17]['ordered_edge_sha256']='f'*64
|
||||
result=f.audit();self.assertFalse(result['pass_all']);self.assertGreater(result['difference_count'],0)
|
||||
|
||||
def test_wrong_delay_by_one_tick_changes_queue_and_acceptance(self):
|
||||
f=Fixture();f.child['queues'][17],f.child['queues'][18]=f.child['queues'][18],f.child['queues'][17]
|
||||
for t,row in enumerate(f.child['queues']):row['tick']=t
|
||||
self.assertFalse(f.audit()['pass_all'])
|
||||
|
||||
def test_reference_absence_is_incomplete_even_with_computed_witness(self):
|
||||
f=Fixture();f.child.update(traces={},state_hashes=None,queues=None)
|
||||
result=f.audit();self.assertTrue(result['conditional_ref_request_queue_exact'])
|
||||
self.assertIsNotNone(result['coverage']['first_witness']);self.assertFalse(result['accepted_changed_edge_witness_verified'])
|
||||
|
||||
def test_duplicate_or_missing_candidate_and_nonfinite_reject(self):
|
||||
f=Fixture();f.graph['candidate_edge_id'][0]=99
|
||||
with self.assertRaisesRegex(ValueError,'Candidate missing'):f.audit()
|
||||
f=Fixture();f.graph['delta_after'][0]=np.nan
|
||||
with self.assertRaisesRegex(ValueError,'delta after'):f.audit()
|
||||
|
||||
def test_request_acceptance_reconstructed_not_just_copied(self):
|
||||
f=Fixture();f.child['requests'][0,3:]=[0,1]
|
||||
result=f.audit();self.assertFalse(result['pass_all'])
|
||||
self.assertTrue(any(row['field']=='request.acceptance' for row in result['differences']))
|
||||
|
||||
def test_incomplete_summary_is_not_an_array_only_pass(self):
|
||||
f=Fixture();f.child['summary']['complete']=False
|
||||
with self.assertRaisesRegex(ValueError,'summary is incomplete'):f.audit()
|
||||
|
||||
|
||||
class LoaderTests(unittest.TestCase):
|
||||
def test_actual_frozen_loader_accepts_declared_oracle_without_fake_schema(self):
|
||||
f=Fixture()
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root=Path(tmp);r=f.oracle
|
||||
save(root/'summary.json',r['summary']);np.savez_compressed(root/'state.npz',**r['state'])
|
||||
np.savez_compressed(root/'terminal-queues.npz',**r['terminal'])
|
||||
np.save(root/'apl-pending-tail.float32.npy',r['terminal']['apl_pending'])
|
||||
save(root/'apl-timing-audit.json',{'final_apl_state_u32_bits':r['terminal']['apl_state'].view(np.uint32).tolist()})
|
||||
for name,filename in m.C.TRACE_FILES.items():np.save(root/filename,r['traces'][name])
|
||||
for name,rows in (('queue.jsonl',r['queues']),('tick-state-hashes.jsonl',r['state_hashes'])):
|
||||
(root/name).write_text(''.join(json.dumps(row)+'\n' for row in rows),encoding='utf-8')
|
||||
with (root/'requests.csv').open('w',newline='') as stream:
|
||||
writer=csv.writer(stream);writer.writerow(m.C.REQUEST_FIELDS);writer.writerows(r['requests'])
|
||||
np.savez_compressed(root/'boundary-snapshot.npz',**r['boundary_snapshot'])
|
||||
save(root/'boundary-comparison.json',r['boundary_report']);save(root/'oracle-provenance.json',r['oracle_provenance'])
|
||||
loaded=m.load_record(root,kind='oracle')
|
||||
try:
|
||||
self.assertTrue(loaded['summary']['within_trial_weight_updates'])
|
||||
self.assertFalse(loaded['summary']['production_backend'])
|
||||
result=m.compare_boundary(loaded,f.child,parent=f.parent,
|
||||
expected_before_sha256=f.before_sha,expected_after_sha256=f.after_sha)
|
||||
self.assertTrue(result['pass_all'])
|
||||
finally:m.close_record(loaded)
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,331 @@
|
||||
"""Independent CPU tests of the new diagnostic oracle, not GPU evidence.
|
||||
|
||||
AST tests consume the real pinned AJ/C/R source. Tiny tensor/helper doubles
|
||||
exercise switch/installation code without claiming a fullgraph simulation,
|
||||
executing any CUDA kernel, or restoring state as an equivalence oracle.
|
||||
"""
|
||||
import ast
|
||||
import copy
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
import uuid
|
||||
|
||||
import numpy as np
|
||||
|
||||
import boundary_oracle as b
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
AJ = ROOT / 'apl-timing-lab-v1' / 'gpu_timing.py'
|
||||
|
||||
|
||||
def sha(value):
|
||||
return hashlib.sha256(value).hexdigest()
|
||||
|
||||
|
||||
def bits(value):
|
||||
return np.asarray(value).tobytes()
|
||||
|
||||
|
||||
def fixture(tick=41):
|
||||
"""Raw global-phase rings; the live oracle must NOT rotate spike slots."""
|
||||
v = np.array([-.051, -.047], np.float64)
|
||||
g = np.array([-0., .00013], np.float64)
|
||||
ref, counts = np.array([22, 3], np.int32), np.array([5, 2], np.int32)
|
||||
ring = np.zeros((19, 2), np.uint8)
|
||||
ring[(tick - 1) % 19, 0] = 1
|
||||
ring[(tick - 18) % 19, 1] = 1
|
||||
# Distinct samples across every row expose off-by-one and 18/19 confusion.
|
||||
apl_ring = np.arange(36, dtype=np.float32).reshape(18, 2) / np.float32(16)
|
||||
apl_ring[0, 0] = np.float32(-0.)
|
||||
apl_state = np.array([.5, -0.], np.float32)
|
||||
parent = dict(steps=tick, global_next_tick=tick, fresh=True, manifest_sha256='a' * 64,
|
||||
state={key: value.copy() for key, value in zip(('v', 'g', 'ref', 'counts'), (v, g, ref, counts))},
|
||||
terminal=dict(spike_ring=ring.copy(), apl_state=apl_state.copy(),
|
||||
apl_pending=np.concatenate((apl_ring[tick % 18:], apl_ring[:tick % 18])), next_tick=np.asarray(tick, np.int64)))
|
||||
return parent, [v, g, ref, counts, ring, apl_ring, apl_state]
|
||||
|
||||
|
||||
class Tensor:
|
||||
"""NumPy-only tensor double, including assignment accounting."""
|
||||
def __init__(self, value):
|
||||
self.a = np.array(value, copy=True)
|
||||
self.assignments = []
|
||||
|
||||
def cpu(self): return self
|
||||
def numpy(self): return self.a
|
||||
def numel(self): return self.a.size
|
||||
|
||||
def __getitem__(self, key):
|
||||
return Tensor(self.a[key.a if isinstance(key, Tensor) else key])
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
index = key.a if isinstance(key, Tensor) else key
|
||||
self.assignments.append(np.array(index, copy=True))
|
||||
self.a[index] = value.a if isinstance(value, Tensor) else value
|
||||
|
||||
def __add__(self, other): return Tensor(self.a + (other.a if isinstance(other, Tensor) else other))
|
||||
def __mul__(self, other): return Tensor(self.a * other)
|
||||
|
||||
|
||||
class CanonicalEdgeIdentity:
|
||||
"""No actual fullgraph arrays: only the private test's admission double."""
|
||||
def __len__(self): return 25582938
|
||||
def __getitem__(self, key): return np.asarray(key, dtype=np.int64).copy()
|
||||
|
||||
|
||||
class TinyHelper:
|
||||
@staticmethod
|
||||
def map_installation(base, edges, apl_mask, plan):
|
||||
nz = plan['plastic_delta_mv'] != np.float32(0)
|
||||
rows = plan['edge_id'][nz]
|
||||
# Independent frozen bridge expression; do not invoke oracle helper.
|
||||
expected = np.add(base[rows], np.multiply(plan['plastic_delta_mv'][nz].astype(np.float64), np.float64(.001)))
|
||||
return dict(rows=rows, expected_si=expected, missing_candidate_count=0)
|
||||
|
||||
@staticmethod
|
||||
def expected_hashes(base, apl_mask, mapping):
|
||||
result = base.copy()
|
||||
result[mapping['rows']] = mapping['expected_si']
|
||||
return sha(bits(base)), sha(bits(result))
|
||||
|
||||
@staticmethod
|
||||
def bit_equal(a, c):
|
||||
return a.dtype == c.dtype and a.shape == c.shape and a.tobytes() == c.tobytes()
|
||||
|
||||
|
||||
class BoundaryOracleTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Use the actual pinned dependency, with no Torch/CUDA import.
|
||||
cls.c = b.frozen()
|
||||
cls.source = AJ.read_bytes()
|
||||
|
||||
def test_real_AJ_hook_rollback_and_entire_original_functions_identical(self):
|
||||
source_before = sha(self.source)
|
||||
derived, audit = b.derive_oracle(self.c, self.source)
|
||||
old_reference, original_audit = self.c.R.derive_ast(self.source, 'reference')
|
||||
loops = [n for n in ast.walk(derived) if isinstance(n, ast.For) and isinstance(n.target, ast.Name) and n.target.id == 'tick']
|
||||
self.assertEqual(len(loops), 1)
|
||||
self.assertEqual(ast.unparse(loops[0].body[0]), b.HOOK)
|
||||
hookless = copy.deepcopy(derived)
|
||||
loop = next(n for n in ast.walk(hookless) if isinstance(n, ast.For) and isinstance(n.target, ast.Name) and n.target.id == 'tick')
|
||||
del loop.body[0]
|
||||
self.assertEqual(self.c.R._dump(hookless), self.c.R._dump(old_reference))
|
||||
# Independently roll back the inherited R edits as well. This reaches
|
||||
# the ACTUAL frozen AJ functions, not merely the adapter's own receipt.
|
||||
loader, run = hookless.body
|
||||
admission = [n for n in ast.walk(loader) if isinstance(n, ast.Compare) and ast.unparse(n) == "0 < steps <= spec['max_steps']"]
|
||||
self.assertEqual(len(admission), 1)
|
||||
admission[0].comparators[-1] = ast.Constant(value=1000)
|
||||
body = next(n for n in run.body if isinstance(n, ast.Try)).body
|
||||
for text in (self.c.R._INSTALL, self.c.R._FINISH):
|
||||
indices = [i for i, n in enumerate(body) if ast.unparse(n) == text]
|
||||
self.assertEqual(len(indices), 1)
|
||||
del body[indices[0]]
|
||||
originals = ast.parse(self.source)
|
||||
original_module = ast.Module(body=[next(n for n in originals.body if isinstance(n, ast.FunctionDef) and n.name == name)
|
||||
for name in ('load_inputs', 'run_gpu')], type_ignores=[])
|
||||
self.assertEqual(self.c.R._dump(hookless), self.c.R._dump(original_module))
|
||||
self.assertEqual(audit['base'], original_audit)
|
||||
self.assertTrue(audit['full_AST_rollback_identical'])
|
||||
self.assertFalse(audit['restore_called'])
|
||||
self.assertFalse(audit['production_backend'])
|
||||
self.assertEqual(sha(self.source), source_before)
|
||||
compile(derived, '<actual-AJ-oracle-CPU-compile-only>', 'exec')
|
||||
|
||||
def test_oracle_has_one_hook_before_all_frozen_tick_operations_and_no_restore(self):
|
||||
tree, _ = b.derive_oracle(self.c, self.source)
|
||||
loop = next(n for n in ast.walk(tree) if isinstance(n, ast.For) and isinstance(n.target, ast.Name) and n.target.id == 'tick')
|
||||
self.assertEqual(ast.unparse(loop.body[1]), 'requests.zero_()')
|
||||
calls = [ast.unparse(n.func) for n in ast.walk(tree) if isinstance(n, ast.Call)]
|
||||
self.assertEqual(calls.count('_oracle.switch'), 1)
|
||||
self.assertFalse(any('restore' in name for name in calls))
|
||||
self.assertFalse(any(isinstance(n, ast.Name) and n.id == '_continuation' for n in ast.walk(tree)))
|
||||
oracle_class = b.runtime_class(self.c)
|
||||
self.assertIs(oracle_class.__bases__[0], self.c.R._Runtime)
|
||||
self.assertFalse(issubclass(oracle_class, self.c.ContinuedRuntime))
|
||||
self.assertFalse(hasattr(oracle_class, 'restore'))
|
||||
self.assertIn('due = ring[(tick - 18) % 19]', ast.unparse(tree))
|
||||
self.assertIn('slot = tick % apl_delay', ast.unparse(tree))
|
||||
|
||||
def test_real_source_pin_rejects_even_whitespace_drift(self):
|
||||
for changed in (self.source + b'\n', self.source.replace(b'tick >= 18', b'tick >= 17')):
|
||||
with self.assertRaisesRegex(ValueError, 'AJ source pin'):
|
||||
b.derive_oracle(self.c, changed)
|
||||
|
||||
def test_frozen_C_pin_and_existing_module_binding_refuse_before_execution(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
path = Path(tmp) / 'tiny.py'
|
||||
path.write_text('VALUE = 17\n', encoding='utf-8')
|
||||
name = 'boundary_oracle_cpu_fixture_' + uuid.uuid4().hex
|
||||
with self.assertRaisesRegex(ValueError, 'Unverified'):
|
||||
b.load(name, path, '0' * 64)
|
||||
self.assertNotIn(name, sys.modules)
|
||||
try:
|
||||
module = b.load(name, path, b.digest(path))
|
||||
self.assertEqual(module.VALUE, 17)
|
||||
with self.assertRaisesRegex(ValueError, 'Unverified'):
|
||||
b.load(name, path, b.digest(path))
|
||||
self.assertIs(sys.modules[name], module)
|
||||
finally:
|
||||
sys.modules.pop(name, None) # Only this test-created tiny module.
|
||||
frozen_path = Path(tmp) / 'runtime_continuation.py'
|
||||
frozen_path.write_text('raise AssertionError("must not execute")\n', encoding='utf-8')
|
||||
with patch.object(b, 'LAB', Path(tmp)), self.assertRaisesRegex(ValueError, 'Unverified'):
|
||||
b.frozen()
|
||||
|
||||
def test_expected_bridge_is_original_base_plus_widened_after_delta_not_old_effective(self):
|
||||
base = np.array([.000275, .000550, -.00011, .0], np.float64)
|
||||
mask = np.array([0, 1], np.int64)
|
||||
before = np.array([-.00275, -.013125], np.float32)
|
||||
after = np.array([-.0055, -.02125], np.float32)
|
||||
old_effective = base[mask] + before.astype(np.float64) * np.float64(.001)
|
||||
expected = np.add(base[mask], np.multiply(after.astype(np.float64), np.float64(.001)))
|
||||
actual = b.expected_candidate_values(base, mask, after)
|
||||
self.assertEqual(bits(actual), bits(expected))
|
||||
self.assertNotEqual(bits(actual), bits(old_effective + after.astype(np.float64) * np.float64(.001)))
|
||||
self.assertNotEqual(bits(actual), bits(base[mask] + (after * np.float32(.001)).astype(np.float64)))
|
||||
zero = np.array([0., -0.], np.float32)
|
||||
self.assertEqual(bits(b.expected_candidate_values(base, mask, zero)), bits(base[mask]))
|
||||
self.assertEqual(bits(base), bits(np.array([.000275, .000550, -.00011, .0], np.float64)))
|
||||
|
||||
def test_candidate_bridge_rejects_dtype_bounds_order_sign_and_nonfinite(self):
|
||||
base, mask, delta = np.array([.01, .02], np.float64), np.array([0, 1], np.int64), np.array([-.001, -.002], np.float32)
|
||||
cases = [(base.astype(np.float32), mask, delta), (base, mask.astype(np.int32), delta),
|
||||
(base, mask, delta.astype(np.float64)), (base, mask[::-1].copy(), delta),
|
||||
(base, np.array([0, 0], np.int64), delta), (base, np.array([-1, 1], np.int64), delta),
|
||||
(base, np.array([0, 2], np.int64), delta), (base, mask, np.array([np.nan, 0.], np.float32)),
|
||||
(base, mask, np.array([np.inf, 0.], np.float32)), (base, mask, np.array([.01, 0.], np.float32)),
|
||||
(base, mask, np.array([-20., 0.], np.float32)), (np.array([np.inf, .02], np.float64), mask, delta)]
|
||||
for args in cases:
|
||||
with self.subTest(args=[(a.dtype.str, a.tolist()) for a in args]), self.assertRaises(ValueError):
|
||||
b.expected_candidate_values(*args)
|
||||
|
||||
def test_live_raw_boundary_checks_18_and_19_phases_without_rotating_spike_ring(self):
|
||||
for tick in (1, 5, 17, 18, 19, 20, 35, 36, 37, 38, 41, 1200):
|
||||
parent, arrays = fixture(tick)
|
||||
before = [bits(value) for value in arrays]
|
||||
actual, checks = b.boundary_arrays(parent, tick, *arrays)
|
||||
self.assertTrue(all(checks.values()))
|
||||
self.assertEqual(bits(actual['spike_ring']), bits(arrays[4]))
|
||||
order = np.array([(tick + i) % 18 for i in range(18)])
|
||||
self.assertEqual(bits(actual['apl_pending']), bits(arrays[5][order]))
|
||||
self.assertEqual(before, [bits(value) for value in arrays])
|
||||
if tick % 19:
|
||||
wrong = list(arrays); wrong[4] = self.c.rotate_spike_ring(arrays[4], tick)
|
||||
with self.subTest(tick=tick), self.assertRaisesRegex(ValueError, 'spike_ring'):
|
||||
b.boundary_arrays(parent, tick, *wrong)
|
||||
|
||||
def test_boundary_rejects_rawbit_dtype_queue_clock_or_counts_corruption(self):
|
||||
for variant in ('negative_zero_g', 'negative_zero_apl', 'g_dtype', 'v_shape', 'counts', 'spike', 'apl_phase', 'clock', 'continued', 'booltick'):
|
||||
parent, arrays = fixture(41)
|
||||
tick = 41
|
||||
if variant == 'negative_zero_g': arrays[1][0] = 0.
|
||||
if variant == 'negative_zero_apl': arrays[6][1] = np.float32(0.)
|
||||
if variant == 'g_dtype': arrays[1] = arrays[1].astype(np.float32)
|
||||
if variant == 'v_shape': arrays[0] = arrays[0][:-1]
|
||||
if variant == 'counts': arrays[3][0] += 1
|
||||
if variant == 'spike': arrays[4][2, 0] ^= 1
|
||||
if variant == 'apl_phase': arrays[5] = np.roll(arrays[5], 1, axis=0)
|
||||
if variant == 'clock': parent['global_next_tick'] += 1
|
||||
if variant == 'continued': parent['fresh'] = False
|
||||
if variant == 'booltick': tick = True
|
||||
with self.subTest(variant=variant), self.assertRaises(ValueError): b.boundary_arrays(parent, tick, *arrays)
|
||||
|
||||
def runtime_fixture(self, out):
|
||||
parent, arrays = fixture(41)
|
||||
base = np.array([.000275, .000550, -.00011, .0], np.float64)
|
||||
mask = np.array([0, 1], np.int64)
|
||||
old = dict(edge_id=mask, plastic_delta_mv=np.array([-.00275, -.013125], np.float32))
|
||||
new = dict(edge_id=mask, plastic_delta_mv=np.array([-.0055, -.02125], np.float32))
|
||||
helper = TinyHelper()
|
||||
apl_mask = SimpleNamespace(sum=lambda: 5845)
|
||||
prior = helper.map_installation(base, None, apl_mask, old)
|
||||
following = helper.map_installation(base, None, apl_mask, new)
|
||||
before_sha = helper.expected_hashes(base, apl_mask, prior)[1]
|
||||
after_sha = helper.expected_hashes(base, apl_mask, following)[1]
|
||||
parent['summary'] = {'effective_weights_raw_sha256': before_sha}
|
||||
saved = {}
|
||||
# Only these diagnostic I/O and GPU-observer dependencies are doubles;
|
||||
# the actual Oracle install/switch implementation is executed below.
|
||||
r = SimpleNamespace(_Runtime=self.c.R._Runtime, FiniteObserver=lambda *_: object(),
|
||||
_copy_input=lambda *_: None, digest=lambda p: sha(str(p).encode()),
|
||||
_save=lambda p, value: saved.__setitem__(Path(p).name, value))
|
||||
cls = b.runtime_class(SimpleNamespace(R=r))
|
||||
boundary = dict(parent=parent, after_plan=new,
|
||||
value=dict(expected_effective_weight_before_sha256=before_sha, expected_effective_weight_after_sha256=after_sha),
|
||||
paths={key: out / key for key in ('before_overlay', 'before_manifest', 'after_overlay', 'after_manifest')})
|
||||
obj = cls('reference', {'max_steps': 60, 'steps': 60}, helper, old, {}, {},
|
||||
SimpleNamespace(int64=np.int64, float64=np.float64), out / 'old.npz', out / 'old.json', boundary=boundary)
|
||||
weights = Tensor(base)
|
||||
graph = dict(nodes=range(166700), edge_id=CanonicalEdgeIdentity(), weights=base)
|
||||
upload = lambda value, dtype: Tensor(np.asarray(value, dtype=dtype))
|
||||
args = [Tensor(value) for value in arrays[:-1]] + [SimpleNamespace(state=Tensor(arrays[-1]))]
|
||||
return obj, weights, graph, apl_mask, upload, args, saved, base, new
|
||||
|
||||
def test_actual_install_then_one_switch_replaces_base_plus_after_and_never_state_or_queues(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
out = Path(tmp)
|
||||
obj, weights, graph, mask, upload, args, saved, base, new = self.runtime_fixture(out)
|
||||
obj.install(weights, graph, mask, upload, out, {}, 'CPU-double')
|
||||
before = weights.a.copy()
|
||||
state_before = [bits(x.a) for x in args[:-1]] + [bits(args[-1].state.a)]
|
||||
obj.switch(41, weights, *args, out)
|
||||
expected = base.copy()
|
||||
expected[new['edge_id']] = np.add(base[new['edge_id']], np.multiply(new['plastic_delta_mv'].astype(np.float64), np.float64(.001)))
|
||||
self.assertEqual(bits(weights.a), bits(expected))
|
||||
wrong = before.copy(); wrong[new['edge_id']] += new['plastic_delta_mv'].astype(np.float64) * np.float64(.001)
|
||||
self.assertNotEqual(bits(weights.a), bits(wrong))
|
||||
self.assertEqual(bits(weights.a[2:]), bits(before[2:]))
|
||||
self.assertEqual(obj.switches, 1)
|
||||
self.assertEqual(obj.installations, 1)
|
||||
self.assertEqual(state_before, [bits(x.a) for x in args[:-1]] + [bits(args[-1].state.a)])
|
||||
self.assertFalse(saved['boundary-comparison.json']['restore_called'])
|
||||
self.assertFalse(saved['boundary-comparison.json']['queues_replaced'])
|
||||
self.assertEqual(len(weights.assignments), 2) # One old-overlay install, one replacement.
|
||||
with np.load(out / 'boundary-snapshot.npz', allow_pickle=False) as recorded:
|
||||
self.assertEqual(bits(recorded['g']), state_before[1])
|
||||
with self.assertRaisesRegex(ValueError, 'repeated'): obj.switch(41, weights, *args, out)
|
||||
with self.assertRaisesRegex(ValueError, 'one intact'): obj.install(weights, graph, mask, upload, out, {}, 'CPU-double')
|
||||
|
||||
def test_switch_refuses_wrong_time_or_preexisting_weight_state_drift(self):
|
||||
for variant in ('before_install', 'wrong_tick', 'weight_drift', 'state_drift', 'after_hash'):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
out = Path(tmp)
|
||||
obj, weights, graph, mask, upload, args, _, _, _ = self.runtime_fixture(out)
|
||||
obj.install(weights, graph, mask, upload, out, {}, 'CPU-double')
|
||||
tick = 41
|
||||
if variant == 'before_install': obj.installations = 0
|
||||
if variant == 'wrong_tick': tick = 42
|
||||
if variant == 'weight_drift': weights.a[3] = .0001
|
||||
if variant == 'state_drift': args[1].a[0] = 0.
|
||||
if variant == 'after_hash': obj.after_sha = 'f' * 64
|
||||
with self.subTest(variant=variant), self.assertRaises(ValueError): obj.switch(tick, weights, *args, out)
|
||||
self.assertEqual(obj.switches, 0)
|
||||
self.assertFalse((out / 'boundary-snapshot.npz').exists())
|
||||
|
||||
def test_finish_requires_the_boundary_and_summary_discloses_diagnostic_scope(self):
|
||||
cls = b.runtime_class(self.c)
|
||||
obj = object.__new__(cls)
|
||||
obj.switches = 0
|
||||
with self.assertRaisesRegex(ValueError, 'did not execute'): obj.finish()
|
||||
obj.mode = 'reference'; obj.spec = dict(max_steps=100, steps=100)
|
||||
obj.result = {'first_failure_tick': -1}; obj.boundary_tick = 41; obj.switches = 1
|
||||
obj.after_sha = 'a' * 64; obj.before_sha = 'b' * 64
|
||||
result = obj.summary({'complete': True, 'effective_weights_raw_sha256': 'b' * 64, 'learning': False})
|
||||
self.assertTrue(result['within_trial_weight_updates'])
|
||||
self.assertFalse(result['production_backend'])
|
||||
self.assertFalse(result['restored_from_checkpoint'])
|
||||
self.assertFalse(result['learning_pass_claimed'])
|
||||
self.assertEqual(result['effective_weights_raw_sha256'], 'a' * 64)
|
||||
self.assertEqual(result['initial_effective_weights_raw_sha256'], 'b' * 64)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,284 @@
|
||||
"""CPU fixtures and frozen-source checks; never sample or run a brain."""
|
||||
from copy import deepcopy
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
import boundary_plan as B
|
||||
|
||||
|
||||
SOURCE = Path(__file__).resolve().parent.parent
|
||||
EVIDENCE = SOURCE.parent / 'reports/phase4ap-publication/evidence'
|
||||
if not EVIDENCE.is_dir():
|
||||
EVIDENCE = SOURCE.parents[1] / 'registry/phase4ap-conditioning-interface-v2/evidence'
|
||||
OUTPUT_ROOT = '/data/digital-drosophila/experiments/boundary-plan-fixture'
|
||||
|
||||
|
||||
def load_source(name, path):
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
class BoundaryPlanTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.template = json.loads((EVIDENCE / 'cases/D1--reference--epoch-001/spec.json').read_text())
|
||||
cls.registry = load_source('boundary_test_seed_registry', SOURCE/'olfactory-conditioning-lab-v1/seed_registry.py')
|
||||
with patch.dict(sys.modules, {'seed_registry': cls.registry}):
|
||||
cls.trial_plan = load_source('boundary_test_trial_plan', SOURCE/'olfactory-conditioning-lab-v1/trial_plan.py')
|
||||
|
||||
def setUp(self):
|
||||
self.plan = B.build_plan()
|
||||
self.calls = {c['call_id']: c for c in self.plan['calls']}
|
||||
|
||||
def spec(self, call):
|
||||
return B.derive_case_spec(self.template, call, budget_root=OUTPUT_ROOT)
|
||||
|
||||
def test_source_protocol_and_template_pins_match_actual_local_bytes(self):
|
||||
for path, pin in B.SOURCE_PINS.items():
|
||||
self.assertEqual(hashlib.sha256((SOURCE/path).read_bytes()).hexdigest(), pin, path)
|
||||
for path, pin in B.AP_ANCHORS.items():
|
||||
self.assertEqual(hashlib.sha256((EVIDENCE/path).read_bytes()).hexdigest(), pin, path)
|
||||
for arm, pin in B.PARENT_PINS.items():
|
||||
raw = (EVIDENCE/f'runs/{arm}--reference--epoch-001/checkpoint-manifest.json').read_bytes()
|
||||
self.assertEqual(hashlib.sha256(raw).hexdigest(), pin)
|
||||
self.assertEqual(B._sha(self.template), B.TEMPLATE_PAYLOAD_SHA256)
|
||||
|
||||
def test_exact_inventory_ticks_children_and_no_execution_claim(self):
|
||||
self.assertTrue(B.validate_plan(self.plan))
|
||||
self.assertEqual(len(self.calls), 23)
|
||||
self.assertEqual(sum(c['steps'] for c in self.calls.values()), 125200)
|
||||
self.assertEqual(len({c['case_group'] for c in self.calls.values()}), 17)
|
||||
self.assertEqual(len(self.plan['imported_parents']), 3)
|
||||
self.assertEqual(len(self.plan['cpu_children']), 7)
|
||||
self.assertEqual(self.plan['counts']['total_children'], 23+7+1)
|
||||
self.assertEqual(self.plan['sampler_child']['uniform_batch_calls'], 2)
|
||||
self.assertEqual(self.plan['sampler_child']['execution'], 'GPU_private_generator')
|
||||
self.assertIsNone(self.plan['counts']['raw_uniform_draw_count'])
|
||||
for key in ('brain_executed', 'inputs_sampled', 'acquisition_executed', 'full_retention_experiment',
|
||||
'scientific_learning_claimed', 'external_identity_verified_here', 'execution_authorized'):
|
||||
self.assertIs(self.plan[key], False)
|
||||
|
||||
def test_plan_reconstruction_rejects_mutations_including_booleans(self):
|
||||
mutations = [lambda p: p['calls'][0].update(steps=999),
|
||||
lambda p: p['counts'].update(new_brain_calls=20),
|
||||
lambda p: p['calls'][-1].update(parent='D1--probe--t1--A'),
|
||||
lambda p: p['calls'][-1].update(neural_reset=True),
|
||||
lambda p: p['calls'][2].update(overlay_before_role='AP.initial_overlay'),
|
||||
lambda p: p['mechanical_update'].update(trace_backend='numpy'),
|
||||
lambda p: p['source_sha256'].update({'conditioning-interface-v2/PROTOCOL.md': 'a'*64}),
|
||||
lambda p: p.update(execution_authorized=0)]
|
||||
for mutate in mutations:
|
||||
plan = deepcopy(self.plan)
|
||||
mutate(plan)
|
||||
with self.assertRaises(ValueError):
|
||||
B.validate_plan(plan)
|
||||
|
||||
def test_seeds_are_exact_existing_evaluation_streams_not_training_streams(self):
|
||||
streams = B.evaluation_seeds()
|
||||
for cue, row in streams.items():
|
||||
key = self.trial_plan._input_key(B.BLOCK, 'evaluation', cue, 0, 'base-probe')
|
||||
seed, digest = self.registry.seed_for(B.MASTER, 'evaluation', key)
|
||||
self.assertEqual(row['key'], list(key))
|
||||
self.assertEqual((row['seed'], row['derivation_sha256']), (seed, digest))
|
||||
self.assertEqual(row['stream_id'], self.trial_plan._stream_id(B.MASTER, 'evaluation', key))
|
||||
train_seed, _ = self.registry.seed_for(B.MASTER, 'training', key)
|
||||
self.assertNotEqual(seed, train_seed)
|
||||
self.assertGreater(seed, 2**32)
|
||||
self.assertLess(seed, 2**63)
|
||||
self.assertEqual({self.spec(f'D1--probe--{t}--{cue}')['cs_input_seed'] for t in ('t0','t1','t10')}, {seed})
|
||||
self.assertNotEqual(streams['A']['seed'], streams['B']['seed'])
|
||||
|
||||
def test_plan_and_derivation_never_sample(self):
|
||||
with patch('numpy.random.default_rng', side_effect=AssertionError('sampling forbidden')), \
|
||||
patch('numpy.random.uniform', side_effect=AssertionError('sampling forbidden')):
|
||||
B.build_plan()
|
||||
B.evaluation_seeds()
|
||||
for call in self.calls:
|
||||
self.spec(call)
|
||||
|
||||
def test_continuous_idle_clock_and_probe_fork_no_feedback(self):
|
||||
first, second = self.calls['D1--idle--1s'], self.calls['D1--idle--9s']
|
||||
self.assertEqual((first['steps'], first['global_tick_offset'], first['global_next_tick']), (10000,1200,11200))
|
||||
self.assertEqual((second['steps'], second['global_tick_offset'], second['global_next_tick']), (90000,11200,101200))
|
||||
self.assertEqual(second['parent'], first['call_id'])
|
||||
self.assertEqual((first['transition'], second['transition']), ('epoch_update','idle'))
|
||||
for t, parent, tick in (('t0','AP.D1.reference.epoch001',1200),
|
||||
('t1',first['call_id'],11200), ('t10',second['call_id'],101200)):
|
||||
for cue in ('A','B'):
|
||||
probe = self.calls[f'D1--probe--{t}--{cue}']
|
||||
self.assertEqual((probe['parent'],probe['global_tick_offset'],probe['steps']), (parent,tick,1200))
|
||||
self.assertTrue(probe['probe_fork_discard'])
|
||||
for key in ('feedback_to_idle','neural_reset','US','plastic_update'):
|
||||
self.assertIs(probe[key], False)
|
||||
self.assertFalse(any('--probe--' in (c['parent'] or '') for c in self.calls.values()))
|
||||
|
||||
def test_template_keydiff_preserves_model_APL_delay_and_reset(self):
|
||||
saved = deepcopy(self.template)
|
||||
for name in self.calls:
|
||||
spec = self.spec(name)
|
||||
common = set(spec) & set(saved)
|
||||
changed = {key for key in common if spec[key] != saved[key]}
|
||||
self.assertLessEqual(changed, B.CASE_CHANGED_KEYS | B.STALE_INPUT_KEYS)
|
||||
self.assertLessEqual(set(spec)-set(saved), B.CASE_ADDED_KEYS)
|
||||
self.assertLessEqual(set(saved)-set(spec), B.STALE_INPUT_KEYS)
|
||||
for key in ('model','apl','apl_delay_steps','apl_precision','precision','seed','dt_ms',
|
||||
'graph_dir','apl_bundle_dir','coefficients_path','legacy_apl_worker','kind'):
|
||||
self.assertEqual(spec[key], saved[key], (name,key))
|
||||
self.assertEqual(spec['max_steps'], spec['steps'])
|
||||
self.assertEqual(spec['duration_ms'], spec['steps'] * saved['dt_ms'])
|
||||
self.assertEqual(self.template, saved)
|
||||
|
||||
def test_shared_ref_light_oldC_case_groups_produce_identical_specs(self):
|
||||
for arm in ('D1','D0','frozen','mechanical'):
|
||||
ref = self.spec(f'{arm}--updated--reference')
|
||||
self.assertEqual(ref, self.spec(f'{arm}--updated--light'))
|
||||
if arm != 'mechanical':
|
||||
self.assertEqual(ref['name'], f'AP-{arm}-suffix')
|
||||
if arm in ('D0','frozen'):
|
||||
self.assertEqual(ref, self.spec(f'{arm}--old-C--reference'))
|
||||
|
||||
def test_nonolfactory_cases_remove_stale_odor_metadata(self):
|
||||
for name, call in self.calls.items():
|
||||
spec = self.spec(name)
|
||||
if 'cue' not in call:
|
||||
self.assertTrue(B.STALE_INPUT_KEYS.isdisjoint(spec), name)
|
||||
else:
|
||||
for key in ('odor_id','rate_sum_hz','source_panel_row','source_panel_split','target_count','expected_CS_requests'):
|
||||
self.assertNotIn(key, spec)
|
||||
self.assertEqual(spec['CS_window'], [0,1000])
|
||||
|
||||
def test_oracle_is_fresh_diagnostic_one_switch_not_restore(self):
|
||||
for arm in ('D1','mechanical'):
|
||||
row = self.calls[f'{arm}--live-oracle']
|
||||
spec = self.spec(row['call_id'])
|
||||
self.assertIsNone(row['parent'])
|
||||
self.assertEqual(row['steps'], 2200)
|
||||
self.assertEqual(row['global_tick_offset'], 0)
|
||||
self.assertIs(row['restore_used'], False)
|
||||
self.assertIs(spec['within_trial_weight_updates'], True)
|
||||
self.assertEqual(spec['diagnostic_boundary_tick'], 1200)
|
||||
self.assertIs(spec['scientific_learning_claimed'], False)
|
||||
self.assertEqual(self.calls['D1--live-oracle']['overlay_before_role'], 'AP.D1.reference.epoch001.recorded_overlay')
|
||||
for name, row in self.calls.items():
|
||||
if row['runner'] != 'boundary_oracle':
|
||||
self.assertIs(self.spec(name)['within_trial_weight_updates'], False)
|
||||
|
||||
def test_mechanical_before_is_registration_original_zero_not_D0_output(self):
|
||||
registration = json.loads((EVIDENCE/'protocol/preregistered.json').read_text())
|
||||
initial = self.plan['initial_overlay']
|
||||
self.assertEqual(initial['role'], 'AP.initial_overlay')
|
||||
for role in ('overlay_file','overlay_manifest'):
|
||||
self.assertEqual(initial[role]['path'], registration['initial_overlay'][role])
|
||||
self.assertEqual(initial[role]['sha256'], registration['input_sha256'][initial[role]['path']])
|
||||
self.assertEqual(self.calls['mechanical--fresh-parent']['overlay_after_role'], initial['role'])
|
||||
self.assertFalse(self.calls['mechanical--fresh-parent']['inherited_learned_delta'])
|
||||
update = self.plan['mechanical_update']
|
||||
self.assertEqual((update['steps'],update['us_tick'],update['d_command'],update['trace_backend']), (1200,1199,1.0,'torch'))
|
||||
self.assertEqual(update['before_overlay_role'], initial['role'])
|
||||
|
||||
def test_template_drift_unknown_calls_and_bad_output_roots_rejected(self):
|
||||
wrong = deepcopy(self.template)
|
||||
wrong['model']['threshold_mv'] = -44.0
|
||||
with self.assertRaises(ValueError):
|
||||
B.derive_case_spec(wrong,'D1--updated--reference',budget_root=OUTPUT_ROOT)
|
||||
with self.assertRaises(ValueError):
|
||||
self.spec('unregistered-extra-call')
|
||||
for root in ('relative','/',B.AP_ROOT,B.AP_ROOT+'/child','/data','/tmp/../test'):
|
||||
with self.assertRaises(ValueError):
|
||||
B.derive_case_spec(self.template,'D1--updated--reference',budget_root=root)
|
||||
|
||||
def test_budgets_are_fixed_stop_proposals_not_trial_shortening(self):
|
||||
budget = self.plan['budget_proposal']
|
||||
self.assertEqual((budget['output_bytes'],budget['free_reserve_bytes']), (4*2**30,10*2**30))
|
||||
self.assertEqual((budget['child_timeout_seconds'],budget['workflow_timeout_seconds']), (1800,7200))
|
||||
self.assertFalse(budget['approved'])
|
||||
self.assertIn('never_shorten_trial_or_change_gate', budget['on_limit'])
|
||||
|
||||
def test_performance_slot_replays_natural_AP_input_with_full_fresh_cycle(self):
|
||||
row = self.calls['performance--natural-light-fresh']
|
||||
self.assertEqual((row['diagnostic_mode'],row['steps'],row['global_tick_offset']), ('light',1200,0))
|
||||
self.assertIsNone(row['parent'])
|
||||
self.assertEqual(row['input_policy'],'replay_AP_D1_epoch001_input')
|
||||
self.assertEqual(row['overlay_after_role'],'AP.D1.reference.epoch001.recorded_overlay')
|
||||
self.assertFalse(row['new_learning'])
|
||||
self.assertFalse(row['input_sampled'])
|
||||
update = self.plan['performance_update']
|
||||
self.assertEqual((update['us_tick'],update['d_command'],update['trace_backend']), (900,1.0,'torch'))
|
||||
self.assertEqual(update['required_regression'],['all_events','final_state','delta_after'])
|
||||
names = list(self.calls)
|
||||
self.assertLess(names.index(row['call_id']), names.index('mechanical--fresh-parent'))
|
||||
|
||||
def test_fresh_performance_probe_is_not_retention_continuation(self):
|
||||
name = 'performance--evaluation-A-light-fresh'
|
||||
row = self.calls[name]
|
||||
self.assertEqual((row['runner'],row['steps'],row['global_tick_offset']), ('fresh_probe',1200,0))
|
||||
self.assertEqual(row['diagnostic_mode'],'light')
|
||||
self.assertIsNone(row['parent'])
|
||||
self.assertTrue(row['neural_reset'])
|
||||
self.assertEqual(row['overlay_after_role'],'AP.initial_overlay')
|
||||
for key in ('US','plastic_update','feedback_to_idle'):
|
||||
self.assertIs(row[key],False)
|
||||
spec = self.spec(name)
|
||||
self.assertEqual(spec['cs_input_seed'],B.evaluation_seeds()['A']['seed'])
|
||||
self.assertNotIn('parent_checkpoint_manifest_sha256',spec)
|
||||
names = list(self.calls)
|
||||
self.assertEqual(names.index(name),names.index('performance--natural-light-fresh')+1)
|
||||
self.assertNotEqual(row['case_group'],self.calls['D1--probe--t0--A']['case_group'])
|
||||
|
||||
|
||||
class MechanicalRequestTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.mapping = dict(edge_id=np.arange(B.CANDIDATES,dtype=np.int64),
|
||||
source_neuron_idx=np.full(B.CANDIDATES,33,dtype=np.int32),
|
||||
target_neuron_idx=np.full(B.CANDIDATES,900,dtype=np.int32),
|
||||
target_compartment_verbatim=np.full(B.CANDIDATES,'other',dtype='U8'))
|
||||
self.mapping['target_compartment_verbatim'][[4,700]] = B.COMPARTMENT
|
||||
self.mapping['source_neuron_idx'][[0,4,700]] = [1,21,7]
|
||||
self.dan = np.array([101,102,104,108],dtype=np.int32)
|
||||
self.binding = dict(candidate_map_sha256='1'*64,pam15_membership_sha256='2'*64)
|
||||
|
||||
def run_request(self):
|
||||
return B.mechanical_requests(self.mapping,self.dan,identity_binding=self.binding)
|
||||
|
||||
def test_single_minimum_matching_KC_plus_four_DAN_last_tick(self):
|
||||
before = {key:a.copy() for key,a in self.mapping.items()}
|
||||
request, audit = self.run_request()
|
||||
np.testing.assert_array_equal(request['tick'], np.full(5,1199,dtype=np.int32))
|
||||
np.testing.assert_array_equal(request['neuron_idx'], np.array([7,101,102,104,108],dtype=np.int32))
|
||||
self.assertEqual(audit['selected_KC_source_neuron_idx'], 7)
|
||||
self.assertFalse(audit['external_identity_verified_here'])
|
||||
self.assertFalse(audit['accepted_spikes_verified'])
|
||||
self.assertFalse(audit['olfactory_input'])
|
||||
for key in self.mapping:
|
||||
np.testing.assert_array_equal(self.mapping[key],before[key])
|
||||
self.dan[0] = 100
|
||||
self.assertEqual(request['neuron_idx'][1],101)
|
||||
|
||||
def test_array_and_identity_schema_mutations_fail_closed(self):
|
||||
mutations = [lambda: self.mapping.update(edge_id=self.mapping['edge_id'].astype(np.int32)),
|
||||
lambda: self.mapping['edge_id'].__setitem__(1,0),
|
||||
lambda: self.mapping.update(source_neuron_idx=self.mapping['source_neuron_idx'][:-1]),
|
||||
lambda: self.mapping['source_neuron_idx'].__setitem__(0,-1),
|
||||
lambda: self.mapping['target_compartment_verbatim'].__setitem__(slice(None),'y5B2a'),
|
||||
lambda: setattr(self,'dan',self.dan.astype(np.int64)),
|
||||
lambda: self.dan.__setitem__(1,101),
|
||||
lambda: setattr(self,'dan',self.dan[::-1]),
|
||||
lambda: self.dan.__setitem__(0,7),
|
||||
lambda: self.binding.update(pam15_membership_sha256='not-authenticated')]
|
||||
for mutation in mutations:
|
||||
self.setUp()
|
||||
mutation()
|
||||
with self.assertRaises(ValueError):
|
||||
self.run_request()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,82 @@
|
||||
"""Source/API and synthetic orchestration tests; never actual CUDA sampling."""
|
||||
import copy
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import tempfile
|
||||
import types
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
import boundary_sampler as S
|
||||
|
||||
|
||||
class SamplerTests(unittest.TestCase):
|
||||
def test_actual_frozen_dependency_pins(self):
|
||||
for name,sha in S.PINS.items():
|
||||
with self.subTest(name=name):self.assertEqual(S.A.digest(S.LAB/name),sha)
|
||||
|
||||
def test_real_sampler_signature_lazy_GPU_and_request_window(self):
|
||||
raw=(S.LAB/'conditioning_inputs.py').read_bytes()
|
||||
module=types.ModuleType('_ci_cpu_fixture');exec(compile(raw,str(S.LAB/'conditioning_inputs.py'),'exec'),module.__dict__)
|
||||
import inspect
|
||||
self.assertEqual(list(inspect.signature(module.generate_cs_requests).parameters),
|
||||
['targets','rates_hz','seed','steps','cs_start_tick','cs_stop_tick','device','max_uniform_draws','dt_ms'])
|
||||
targets=np.array([5,2],np.int32);forced=np.ones((1200,2),np.bool_)
|
||||
result=module.requests_from_forced(forced,targets,cs_start_tick=0,cs_stop_tick=1000)
|
||||
self.assertEqual(len(result['requests']['tick']),2000)
|
||||
self.assertEqual(int(result['requests']['tick'].max()),999)
|
||||
self.assertTrue(np.array_equal(result['requests']['neuron_idx'][:2],np.array([2,5],np.int32)))
|
||||
|
||||
def run_fixture(self,*,mutate_seed=False):
|
||||
"""Fake sampler is intentionally NOT a stochastic or neural validation."""
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
root=Path(td).resolve();(root/'protocol').mkdir();(root/'inputs/static').mkdir(parents=True);(root/'runs').mkdir()
|
||||
regfile=root/'protocol/preregistered.json';full=root/'full.json';full.write_text('{}')
|
||||
plan=S.PLAN.build_plan();tables={};streams={};calls=[]
|
||||
for cue in ('A','B'):
|
||||
tables[cue]=dict(targets=np.array([5,2],np.int32),rates_hz=np.array([10.,20.],np.float32))
|
||||
with (root/f'inputs/static/{cue}-rates.npz').open('wb') as f:np.savez(f,**tables[cue])
|
||||
stream=copy.deepcopy(plan['evaluation_streams'][cue]);stream['semantic_key']=stream.pop('key')
|
||||
if mutate_seed and cue=='B':stream['seed']+=1
|
||||
streams[(S.PLAN.BLOCK,cue)]=stream
|
||||
reg=dict(schema='conditioning-execution-registration-v1',plan=plan,source_sha256={},prepared_file_sha256={},
|
||||
input_sha256={str(S.LAB/n):sha for n,sha in S.PINS.items()},original_full_plan=S.A.pin(full))
|
||||
regfile.write_text(json.dumps(reg))
|
||||
ci=types.ModuleType('conditioning_inputs');i=types.ModuleType('conditioning_preflight_inputs');ep=types.ModuleType('evaluation_plan')
|
||||
i.load_rate_tables=lambda root:dict(tables=tables)
|
||||
ep._streams=lambda full:streams
|
||||
def generate(targets,rates,**kw):
|
||||
calls.append(kw)
|
||||
self.assertEqual(kw['steps'],1200);self.assertEqual(kw['cs_start_tick'],0)
|
||||
self.assertEqual(kw['cs_stop_tick'],1000);self.assertEqual(kw['max_uniform_draws'],2400)
|
||||
return dict(requests=dict(tick=np.array([0,999],np.int32),neuron_idx=np.array([2,5],np.int32)),audit={'synthetic_fixture':True})
|
||||
ci.generate_cs_requests=generate
|
||||
real_import=__import__
|
||||
def intercepted(name,*args,**kwargs):
|
||||
if name in ('conditioning_inputs','conditioning_preflight_inputs','evaluation_plan'):
|
||||
return {'conditioning_inputs':ci,'conditioning_preflight_inputs':i,'evaluation_plan':ep}[name]
|
||||
return real_import(name,*args,**kwargs)
|
||||
old_path=list(sys.path)
|
||||
try:
|
||||
with patch('builtins.__import__',side_effect=intercepted):
|
||||
result=S.run(regfile,S.A.digest(regfile),root/'runs/generated')
|
||||
self.assertEqual(len(calls),2);self.assertNotEqual(calls[0]['seed'],calls[1]['seed'])
|
||||
self.assertEqual(result['uniform_draws'],4800);self.assertFalse(result['brain_executed'])
|
||||
self.assertFalse(result['reuse_executed_here']);self.assertFalse(result['US_added'])
|
||||
self.assertEqual(set(result['files_sha256']),{'A-requests.npz','A-sampler.json','B-requests.npz','B-sampler.json'})
|
||||
with patch('builtins.__import__',side_effect=intercepted):
|
||||
with self.assertRaisesRegex(ValueError,'Exclusive new sampler'):S.run(regfile,S.A.digest(regfile),root/'runs/generated')
|
||||
return result
|
||||
finally:sys.path[:]=old_path
|
||||
|
||||
def test_only_two_fixed_batches_and_honest_scope(self):self.run_fixture()
|
||||
|
||||
def test_wrong_full_semantic_seed_rejected(self):
|
||||
with self.assertRaisesRegex(ValueError,'Evaluation semantic stream differs'):self.run_fixture(mutate_seed=True)
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,213 @@
|
||||
"""Small synthetic filesystem receipts; these are NOT real cost measurements."""
|
||||
from copy import deepcopy
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
import boundary_plan as P
|
||||
import budget_report as R
|
||||
|
||||
|
||||
class BudgetReportTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp=tempfile.TemporaryDirectory();self.addCleanup(self.tmp.cleanup)
|
||||
self.root=Path(self.tmp.name);self.exp=self.root/'phase4-fixture';self.model=self.root/'model'
|
||||
for name in ('audit','receipts','jobs','logs','runs','updates','authorities','cases','protocol','extension-build'):
|
||||
(self.exp/name).mkdir(parents=True,exist_ok=True)
|
||||
self.model.mkdir();self.worker=self.model/'isolated_execution.py';self.ap=self.model/'ap_worker.py'
|
||||
for path in (self.worker,self.ap,self.model/'runtime_light.py',self.model/'runtime_continuation.py',self.model/'conditioning_epoch.py'):
|
||||
path.write_text('# CPU fixture '+path.name,encoding='utf-8')
|
||||
self.patch('EXP',self.exp);self.patch('MODEL',self.model);self.patch('AP_WORKER',self.ap)
|
||||
p=patch.object(R.F.W,'AP_SHA',R.A.digest(self.ap));p.start();self.addCleanup(p.stop)
|
||||
self.plan=P.build_plan();self.calls={c['call_id']:c for c in self.plan['calls']}
|
||||
self.zero=self.exp/'protocol/zero.npz';R.F.save_npz(self.zero,dict(delta=np.array([0.],np.float32)))
|
||||
self.reg=dict(plan=self.plan,source_sha256={str(self.worker):R.A.digest(self.worker)},
|
||||
initial_overlay=dict(overlay_file=str(self.zero),overlay_manifest=str(self.zero)),
|
||||
input_sha256={},prepared_file_sha256={})
|
||||
R.F.save(self.exp/'protocol/preregistered.json',self.reg);self.regsha=R.A.digest(self.exp/'protocol/preregistered.json')
|
||||
p=patch.object(R.F,'registration',side_effect=self.registration);p.start();self.addCleanup(p.stop)
|
||||
self.specs={};self.processes={};self.cycle_times={}
|
||||
self.put(self.exp/'extension-build/kernel.bin','actual-fixture-cache')
|
||||
for index,call in enumerate(self.plan['calls']):
|
||||
name=call['call_id'];start=(index+1)*100.;self.cycle_times[name]=(start,start+40.)
|
||||
if call['runner'] in ('runtime_light','fresh_probe'):
|
||||
case=self.exp/'cases'/name;case.mkdir()
|
||||
spec=dict(steps=call['steps'],dt_ms=.1,model=dict(frozen_fixture=True),apl=dict(gain=.01),
|
||||
precision='float64',apl_precision='float32',apl_delay_steps=18,
|
||||
graph_dir='pinned-fullgraph-fixture',apl_bundle_dir='pinned-APL-fixture')
|
||||
R.F.save(case/'spec.json',spec)
|
||||
R.F.save_npz(case/'requests.npz',dict(tick=np.array([5],np.int32),neuron_idx=np.array([20],np.int32)))
|
||||
self.specs[name]=case
|
||||
self._epoch(R.TRAIN);self._epoch('mechanical--fresh-parent')
|
||||
for arm in ('D1','D0','frozen'):self._process('AP-'+arm+'--cpu-verify','validate_cpu',10.)
|
||||
for call in self.plan['calls']:
|
||||
name=call['call_id'];start=self.cycle_times[name][0]
|
||||
kind={'runtime_light':'brain','fresh_probe':'brain','runtime_continuation':'unchanged',
|
||||
'updated_continuation':'updated','boundary_oracle':'oracle'}[call['runner']]
|
||||
self._process(name,kind,start+1)
|
||||
if name in (R.TRAIN,'mechanical--fresh-parent'):
|
||||
self._process(name+'--original-E','update',start+11,base=name)
|
||||
self._process(name+'--cpu-verify','validate_cpu',start+21,base=name)
|
||||
self._process('evaluation-inputs','sample',self.cycle_times[R.TRAIN][1]+10)
|
||||
build=R.F.tree(self.exp/'extension-build')
|
||||
for call in self.plan['calls']:
|
||||
name=call['call_id'];start,end=self.cycle_times[name]
|
||||
rows=[self.processes[event] for _,event in R.SELECTED[name]] if name in R.SELECTED else []
|
||||
inventory=R._cycle_files(name,rows,R.Evidence()) if rows else {}
|
||||
value=dict(call=call,complete=True,start_monotonic=start,end_monotonic=end,wall_seconds=end-start,
|
||||
output_inventory=inventory,output_bytes=sum(v['bytes'] for v in inventory.values()),
|
||||
mutable_build_inventory_before=build,mutable_build_inventory_after=build,
|
||||
mutable_build_bytes_before=sum(v['bytes'] for v in build.values()),
|
||||
mutable_build_bytes_after=sum(v['bytes'] for v in build.values()),
|
||||
source_registration_sha256=self.regsha,learning_pass_claimed=False)
|
||||
R.F.save(self.exp/'receipts'/f'{name}.cycle.json',value)
|
||||
R.F.save(self.exp/'audit/execution-attempt.json',dict(registration_sha256=self.regsha,monotonic_origin=1.))
|
||||
R.F.save(self.exp/'audit/execution-complete.json',dict(complete=True,registration_sha256=self.regsha,
|
||||
scientific_learning_pass_claimed=False,completed_calls=[c['call_id'] for c in self.plan['calls']],
|
||||
processes={name:str(self.exp/'receipts'/f'{name}.process.json') for name in self.processes}))
|
||||
|
||||
def patch(self,key,value):
|
||||
p=patch.object(R.F,key,value);p.start();self.addCleanup(p.stop)
|
||||
|
||||
def registration(self,sha):
|
||||
R.require(sha==R.A.digest(self.exp/'protocol/preregistered.json'),'Registration differs')
|
||||
return self.reg
|
||||
|
||||
def put(self,path,text):
|
||||
Path(path).write_text(text,encoding='utf-8')
|
||||
|
||||
def rewrite(self,path,mutate):
|
||||
value=R.A.read(path);mutate(value)
|
||||
self.put(path,json.dumps(value,sort_keys=True,allow_nan=False))
|
||||
|
||||
def _epoch(self,name):
|
||||
R.F.save(self.exp/'authorities'/f'{name}.epoch.json',dict(checkpoint_dir=str(self.exp/'runs'/name),
|
||||
command=dict(steps=1200,compartment="y5B'2a",us_tick=900 if name==R.TRAIN else 1199,
|
||||
d_command=1.,frozen=False,trace_backend='torch')))
|
||||
|
||||
def _process(self,name,kind,start,base=None):
|
||||
ap=kind in ('brain','update');script=self.ap if ap else self.worker
|
||||
output=self.exp/('updates' if kind=='update' else 'runs')/(base if kind=='update' else name);output.mkdir()
|
||||
sources={role:dict(path=str(self.model/(role+'.py')),sha256=R.A.digest(self.model/(role+'.py')))
|
||||
for role in (('runtime_light','runtime_continuation') if kind=='brain' else ('conditioning_epoch',))} if ap else {}
|
||||
job=dict(job_id=name,kind=kind,registration_sha256=self.regsha,worker_sha256=R.A.digest(script),
|
||||
receipt_file=str(self.exp/'receipts'/f'{name}.worker.json'),output_dir=str(output),
|
||||
input_sha256={str(self.exp/'protocol/preregistered.json'):self.regsha},sources=sources,source_sha256={})
|
||||
result={};environment=dict(gpu_uuid='FIXTURE',python_version='fixture',torch_version='fixture')
|
||||
if kind=='brain':
|
||||
job.update(case_dir=str(self.specs[name]),diagnostic_mode=self.calls[name]['diagnostic_mode'],overlay_file=str(self.zero))
|
||||
summary=dict(steps=1200,completed_ticks=1200,explicit_steps_executed=1200,max_steps=1200,nodes=R.B.N,edges=R.B.E,
|
||||
diagnostic_mode=job['diagnostic_mode'],entire_neural_trial_executed=True,within_trial_weight_updates=False,
|
||||
precision='float64',apl_precision='float32')
|
||||
R.F.save(output/'summary.json',summary);result['complete_fresh_trial']=True
|
||||
elif kind=='sample':
|
||||
for cue in ('A','B'):
|
||||
R.F.save_npz(output/f'{cue}-requests.npz',dict(tick=np.array([5],np.int32),neuron_idx=np.array([20],np.int32)))
|
||||
else:R.F.save(output/'fixture.json',dict(complete=True))
|
||||
if base:
|
||||
job.update(authority_file=str(self.exp/'authorities'/f'{base}.epoch.json'))
|
||||
if kind=='validate_cpu':job['update_dir']=str(self.exp/'updates'/base)
|
||||
jobpath=self.exp/'jobs'/f'{name}.json';R.F.save(jobpath,job);jobsha=R.A.digest(jobpath)
|
||||
expected={**job['input_sha256'],str(jobpath):jobsha,str(script):job['worker_sha256']}
|
||||
if ap:expected.update({v['path']:v['sha256'] for v in sources.values()})
|
||||
else:expected[str(self.ap)]=R.F.W.AP_SHA
|
||||
logs={}
|
||||
for side in ('stdout','stderr'):
|
||||
path=self.exp/'logs'/f'{name}.{side}.log';self.put(path,'');logs[side+'_sha256']=R.A.digest(path)
|
||||
attempt=self.exp/'receipts'/f'{name}.worker.json.attempt.json';R.F.save(attempt,dict(fixture=True))
|
||||
inventory=R.F.tree(output);hashes={k:v['sha256'] for k,v in inventory.items()}
|
||||
worker=dict(schema='phase4ap-isolated-worker-receipt-v1' if ap else 'conditioning-isolated-execution-receipt-v1',
|
||||
complete=True,job_id=name,kind=kind,registration_sha256=self.regsha,worker_sha256=job['worker_sha256'],
|
||||
job_sha256=jobsha,attempt_sha256=R.A.digest(attempt),output_dir=str(output),output_files_sha256=hashes,
|
||||
environment=environment,result=result,wall_seconds=2.)
|
||||
worker['verified_input_sha256' if ap else 'input_sha256']=expected
|
||||
workerpath=Path(job['receipt_file']);R.F.save(workerpath,worker)
|
||||
command=['fixture-python','-B',str(script)]+([kind] if ap else [])+['--job',str(jobpath),'--job-sha256',jobsha]
|
||||
process=dict(schema='conditioning-execution-process-v1',complete=True,name=name,kind=kind,
|
||||
registration_sha256=self.regsha,exit_code=0,timed_out=False,job_sha256=jobsha,argv=command,
|
||||
worker_receipt_sha256=R.A.digest(workerpath),spawn_monotonic=start,exit_monotonic=start+4.,
|
||||
validation_end_monotonic=start+5.,child_wall_seconds=4.,end_to_end_seconds=5.,validation_wall_seconds=1.,
|
||||
output_bytes=sum(v['bytes'] for v in inventory.values()),
|
||||
output_inventory_sha256=hashlib.sha256(json.dumps(hashes,sort_keys=True).encode()).hexdigest(),**logs)
|
||||
processpath=self.exp/'receipts'/f'{name}.process.json';R.F.save(processpath,process)
|
||||
self.processes[name]=dict(process=process,job=job,worker=worker,output_inventory=inventory,
|
||||
binding=dict(receipt_id=str(processpath),sha256=R.A.digest(processpath)))
|
||||
|
||||
def report(self,save=False):return R.report(self.regsha,save_report=save)
|
||||
|
||||
def test_actual_cycles_tail_complete_bytes_and_no_forecast_without_future_policy(self):
|
||||
value=self.report()
|
||||
self.assertEqual(value['status'],'INSUFFICIENT-MEASUREMENTS')
|
||||
self.assertEqual(value['policy_status'],'FUTURE-POLICY-NOT-REGISTERED')
|
||||
self.assertEqual(value['registration_sha256'],self.regsha)
|
||||
self.assertEqual(value['inventory']['brain_calls'],33920)
|
||||
self.assertEqual({r['cycle_id'] for r in value['measurements']},{R.TRAIN,R.PROBE})
|
||||
for name in (R.TRAIN,R.PROBE):
|
||||
account=value['accounting'][name]
|
||||
self.assertEqual((account['recorded_cycle_seconds'],account['tail_upper_bound_seconds'],
|
||||
account['conservative_complete_cycle_seconds']),(40.,60.,100.))
|
||||
self.assertEqual(account['total_conservative_bytes'],account['created_bytes']+
|
||||
account['cycle_receipt_bytes']+account['repeated_full_cache_bytes'])
|
||||
self.assertGreater(account['cycle_receipt_bytes'],0)
|
||||
self.assertIsNone(value['estimated_wall_seconds']);self.assertIsNone(value['estimated_output_bytes'])
|
||||
self.assertIsNone(value['strict_projection']['estimated_wall_seconds'])
|
||||
self.assertFalse(value['learning_pass_claimed']);self.assertFalse(value['execution_authorized'])
|
||||
|
||||
def test_saved_report_reproduces_exactly_and_is_exclusive(self):
|
||||
first=self.report(True);second=self.report(False)
|
||||
self.assertEqual(R._canonical(first),R._canonical(second))
|
||||
self.assertEqual(R._canonical(first),R._canonical(R.A.read(self.exp/'audit/budget-report.json')))
|
||||
with self.assertRaisesRegex(ValueError,'never overwrite'):self.report(True)
|
||||
self.assertNotIn('generated_at',first);self.assertNotIn('free_bytes',first)
|
||||
|
||||
def test_worker_byte_tampering_and_wrong_registration_rejected(self):
|
||||
path=self.exp/'receipts'/f'{R.TRAIN}.worker.json'
|
||||
self.rewrite(path,lambda r:r.update(wall_seconds=.01))
|
||||
with self.assertRaisesRegex(ValueError,'Evidence bytes changed'):self.report()
|
||||
with self.assertRaises(ValueError):R.report('f'*64,save_report=False)
|
||||
|
||||
def test_unsuccessful_parent_process_cannot_be_reclassified_by_worker(self):
|
||||
path=self.exp/'receipts'/f'{R.TRAIN}.process.json'
|
||||
self.rewrite(path,lambda r:r.update(exit_code=1))
|
||||
with self.assertRaisesRegex(ValueError,'Unsuccessful'):self.report()
|
||||
|
||||
def test_cycle_inventory_omission_not_mistaken_for_full_output_bytes(self):
|
||||
path=self.exp/'receipts'/f'{R.TRAIN}.cycle.json'
|
||||
def omit(row):
|
||||
key=next(iter(row['output_inventory']));del row['output_inventory'][key]
|
||||
row['output_bytes']=sum(v['bytes'] for v in row['output_inventory'].values())
|
||||
self.rewrite(path,omit)
|
||||
with self.assertRaisesRegex(ValueError,'complete fixed-branch scope'):self.report()
|
||||
|
||||
def test_missing_cycle_evidence_returns_insufficient_without_inventing_measurement(self):
|
||||
(self.exp/'receipts'/f'{R.TRAIN}.cycle.json').unlink()
|
||||
value=self.report()
|
||||
self.assertEqual(value['status'],'INSUFFICIENT-MEASUREMENTS')
|
||||
self.assertEqual(value['measurements'],[])
|
||||
self.assertTrue(any('evidence missing' in item for item in value['missing']))
|
||||
self.assertIsNone(value['estimated_output_bytes'])
|
||||
|
||||
def test_inconsistent_adjacent_clock_cannot_supply_tail_upper_bound(self):
|
||||
path=self.exp/'receipts'/f'{R.PROBE}.cycle.json'
|
||||
self.rewrite(path,lambda r:r.update(start_monotonic=self.cycle_times[R.TRAIN][1]-1))
|
||||
with self.assertRaisesRegex(ValueError,'adjacent-cycle tail'):self.report()
|
||||
|
||||
def test_mutable_cache_final_bytes_must_match_observed_final_inventory(self):
|
||||
self.put(self.exp/'extension-build/kernel.bin','changed-after-observation')
|
||||
with self.assertRaisesRegex(ValueError,'mutable cache inventory changed'):self.report()
|
||||
|
||||
def test_reference_or_continuation_not_admitted_as_fresh_performance(self):
|
||||
real=R._parent_process
|
||||
def different(name,*args):
|
||||
row=real(name,*args)
|
||||
if name==R.PROBE:row=deepcopy(row);row['job']['diagnostic_mode']='reference'
|
||||
return row
|
||||
with patch.object(R,'_parent_process',side_effect=different):
|
||||
with self.assertRaisesRegex(ValueError,'fresh light'):self.report()
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,103 @@
|
||||
"""Pure authority construction tests; synthetic files, no graph or GPU claims."""
|
||||
import copy
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import execution_authority as A
|
||||
|
||||
|
||||
class AuthorityTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp=tempfile.TemporaryDirectory();self.root=Path(self.tmp.name).resolve()
|
||||
self.case=self.root/'case';self.parent=self.root/'parent';self.update=self.root/'update'
|
||||
for p in (self.case,self.parent,self.update):p.mkdir()
|
||||
self.write(self.parent/'checkpoint-manifest.json',{'fixture':True})
|
||||
self.write(self.parent/'summary.json',{'steps':1200,'effective_weights_raw_sha256':'a'*64,'diagnostic_mode':'reference'})
|
||||
self.write(self.case/'spec.json',{'steps':1000,'global_tick_offset':1200,
|
||||
'parent_checkpoint_manifest_sha256':A.digest(self.parent/'checkpoint-manifest.json')})
|
||||
(self.case/'requests.npz').write_bytes(b'synthetic-file-not-a-real-npz')
|
||||
(self.parent/'state.npz').write_bytes(b'synthetic-state-not-a-real-npz')
|
||||
self.before=dict(overlay_file=str(self.root/'before.npz'),overlay_manifest=str(self.root/'before.json'))
|
||||
self.after=dict(overlay_file=str(self.root/'after.npz'),overlay_manifest=str(self.root/'after.json'))
|
||||
for p in (*self.before.values(),*self.after.values()):Path(p).write_bytes(b'fixture')
|
||||
self.epoch=self.root/'epoch.json';self.cpu=self.root/'cpu.json'
|
||||
self.write(self.epoch,{});self.write(self.cpu,{})
|
||||
for n in ('chain-receipt.json','update-receipt.json','delta-after.npz','overlay-manifest.json'):
|
||||
(self.update/n).write_bytes(b'fixture')
|
||||
|
||||
def tearDown(self):self.tmp.cleanup()
|
||||
|
||||
def write(self,path,value):path.write_text(json.dumps(value),encoding='utf-8')
|
||||
|
||||
def make(self,**changes):
|
||||
kw=dict(boundary_id='fixture',registration_sha256='c'*64,case=self.case,parent=self.parent,
|
||||
transition='epoch_update',input_policy='empty_idle',mode='light',before_overlay=self.before,
|
||||
after_overlay=self.after,source_files={'fixture':A.pin(self.cpu)},frozen_inputs={str(self.epoch):A.digest(self.epoch)},
|
||||
epoch=self.epoch,update_dir=self.update,cpu_receipt=self.cpu)
|
||||
kw.update(changes)
|
||||
# Hash computation is stubbed only here: no effective-weight verification claim.
|
||||
with patch.object(A,'effective_hash',side_effect=['a'*64,'b'*64] if kw['transition']=='epoch_update' else ['a'*64]*2):
|
||||
return A.boundary_authority(**kw)
|
||||
|
||||
def test_exact_boundary_fields_and_live_payload_pins(self):
|
||||
value=self.make()
|
||||
self.assertEqual(value['global_tick_offset'],1200)
|
||||
self.assertEqual(value['parent']['checkpoint_manifest_sha256'],A.digest(self.parent/'checkpoint-manifest.json'))
|
||||
self.assertEqual(value['update']['files']['delta-after.npz'],A.pin(self.update/'delta-after.npz'))
|
||||
self.assertEqual(value['expected_effective_weight_after_sha256'],'b'*64)
|
||||
|
||||
def test_changed_clock_or_parent_rejected(self):
|
||||
original=A.read(self.case/'spec.json')
|
||||
for key,value in (('global_tick_offset',1199),('parent_checkpoint_manifest_sha256','0'*64)):
|
||||
spec={**original,key:value};self.write(self.case/'spec.json',spec)
|
||||
with self.subTest(key=key),self.assertRaises(ValueError):self.make()
|
||||
|
||||
def test_later_parent_uses_absolute_next_tick(self):
|
||||
summary=A.read(self.parent/'summary.json');summary['global_next_tick']=11200
|
||||
self.write(self.parent/'summary.json',summary)
|
||||
spec=A.read(self.case/'spec.json');spec['global_tick_offset']=11200;self.write(self.case/'spec.json',spec)
|
||||
value=self.make(transition='idle',epoch=None,update_dir=None,cpu_receipt=None)
|
||||
self.assertEqual(value['global_tick_offset'],11200);self.assertIsNone(value['update'])
|
||||
|
||||
def test_epoch_update_requires_all_evidence(self):
|
||||
for name in ('epoch','update_dir','cpu_receipt'):
|
||||
with self.subTest(name=name),self.assertRaises(ValueError):self.make(**{name:None})
|
||||
|
||||
def test_idle_cannot_carry_new_update(self):
|
||||
with self.assertRaisesRegex(ValueError,'Idle cannot'):self.make(transition='idle')
|
||||
|
||||
def test_boundary_copies_descriptors_not_aliases(self):
|
||||
sources={'role':A.pin(self.cpu)};frozen={str(self.epoch):A.digest(self.epoch)}
|
||||
value=self.make(source_files=sources,frozen_inputs=frozen)
|
||||
sources['role']['sha256']='0'*64;frozen.clear()
|
||||
self.assertNotEqual(value['source_files'],sources);self.assertTrue(value['frozen_inputs'])
|
||||
|
||||
def test_complete_direct_closure_and_conflicting_pin(self):
|
||||
value=self.make();pins=A.files_from_authority(value)
|
||||
for p in (self.epoch,self.cpu,self.case/'requests.npz',self.parent/'checkpoint-manifest.json',self.update/'delta-after.npz'):
|
||||
self.assertEqual(pins[str(p)],A.digest(p))
|
||||
value['frozen_inputs'][str(self.cpu)]='0'*64
|
||||
with self.assertRaisesRegex(ValueError,'Conflicting'):A.files_from_authority(value)
|
||||
|
||||
def test_epoch_template_is_not_modified(self):
|
||||
spec=A.read(self.case/'spec.json');spec['steps']=1200;self.write(self.case/'spec.json',spec)
|
||||
template=dict(schema='phase4an-epoch-postprocess-authority-v1',files={'old':{'path':'literal','sha256':'1'*64}},
|
||||
frozen_inputs={'literal':'1'*64})
|
||||
original=copy.deepcopy(template)
|
||||
result=A.epoch_authority(template,case=self.case,checkpoint=self.parent,overlay=self.before,
|
||||
epoch_id='mechanical',us_tick=1199)
|
||||
self.assertEqual(template,original);self.assertEqual(result['command']['us_tick'],1199)
|
||||
self.assertEqual(result['files']['state'],A.pin(self.parent/'state.npz'))
|
||||
with self.assertRaises(ValueError):A.epoch_authority(template,case=self.case,checkpoint=self.parent,
|
||||
overlay=self.before,epoch_id='bad',us_tick=1200)
|
||||
|
||||
def test_duplicate_or_nonfinite_JSON_rejected(self):
|
||||
for data in ('{"a":1,"a":2}','{"a":NaN}'):
|
||||
self.cpu.write_text(data)
|
||||
with self.assertRaises(ValueError):A.read(self.cpu)
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,142 @@
|
||||
"""Synthetic CPU-only budget contract tests, not measured performance evidence."""
|
||||
from copy import deepcopy
|
||||
import unittest
|
||||
|
||||
import execution_budget as B
|
||||
|
||||
|
||||
CONTEXT = 'a'*64
|
||||
|
||||
|
||||
class BudgetTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.auth = {}
|
||||
self.reserves = {role:dict(wall_seconds=1.,output_bytes=2,basis='explicit fixture allowance')
|
||||
for role in B.RESERVE_ROLES}
|
||||
self.reserves['cycle_multiplier'] = 1.25
|
||||
|
||||
def bind(self, name):
|
||||
self.auth[name] = 'b'*64
|
||||
return dict(receipt_id=name,sha256='b'*64)
|
||||
|
||||
def cycle(self, name, kind='training', mode='light', steps=1200):
|
||||
events = []
|
||||
roles = ['brain','original_E','cpu_validator'] if kind == 'training' else ['brain']
|
||||
for i,role in enumerate(roles):
|
||||
events.append(dict(event_id=name+'-'+role,role=role,receipt_kind='parent-process',
|
||||
receipt=self.bind(name+'-'+role),spawn_s=1.+i*4,exit_s=3.+i*4,validated_s=4.+i*4,
|
||||
exit_code=0,core_seconds=.5,runtime_seconds=1.,child_wall_seconds=2.))
|
||||
return dict(schema=B.SCHEMA,cycle_id=name,kind=kind,diagnostic_mode=mode,steps=steps,
|
||||
neurons=B.N,edges=B.E,dt_ms=.1,context_sha256=CONTEXT,clock_id='parent-clock-1',
|
||||
started_s=0.,validated_s=len(roles)*4.+1,authority=self.bind(name+'-cycle'),events=events,
|
||||
outputs=dict(inventory=self.bind(name+'-inventory'),scope=B.OUTPUT_SCOPE,complete=True,total_bytes=1000),complete=True)
|
||||
|
||||
def estimate(self, rows, **kwargs):
|
||||
return B.estimate_normal_suite(rows,authenticated_receipts=self.auth,target_context_sha256=CONTEXT,
|
||||
reserves=self.reserves,**kwargs)
|
||||
|
||||
def test_full_training_probe_cycles_use_only_end_to_end_and_complete_bytes(self):
|
||||
train,probe = self.cycle('train'),self.cycle('probe','probe')
|
||||
report = self.estimate([train,probe])
|
||||
self.assertEqual(report['status'],'ESTIMATED-NOT-AUTHORIZED')
|
||||
self.assertEqual(report['inventory']['brain_calls'],33920)
|
||||
self.assertEqual(report['inventory']['biological_seconds'],4070.4)
|
||||
self.assertEqual(report['estimated_wall_seconds'],int(1.25*(30000*13+3920*5)+5))
|
||||
self.assertEqual(report['estimated_output_bytes'],int(1.25*33920*1000+10))
|
||||
self.assertEqual(report['measured_cycles'][0]['timing'],dict(core_seconds=1.5,runtime_seconds=3.,
|
||||
child_wall_seconds=6.,end_to_end_seconds=13.))
|
||||
for field in ('execution_authorized','scientific_learning_claimed','external_identity_verified_here'):
|
||||
self.assertFalse(report[field])
|
||||
|
||||
def test_missing_either_cycle_returns_symbolic_not_pseudo_precise_total(self):
|
||||
for rows in ([],[self.cycle('only-train')],[self.cycle('only-probe','probe')]):
|
||||
report = self.estimate(rows)
|
||||
self.assertEqual(report['status'],'INSUFFICIENT-MEASUREMENTS')
|
||||
self.assertIsNone(report['estimated_wall_seconds'])
|
||||
self.assertIsNone(report['estimated_output_bytes'])
|
||||
self.assertTrue(report['missing'])
|
||||
self.assertIn('30000',report['symbolic_wall'])
|
||||
|
||||
def test_reference_idle_short_wrong_context_are_reported_but_not_training_samples(self):
|
||||
rows = [self.cycle('ref',mode='reference'),self.cycle('idle','state_only_idle',steps=10000),
|
||||
self.cycle('short',steps=1000),self.cycle('other')]
|
||||
rows[-1]['context_sha256'] = 'c'*64
|
||||
report = self.estimate(rows+[self.cycle('probe','probe')])
|
||||
self.assertEqual(report['status'],'INSUFFICIENT-MEASUREMENTS')
|
||||
self.assertEqual(report['eligible_cycle_ids']['training'],[])
|
||||
self.assertEqual(len(report['measured_cycles']),5)
|
||||
|
||||
def test_actual_parent_event_order_receipts_and_complete_output_required(self):
|
||||
mutations = [lambda r:r['events'].pop(),lambda r:r['events'][0].update(receipt_kind='AP-worker-slot'),
|
||||
lambda r:r['events'][1].update(spawn_s=0.),lambda r:r['events'][0].update(exit_code=1),
|
||||
lambda r:r['events'][0]['receipt'].update(sha256='f'*64),
|
||||
lambda r:r['outputs'].update(complete=False),lambda r:r['outputs'].update(scope='state-only'),
|
||||
lambda r:r['outputs'].update(total_bytes=True),lambda r:r.update(neurons=16),
|
||||
lambda r:r['events'][0].update(child_wall_seconds=1.),lambda r:r.update(complete=1),
|
||||
lambda r:r['events'][0].update(runtime_seconds=3.),lambda r:r.update(validated_s=float('nan'))]
|
||||
for i,mutate in enumerate(mutations):
|
||||
row = self.cycle('mutate'+str(i))
|
||||
mutate(row)
|
||||
with self.assertRaises(ValueError):
|
||||
self.estimate([row])
|
||||
with self.assertRaises(ValueError):
|
||||
self.estimate([dict(wall_seconds=10,slot='D1')])
|
||||
|
||||
def test_reserves_have_no_implicit_defaults_and_caps_stop_without_inventory_change(self):
|
||||
rows = [self.cycle('train'),self.cycle('probe','probe')]
|
||||
report = self.estimate(rows,limits=dict(wall_seconds=1,output_bytes=1))
|
||||
self.assertEqual(report['status'],'STOP-BUDGET-EXCEEDED')
|
||||
self.assertFalse(report['caps_pass'])
|
||||
self.assertEqual(report['inventory'],B.INVENTORY)
|
||||
original = deepcopy(self.reserves)
|
||||
for role in B.RESERVE_ROLES | {'cycle_multiplier'}:
|
||||
self.reserves = deepcopy(original)
|
||||
del self.reserves[role]
|
||||
with self.assertRaises(ValueError):
|
||||
self.estimate(rows)
|
||||
self.reserves = deepcopy(original)
|
||||
self.reserves['cycle_multiplier'] = .99
|
||||
with self.assertRaises(ValueError):
|
||||
self.estimate(rows)
|
||||
|
||||
def test_maxima_not_fitted_or_pooled_with_reference_and_no_mutation(self):
|
||||
slow = self.cycle('slow')
|
||||
slow['validated_s'] = 25.
|
||||
slow['outputs']['total_bytes'] = 2000
|
||||
ref = self.cycle('ref',mode='reference')
|
||||
ref['validated_s'] = 10000.
|
||||
rows = [self.cycle('fast'),slow,ref,self.cycle('probe','probe')]
|
||||
saved = deepcopy(rows)
|
||||
report = self.estimate(rows)
|
||||
self.assertEqual(report['estimated_wall_seconds'],int(1.25*(30000*25+3920*5)+5))
|
||||
self.assertEqual(report['estimated_output_bytes'],int(1.25*(30000*2000+3920*1000)+10))
|
||||
self.assertEqual(rows,saved)
|
||||
|
||||
def test_missing_core_runtime_are_unknown_not_required_for_end_to_end(self):
|
||||
train,probe = self.cycle('train'),self.cycle('probe','probe')
|
||||
for event in train['events']:
|
||||
event.update(core_seconds=None,runtime_seconds=None)
|
||||
report = self.estimate([train,probe])
|
||||
self.assertEqual(report['status'],'ESTIMATED-NOT-AUTHORIZED')
|
||||
self.assertIsNone(report['measured_cycles'][0]['timing']['core_seconds'])
|
||||
self.assertIsNone(report['measured_cycles'][0]['timing']['runtime_seconds'])
|
||||
self.assertEqual(report['measured_cycles'][0]['timing']['end_to_end_seconds'],13.)
|
||||
|
||||
def test_duplicate_events_and_probe_updates_rejected(self):
|
||||
train = self.cycle('train')
|
||||
duplicate = deepcopy(train)
|
||||
duplicate['cycle_id'] = 'forged-second-cycle'
|
||||
with self.assertRaises(ValueError):
|
||||
self.estimate([train,duplicate])
|
||||
for event in duplicate['events']:
|
||||
event['event_id'] += '-renamed'
|
||||
with self.assertRaises(ValueError):
|
||||
self.estimate([train,duplicate])
|
||||
probe = self.cycle('probe','probe')
|
||||
probe['events'].append(deepcopy(train['events'][1]))
|
||||
with self.assertRaises(ValueError):
|
||||
self.estimate([probe])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,333 @@
|
||||
"""CPU-only workflow mocks: real local receipts/files, never GPU/remote calls."""
|
||||
from copy import deepcopy
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
import boundary_plan as P
|
||||
import execution_workflow as F
|
||||
|
||||
|
||||
class WorkflowTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
path=Path(__file__).resolve().parent.parent/'conditioning-interface-v2/isolated_workers.py'
|
||||
spec=importlib.util.spec_from_file_location('workflow_test_frozen_AP_worker',path)
|
||||
cls.ap=importlib.util.module_from_spec(spec);spec.loader.exec_module(cls.ap)
|
||||
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.tmp.cleanup)
|
||||
self.base = Path(self.tmp.name)
|
||||
self.exp,self.model,self.lab = (self.base/n for n in ('phase4-fixture','model','lab'))
|
||||
for name in ('protocol/case-templates','inputs/static','cases','runs','updates','jobs','authorities',
|
||||
'receipts','logs','audit','extension-build'):
|
||||
(self.exp/name).mkdir(parents=True,exist_ok=True)
|
||||
self.model.mkdir(); self.lab.mkdir()
|
||||
self.ap_worker = self.base/'ap_worker.py'
|
||||
self.put(self.ap_worker,'# fixture AP worker')
|
||||
sources = {}
|
||||
for name in set().union(*F.W.SOURCES.values()) | {'isolated_execution.py'}:
|
||||
path = self.model/name; self.put(path,'# fixture source '+name); sources[str(path)]=F.digest(path)
|
||||
for name in ('runtime_light','runtime_continuation','conditioning_update','eligibility_bridge',
|
||||
'phase4j','am_overlay','conditioning_epoch','conditioning_preflight_compare','engineering_compare'):
|
||||
self.put(self.lab/(name+'.py'),'# fixture '+name)
|
||||
self.patches = [patch.object(F,'EXP',self.exp),patch.object(F,'MODEL',self.model),
|
||||
patch.object(F,'LAB',self.lab),patch.object(F,'AP_WORKER',self.ap_worker)]
|
||||
for item in self.patches:
|
||||
item.start(); self.addCleanup(item.stop)
|
||||
self.plan=P.build_plan(); self.calls={c['call_id']:c for c in self.plan['calls']}
|
||||
self.requests=dict(tick=np.array([3,900],np.int32),neuron_idx=np.array([12,15],np.int32))
|
||||
F.save_npz(self.exp/'inputs/static/mechanical-requests.npz',self.requests)
|
||||
self.initial=self.overlay('zero')
|
||||
parents={}
|
||||
for arm,descriptor in self.plan['imported_parents'].items():
|
||||
directory=self.base/('AP-'+arm); directory.mkdir()
|
||||
self.checkpoint(directory,1200,'reference')
|
||||
update=self.base/('AP-'+arm+'-update'); self.update_files(update)
|
||||
before=self.overlay('before-'+arm)
|
||||
case=self.base/('AP-'+arm+'-case');case.mkdir()
|
||||
F.save(case/'spec.json',dict(steps=1200));F.save_npz(case/'requests.npz',self.requests)
|
||||
epoch=dict(schema='phase4an-epoch-postprocess-authority-v1',checkpoint_dir=str(directory),
|
||||
checkpoint_manifest_sha256=F.digest(directory/'checkpoint-manifest.json'),
|
||||
files={'requests':F.A.pin(case/'requests.npz')},frozen_inputs={})
|
||||
for role in ('runtime_continuation','runtime_light','conditioning_update','eligibility_bridge','phase4j','am_overlay'):
|
||||
epoch['files'][role+'_source']=F.A.pin(self.lab/(role+'.py'))
|
||||
ep=self.base/('AP-'+arm+'.epoch.json');F.save(ep,epoch)
|
||||
parents[descriptor['role']]=dict(directory=str(directory),checkpoint_sha256=epoch['checkpoint_manifest_sha256'],
|
||||
epoch_authority=F.A.pin(ep),update_dir=str(update),before_overlay=before,
|
||||
after_overlay=dict(overlay_file=str(update/'delta-after.npz'),overlay_manifest=str(update/'overlay-manifest.json')))
|
||||
templates={}
|
||||
for call in self.plan['calls']:
|
||||
group=call['case_group']
|
||||
if group not in templates:
|
||||
path=self.exp/'protocol/case-templates'/f'{group}.json'
|
||||
F.save(path,dict(name=group,steps=call['steps'],max_steps=call['steps'],
|
||||
within_trial_weight_updates=call.get('within_trial_weight_updates',False)))
|
||||
templates[group]=str(path)
|
||||
self.reg=dict(plan=self.plan,parent_records=parents,initial_overlay=self.initial,case_templates=templates,
|
||||
source_sha256=sources,input_sha256={},prepared_file_sha256={},budget=dict(root=str(self.exp),
|
||||
output_cap_bytes=2**30,minimum_free_reserve_bytes=0,child_timeout_seconds=20,workflow_timeout_seconds=7200))
|
||||
F.save(self.exp/'protocol/preregistered.json',self.reg)
|
||||
self.w=F.Workflow.__new__(F.Workflow)
|
||||
self.w.sha=F.digest(self.exp/'protocol/preregistered.json');self.w.reg=self.reg
|
||||
self.w.parents=deepcopy(parents);self.w.jobs={};self.w.boundaries={};self.w.completed=[];self.w.cycles=[];self.w.sampler=None
|
||||
self.w.started=0.;self.w.deadline=10**12
|
||||
self.w.h=SimpleNamespace(GPU='fixture-gpu',COMFY_URLS=('fixture-queue',),
|
||||
SOURCE_PINS={n:F.digest(self.lab/(n+'.py')) for n in ('runtime_light','runtime_continuation','conditioning_epoch')})
|
||||
self.launched=[];self.boundary_args=[]
|
||||
|
||||
def put(self,path,text):
|
||||
path=Path(path);path.parent.mkdir(parents=True,exist_ok=True)
|
||||
path.write_text(text,encoding='utf-8')
|
||||
|
||||
def overlay(self,name):
|
||||
npz=self.base/(name+'.npz');meta=self.base/(name+'.json')
|
||||
F.save_npz(npz,dict(delta=np.array([0.],np.float32)));F.save(meta,dict(fixture=name))
|
||||
return dict(overlay_file=str(npz),overlay_manifest=str(meta))
|
||||
|
||||
def checkpoint(self,directory,steps,mode,offset=0):
|
||||
F.save(directory/'summary.json',dict(steps=steps,diagnostic_mode=mode,global_next_tick=offset+steps,
|
||||
effective_weights_raw_sha256='f'*64))
|
||||
F.save_npz(directory/'state.npz',dict(step=np.array([0],np.int32)))
|
||||
F.save(directory/'checkpoint-manifest.json',dict(fixture=True,steps=steps))
|
||||
|
||||
def update_files(self,directory):
|
||||
directory.mkdir()
|
||||
for name in ('chain-receipt.json','update-receipt.json','overlay-manifest.json'):
|
||||
F.save(directory/name,dict(fixture=True))
|
||||
F.save_npz(directory/'delta-after.npz',dict(delta=np.array([-.01],np.float32)))
|
||||
|
||||
def fake_boundary(self,**kw):
|
||||
self.boundary_args.append(deepcopy(kw))
|
||||
case=Path(kw['case']);parent=Path(kw['parent'])
|
||||
return dict(schema='conditioning-updated-boundary-v1',transition=kw['transition'],
|
||||
diagnostic_mode=kw['mode'],boundary_id=kw['boundary_id'],
|
||||
case=dict(spec=F.A.pin(case/'spec.json'),requests=F.A.pin(case/'requests.npz')),
|
||||
parent=dict(directory=str(parent),checkpoint_manifest_sha256=F.digest(parent/'checkpoint-manifest.json')),
|
||||
overlay_before={k:F.A.pin(v) for k,v in kw['before_overlay'].items()},
|
||||
overlay_after={k:F.A.pin(v) for k,v in kw['after_overlay'].items()},
|
||||
source_files=kw['source_files'],frozen_inputs={})
|
||||
|
||||
def fake_launch(self,name,job,*,ap=False):
|
||||
self.launched.append((name,deepcopy(job),ap));output=Path(job['output_dir'])
|
||||
kind=job['kind'];result={}
|
||||
if kind=='update':self.update_files(output)
|
||||
else:
|
||||
output.mkdir()
|
||||
if kind=='sample':
|
||||
for cue,node in (('A',20),('B',30)):
|
||||
F.save_npz(output/f'{cue}-requests.npz',dict(tick=np.array([5],np.int32),neuron_idx=np.array([node],np.int32)))
|
||||
elif kind=='validate_cpu':F.save(output/'validation.json',dict(fixture=True))
|
||||
else:
|
||||
if kind=='brain':case=Path(job['case_dir'])
|
||||
elif kind=='oracle':case=Path(job['oracle_case'])
|
||||
else:case=Path(F.read(job['authority_file'])['case']['spec']['path']).parent
|
||||
spec=F.read(case/'spec.json')
|
||||
self.checkpoint(output,spec['steps'],job.get('diagnostic_mode','reference'),spec.get('global_tick_offset',0))
|
||||
result['checkpoint_manifest_sha256']=F.digest(output/'checkpoint-manifest.json')
|
||||
receipt=dict(output_dir=str(output),result=result)
|
||||
loc=self.exp/'receipts'/f'{name}.fixture-process.json';F.save(loc,dict(name=name,fixture=True))
|
||||
self.w.jobs[name]=dict(loc=dict(process=str(loc)),job=job,receipt=receipt)
|
||||
self.put(self.exp/'extension-build/.ninja_log',str(len(self.launched)))
|
||||
self.put(self.exp/'extension-build/new-extension.bin','compiled fixture artifact')
|
||||
return receipt
|
||||
|
||||
def test_new_job_exact_schema_and_direct_authority_parent_closure(self):
|
||||
cp=self.base/'AP-D1'
|
||||
auth=self.exp/'authorities/test.json'
|
||||
file=self.base/'binding.txt';self.put(file,'bound')
|
||||
F.save(auth,dict(parent=dict(directory=str(cp),checkpoint_manifest_sha256=F.digest(cp/'checkpoint-manifest.json')),
|
||||
files=dict(x=F.A.pin(file)),frozen_inputs={str(self.ap_worker):F.digest(self.ap_worker)}))
|
||||
job=self.w.new_job('test','updated',auth,build_root=str(self.exp/'extension-build'),diagnostic_mode='light')
|
||||
self.assertEqual(set(job),F.W.COMMON | F.W.FIELDS['updated'])
|
||||
self.assertEqual(set(job['source_sha256']),F.W.SOURCES['updated'])
|
||||
for path in (file,auth,cp/'checkpoint-manifest.json',self.exp/'protocol/preregistered.json'):
|
||||
self.assertEqual(job['input_sha256'][str(path)],F.digest(path))
|
||||
sample=self.w.new_job('evaluation-inputs','sample',self.exp/'protocol/preregistered.json')
|
||||
self.assertEqual(set(sample),F.W.COMMON | F.W.FIELDS['sample'])
|
||||
self.assertEqual(set(sample['source_sha256']),F.W.SOURCES['sample'])
|
||||
|
||||
def test_full_fixed_workflow_23_brains_31_processes_and_shared_case_lineage(self):
|
||||
with patch.object(self.w,'launch',side_effect=self.fake_launch),patch.object(F.A,'boundary_authority',side_effect=self.fake_boundary):
|
||||
self.w.run()
|
||||
self.assertEqual(len(self.w.completed),23);self.assertEqual(len(self.w.jobs),31)
|
||||
self.assertEqual(len(list((self.exp/'cases').iterdir())),17)
|
||||
byname={n:j for n,j,_ in self.launched}
|
||||
for _,job,ap in self.launched:
|
||||
expected=self.ap.COMMON | (self.ap.BRAIN_FIELDS if job['kind']=='brain' else self.ap.UPDATE_FIELDS) if ap else F.W.COMMON | F.W.FIELDS[job['kind']]
|
||||
self.assertEqual(set(job),expected)
|
||||
self.assertEqual(sum(j['kind'] in ('brain','updated','oracle','unchanged') for j in byname.values()),23)
|
||||
self.assertEqual(sum(j['kind']=='sample' for j in byname.values()),1)
|
||||
for arm in ('D1','D0','frozen','mechanical'):
|
||||
r=F.read(byname[f'{arm}--updated--reference']['authority_file'])
|
||||
l=F.read(byname[f'{arm}--updated--light']['authority_file'])
|
||||
self.assertEqual(r['case'],l['case']);self.assertEqual(r['parent'],l['parent'])
|
||||
for arm in ('D0','frozen'):
|
||||
job=byname[f'{arm}--old-C--reference'];p=self.reg['parent_records'][f'AP.{arm}.reference.epoch001']
|
||||
self.assertEqual(job['overlay_file'],p['before_overlay']['overlay_file'])
|
||||
self.assertNotEqual(job['overlay_file'],p['after_overlay']['overlay_file'])
|
||||
for arm in ('D1','mechanical'):
|
||||
self.assertEqual(byname[f'{arm}--live-oracle']['authority_file'],byname[f'{arm}--updated--reference']['authority_file'])
|
||||
after=self.reg['parent_records']['AP.D1.reference.epoch001']['after_overlay']
|
||||
idle=next(v for v in self.boundary_args if v['boundary_id']=='D1--idle--9s')
|
||||
self.assertEqual(idle['before_overlay'],after);self.assertEqual(idle['after_overlay'],after)
|
||||
self.assertIsNone(idle['epoch']);self.assertIsNone(idle['update_dir']);self.assertIsNone(idle['cpu_receipt'])
|
||||
self.assertEqual(self.w.parents['D1--idle--9s']['after_overlay'],after)
|
||||
for t in ('t0','t1','t10'):
|
||||
for cue,node in (('A',20),('B',30)):
|
||||
request=F.npz(self.exp/'cases'/f'D1--probe--{t}--{cue}'/'requests.npz')
|
||||
np.testing.assert_array_equal(request['neuron_idx'],np.array([node],np.int32))
|
||||
performance=byname['performance--natural-light-fresh']
|
||||
prior=self.reg['parent_records']['AP.D1.reference.epoch001']
|
||||
self.assertEqual(performance['overlay_file'],prior['before_overlay']['overlay_file'])
|
||||
update=F.read(byname['performance--natural-light-fresh--original-E']['authority_file'])
|
||||
self.assertEqual((update['command']['us_tick'],update['command']['trace_backend'],update['diagnostic_mode']),(900,'torch','light'))
|
||||
self.assertIn('performance--natural-light-fresh--cpu-verify',byname)
|
||||
cpu=byname['performance--natural-light-fresh--cpu-verify']
|
||||
self.assertEqual(cpu['authority_file'],byname['performance--natural-light-fresh--original-E']['authority_file'])
|
||||
self.assertEqual(cpu['update_dir'],byname['performance--natural-light-fresh--original-E']['output_dir'])
|
||||
for output in Path(cpu['update_dir']).iterdir():
|
||||
self.assertEqual(cpu['input_sha256'][str(output)],F.digest(output))
|
||||
probe=byname['performance--evaluation-A-light-fresh']
|
||||
self.assertEqual(probe['overlay_file'],self.initial['overlay_file'])
|
||||
self.assertNotIn('parent_checkpoint_manifest_sha256',F.read(Path(probe['case_dir'])/'spec.json'))
|
||||
self.assertFalse(any(n.startswith('performance--evaluation-A-light-fresh--') for n in byname))
|
||||
complete=F.read(self.exp/'audit/execution-complete.json')
|
||||
self.assertFalse(complete['scientific_learning_pass_claimed'])
|
||||
|
||||
def test_mutable_build_inventory_visible_new_artifacts_not_silently_ignored(self):
|
||||
self.w.reg=deepcopy(self.reg)
|
||||
self.w.reg['plan']=dict(imported_parents={},calls=self.plan['calls'][:2],
|
||||
counts=dict(new_brain_calls=2,total_children=0))
|
||||
def execute(call):
|
||||
self.put(self.exp/'extension-build/.ninja_log',call['call_id'])
|
||||
self.put(self.exp/'extension-build/new-extension.bin','compiled fixture artifact')
|
||||
F.save(self.exp/'runs'/(call['call_id']+'.json'),dict(complete=True))
|
||||
with patch.object(self.w,'execute_call',side_effect=execute):
|
||||
self.w.run()
|
||||
self.assertNotIn('extension-build/.ninja_log',F.tree(self.exp,exclude_build=True))
|
||||
self.assertIn('extension-build/.ninja_log',F.tree(self.exp))
|
||||
for cycle in self.w.cycles:
|
||||
self.assertIn('.ninja_log',cycle['mutable_build_inventory_after'])
|
||||
self.assertIn('new-extension.bin',cycle['mutable_build_inventory_after'])
|
||||
self.assertGreater(cycle['mutable_build_bytes_after'],0)
|
||||
self.assertTrue(cycle['output_inventory'])
|
||||
old=self.exp/'audit/pinned-result.json';F.save(old,dict(value=1))
|
||||
before=F.tree(self.exp,exclude_build=True);self.put(old,'{"value":2}')
|
||||
after=F.tree(self.exp,exclude_build=True)
|
||||
self.assertNotEqual(before['audit/pinned-result.json'],after['audit/pinned-result.json'])
|
||||
|
||||
def test_probe_scope_mutation_rejected_and_shared_case_mismatch_rejected(self):
|
||||
call=deepcopy(self.calls['performance--evaluation-A-light-fresh']);call['US']=True
|
||||
with self.assertRaises(ValueError):self.w.execute_call(call)
|
||||
call=self.calls['D1--updated--reference'];parent=self.w.parents[call['parent']]
|
||||
case=self.w.materialize(call,parent)
|
||||
altered=deepcopy(parent);altered['checkpoint_sha256']='0'*64
|
||||
with self.assertRaises(ValueError):self.w.materialize(call,altered)
|
||||
self.assertEqual(F.read(case/'spec.json')['parent_checkpoint_manifest_sha256'],parent['checkpoint_sha256'])
|
||||
|
||||
def child_receipt(self,command,*,ap=False,mutate=None,**kwargs):
|
||||
jobfile=Path(command[command.index('--job')+1]);job=F.read(jobfile)
|
||||
out=Path(job['output_dir']);out.mkdir();F.save(out/'result.json',dict(fixture=True))
|
||||
attempt=Path(job['receipt_file']+'.attempt.json');F.save(attempt,dict(fixture=True))
|
||||
script=self.ap_worker if ap else self.model/'isolated_execution.py'
|
||||
pins={**job['input_sha256'],str(jobfile):F.digest(jobfile),str(script):job['worker_sha256']}
|
||||
if ap:pins.update({v['path']:v['sha256'] for v in job['sources'].values()})
|
||||
else:
|
||||
pins[str(self.ap_worker)]=F.W.AP_SHA
|
||||
pins.update({str(self.model/k):v for k,v in job['source_sha256'].items()})
|
||||
receipt=dict(schema='phase4ap-isolated-worker-receipt-v1' if ap else 'conditioning-isolated-execution-receipt-v1',
|
||||
complete=True,job_sha256=F.digest(jobfile),registration_sha256=self.w.sha,kind=job['kind'],
|
||||
job_id=job['job_id'],worker_sha256=job['worker_sha256'],output_dir=job['output_dir'],
|
||||
output_files_sha256={'result.json':F.digest(out/'result.json')},attempt_sha256=F.digest(attempt))
|
||||
receipt['verified_input_sha256' if ap else 'input_sha256']=pins
|
||||
if mutate:mutate(receipt)
|
||||
F.save(job['receipt_file'],receipt)
|
||||
return SimpleNamespace(returncode=0)
|
||||
|
||||
def sample_job(self,name):
|
||||
return self.w.new_job(name,'sample',self.exp/'protocol/preregistered.json')
|
||||
|
||||
def test_real_parent_process_receipt_binds_exit_inputs_outputs_and_wall_layers(self):
|
||||
job=self.sample_job('success')
|
||||
with patch.object(self.w,'admission'),patch.object(F,'verify'), \
|
||||
patch.object(F.subprocess,'run',side_effect=self.child_receipt) as run, \
|
||||
patch.object(F.time,'perf_counter',side_effect=[100.,104.,107.]):
|
||||
self.w.deadline=110.;self.w.launch('success',job)
|
||||
process=F.read(self.exp/'receipts/success.process.json')
|
||||
self.assertEqual((process['exit_code'],process['child_wall_seconds'],process['validation_wall_seconds'],process['end_to_end_seconds']),(0,4.,3.,7.))
|
||||
self.assertEqual(run.call_args.kwargs['timeout'],10.)
|
||||
self.assertEqual(process['worker_receipt_sha256'],F.digest(self.exp/'receipts/success.worker.json'))
|
||||
self.assertGreater(process['output_bytes'],0)
|
||||
self.assertTrue(process['complete'])
|
||||
|
||||
def test_frozen_AP_worker_parent_receipt_uses_verified_source_closure(self):
|
||||
prior=self.reg['parent_records']['AP.D1.reference.epoch001']
|
||||
case=Path(F.read(prior['epoch_authority']['path'])['files']['requests']['path']).parent
|
||||
job=self.w.ap_job('performance-ap','brain',case=case,overlay=prior['before_overlay'],output=self.exp/'runs/performance-ap')
|
||||
self.assertEqual(set(job),self.ap.COMMON | self.ap.BRAIN_FIELDS)
|
||||
with patch.object(self.w,'admission'),patch.object(F,'verify'), \
|
||||
patch.object(F.subprocess,'run',side_effect=lambda *a,**kw:self.child_receipt(*a,ap=True,**kw)) as run:
|
||||
self.w.launch('performance-ap',job,ap=True)
|
||||
self.assertEqual(run.call_args.args[0][3],'brain')
|
||||
receipt=F.read(self.exp/'receipts/performance-ap.worker.json')
|
||||
for role in ('runtime_light','runtime_continuation'):
|
||||
binding=job['sources'][role]
|
||||
self.assertEqual(receipt['verified_input_sha256'][binding['path']],binding['sha256'])
|
||||
|
||||
def test_exit_failure_timeout_and_receipt_mutation_preserved_and_not_retried(self):
|
||||
variants=[('exit',lambda *a,**kw:SimpleNamespace(returncode=9)),
|
||||
('timeout',lambda *a,**kw:(_ for _ in ()).throw(subprocess.TimeoutExpired('fixture',1))),
|
||||
('identity',lambda *a,**kw:self.child_receipt(*a,mutate=lambda r:r.update(job_id='wrong'),**kw)),
|
||||
('closure',lambda *a,**kw:self.child_receipt(*a,mutate=lambda r:r['input_sha256'].clear(),**kw)),
|
||||
('output',lambda *a,**kw:self.child_receipt(*a,mutate=lambda r:r['output_files_sha256'].clear(),**kw))]
|
||||
for name,action in variants:
|
||||
job=self.sample_job(name)
|
||||
with patch.object(self.w,'admission'),patch.object(F,'verify'),patch.object(F.subprocess,'run',side_effect=action) as run:
|
||||
with self.assertRaises(ValueError):self.w.launch(name,job)
|
||||
self.assertFalse(F.read(self.exp/f'receipts/{name}.process.json')['complete'])
|
||||
with self.assertRaises(ValueError):self.w.launch(name,job)
|
||||
self.assertEqual(run.call_count,1)
|
||||
self.assertNotIn(name,self.w.jobs)
|
||||
|
||||
def test_workflow_attempt_prevents_restart(self):
|
||||
F.save(self.exp/'audit/execution-attempt.json',dict(partial=True))
|
||||
with patch.object(self.w,'cpu_verify') as verify:
|
||||
with self.assertRaises(ValueError):self.w.run()
|
||||
verify.assert_not_called()
|
||||
|
||||
def test_whole_deadline_starts_before_registration_verification(self):
|
||||
clock=[10.]
|
||||
def registration(sha):clock[0]=50.;return self.reg
|
||||
with patch.object(F,'registration',side_effect=registration),patch.object(F.W,'ap_helpers',return_value=self.w.h), \
|
||||
patch.object(F.time,'perf_counter',side_effect=lambda:clock[0]):
|
||||
workflow=F.Workflow('a'*64)
|
||||
self.assertEqual(workflow.started,10.)
|
||||
self.assertEqual(workflow.deadline,10.+self.reg['budget']['workflow_timeout_seconds'])
|
||||
|
||||
def test_no_complete_after_final_cycle_inventory_crosses_deadline(self):
|
||||
call=self.calls['D1--updated--reference'];self.w.reg=deepcopy(self.reg)
|
||||
self.w.reg['plan']=dict(imported_parents={},calls=[call],counts=dict(new_brain_calls=1,total_children=0))
|
||||
clock=[1.];self.w.started=0.;self.w.deadline=5.
|
||||
def execute(_):clock[0]=6.
|
||||
with patch.object(self.w,'execute_call',side_effect=execute),patch.object(F.time,'perf_counter',side_effect=lambda:clock[0]):
|
||||
with self.assertRaisesRegex(ValueError,'wall limit'):
|
||||
self.w.run()
|
||||
self.assertFalse((self.exp/'audit/execution-complete.json').exists())
|
||||
|
||||
def test_import_does_not_load_old_coordinator_neural_runtime_or_torch(self):
|
||||
code="import sys;sys.path.insert(0,sys.argv[1]);import execution_workflow;bad=[k for k in sys.modules if k in ('torch','runtime_light','runtime_continuation','conditioning_epoch','_conditioning_execution_prior_integrity')];assert not bad,bad"
|
||||
completed=subprocess.run([sys.executable,'-B','-c',code,str(Path(__file__).resolve().parent)],
|
||||
capture_output=True,text=True,timeout=20)
|
||||
self.assertEqual(completed.returncode,0,completed.stderr)
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,147 @@
|
||||
"""Synthetic seal checks only; no historical integrity or brain execution."""
|
||||
import copy
|
||||
from contextlib import contextmanager
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
import finalize_execution as F
|
||||
|
||||
|
||||
class FinalizeTests(unittest.TestCase):
|
||||
@contextmanager
|
||||
def complete_fixture(self):
|
||||
"""Temporary evidence + mocked auditors/child; no real integrity run."""
|
||||
helper = Path(__file__).parents[1]/'pn-recruitment-audit-v1/publication.py'
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp).resolve()
|
||||
for folder in ('protocol', 'audit', 'regression'):
|
||||
(root/folder).mkdir()
|
||||
reg = dict(schema='conditioning-execution-registration-v1', engineering_only=True,
|
||||
scientific_acquisition_authorized=False, source_sha256={}, input_sha256={},
|
||||
prepared_file_sha256={}, source_code_commit='a'*40)
|
||||
F.save(root/'protocol/preregistered.json', reg)
|
||||
regsha = F.digest(root/'protocol/preregistered.json')
|
||||
numerical = dict(schema='conditioning-execution-numerical-audit-v1', complete=True,
|
||||
registration_sha256=regsha, actual_new_brain_calls=23, actual_processes=31,
|
||||
actual_new_brain_ticks=125200, learning_pass_claimed=False, candidate_generated=False,
|
||||
status='PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING', pass_all=True,
|
||||
process_evidence={'synthetic': {'worker_sha256':'b'*64}})
|
||||
budget = dict(schema='synthetic-budget-report-not-scientific', complete=True,
|
||||
registration_sha256=regsha, learning_pass_claimed=False, measured_fixture_seconds=1.)
|
||||
integrity = dict(complete=True, AP={'pass_all':True}, prior={'synthetic_old_roots':'unchanged'},
|
||||
anchors={'synthetic_reference':'c'*64}, old_experiments_reexecuted=False,
|
||||
old_files_modified=False, five_frozen_reference_trials_rerun_here=False,
|
||||
scientific_learning_pass_claimed=False)
|
||||
files = (root/'audit/numerical-comparison.json', root/'audit/budget-report.json',
|
||||
root/'regression/integrity-after.json')
|
||||
for file, value in zip(files, (numerical, budget, integrity)):
|
||||
F.save(file, value)
|
||||
numerical_module = SimpleNamespace(audit=Mock(return_value=copy.deepcopy(numerical)),
|
||||
same_json=lambda a,b: json.dumps(a,sort_keys=True,allow_nan=False)==json.dumps(b,sort_keys=True,allow_nan=False))
|
||||
budget_module = SimpleNamespace(report=Mock(return_value=copy.deepcopy(budget)))
|
||||
def child(command, **kwargs):
|
||||
self.assertEqual(command, [F.sys.executable,'-B',str(F.MODEL/'prepare_execution.py'),
|
||||
'integrity','--output',str(root/'regression/integrity-at-seal.json')])
|
||||
self.assertEqual(kwargs, dict(cwd=F.MODEL,capture_output=True,text=True,timeout=1800))
|
||||
F.save(root/'regression/integrity-at-seal.json', integrity)
|
||||
return SimpleNamespace(returncode=0, stdout='synthetic child', stderr='')
|
||||
with patch.object(F,'EXP',root),patch.object(F,'HELPER',helper), \
|
||||
patch.dict(F.sys.modules,{'audit_execution':numerical_module,'budget_report':budget_module}), \
|
||||
patch.object(F.subprocess,'run',side_effect=child) as process:
|
||||
yield SimpleNamespace(root=root, numerical=numerical, integrity=integrity,
|
||||
audit_module=numerical_module,budget_module=budget_module,process=process,
|
||||
args=(regsha,*(F.digest(p) for p in files)))
|
||||
|
||||
def test_source_helper_matches_actual_local_frozen_file(self):
|
||||
path = Path(__file__).parents[1]/'pn-recruitment-audit-v1/publication.py'
|
||||
with patch.object(F, 'HELPER', path):
|
||||
module = F.helper()
|
||||
self.assertTrue(callable(module.verify_seal))
|
||||
|
||||
def test_exact_seal_detects_mutated_and_extra_payload(self):
|
||||
path = Path(__file__).parents[1]/'pn-recruitment-audit-v1/publication.py'
|
||||
with tempfile.TemporaryDirectory() as tmp, patch.object(F, 'HELPER', path):
|
||||
root = Path(tmp)
|
||||
F.save(root/'one.json', {'learning':False})
|
||||
result = F.seal(root)
|
||||
self.assertTrue(result['pass_all'])
|
||||
self.assertEqual(result['payload_file_count'], 1)
|
||||
with self.assertRaisesRegex(ValueError, 'Never replace'):
|
||||
F.seal(root)
|
||||
F.save(root/'unlisted.json', {})
|
||||
with self.assertRaisesRegex(ValueError, 'unlisted/missing'):
|
||||
F.helper().verify_seal(root)
|
||||
|
||||
def test_refuses_empty_and_bytecode_trees(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
with self.assertRaisesRegex(ValueError, 'Empty'):
|
||||
F.seal(root)
|
||||
(root/'__pycache__').mkdir()
|
||||
with self.assertRaisesRegex(ValueError, 'Unsafe'):
|
||||
F.seal(root)
|
||||
|
||||
def test_stopped_workflow_never_gets_normal_final(self):
|
||||
with tempfile.TemporaryDirectory() as tmp, patch.object(F, 'EXP', Path(tmp)):
|
||||
(Path(tmp)/'audit').mkdir()
|
||||
F.save(Path(tmp)/'audit/stopped.json', {'complete':False})
|
||||
with self.assertRaisesRegex(ValueError, 'separate explicit failure audit'):
|
||||
F.finalize('a'*64, 'b'*64, 'c'*64, 'd'*64)
|
||||
|
||||
def test_full_mock_finalize_recomputes_and_seals_actual_independent_report(self):
|
||||
with self.complete_fixture() as fixture:
|
||||
result = F.finalize(*fixture.args)
|
||||
fixture.audit_module.audit.assert_called_once_with(fixture.args[0],save_report=False)
|
||||
fixture.budget_module.report.assert_called_once_with(fixture.args[0],save_report=False)
|
||||
fixture.process.assert_called_once()
|
||||
final = F.read(fixture.root/'audit/final-status.json')
|
||||
self.assertEqual(result['status'],'PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING')
|
||||
self.assertEqual(final['integrity_at_seal_sha256'],F.digest(fixture.root/'regression/integrity-at-seal.json'))
|
||||
self.assertTrue(final['numerical_and_budget_recomputed_at_seal'])
|
||||
self.assertFalse(final['scientific_acquisition_executed'])
|
||||
self.assertFalse(final['learning_pass_claimed']); self.assertFalse(final['candidate_generated'])
|
||||
self.assertEqual(final['historical_five_trial_regression'],'AM sealed evidence preserved; not rerun here')
|
||||
sealed = F.helper().verify_seal(fixture.root)
|
||||
self.assertTrue(sealed['pass_all'])
|
||||
payload = {row['path'] for row in F.read(fixture.root/'manifest.json')['files']}
|
||||
self.assertTrue({'audit/numerical-comparison.json','audit/budget-report.json',
|
||||
'regression/integrity-after.json','regression/integrity-at-seal.json',
|
||||
'audit/final-status.json'}.issubset(payload))
|
||||
|
||||
def test_recomputed_numerical_or_budget_mutation_rejected_before_integrity_and_seal(self):
|
||||
for kind in ('numerical','budget'):
|
||||
with self.subTest(kind=kind),self.complete_fixture() as fixture:
|
||||
if kind=='numerical':
|
||||
changed=copy.deepcopy(fixture.numerical)
|
||||
changed['process_evidence']['synthetic']['worker_sha256']='d'*64
|
||||
fixture.audit_module.audit.return_value=changed
|
||||
else:
|
||||
changed=copy.deepcopy(fixture.budget_module.report.return_value)
|
||||
changed['measured_fixture_seconds']=2.
|
||||
fixture.budget_module.report.return_value=changed
|
||||
with self.assertRaisesRegex(ValueError,'evidence changed after the independent audit'):
|
||||
F.finalize(*fixture.args)
|
||||
fixture.process.assert_not_called()
|
||||
for name in ('audit/final-status.json','manifest.json','checksums.sha256'):
|
||||
self.assertFalse((fixture.root/name).exists())
|
||||
|
||||
def test_independent_integrity_failure_missing_output_or_changed_prior_refuses_seal(self):
|
||||
for mode in ('nonzero_exit','missing_file','changed_prior'):
|
||||
with self.subTest(mode=mode),self.complete_fixture() as fixture:
|
||||
def child(*args,**kwargs):
|
||||
if mode=='changed_prior':
|
||||
changed=copy.deepcopy(fixture.integrity); changed['prior']['synthetic_old_roots']='changed'
|
||||
F.save(fixture.root/'regression/integrity-at-seal.json',changed)
|
||||
return SimpleNamespace(returncode=1 if mode=='nonzero_exit' else 0,stdout='',stderr='synthetic failure')
|
||||
fixture.process.side_effect=child
|
||||
with self.assertRaisesRegex(ValueError,'integrity-at-seal process failed|Frozen integrity changed'):
|
||||
F.finalize(*fixture.args)
|
||||
for name in ('audit/final-status.json','manifest.json','checksums.sha256'):
|
||||
self.assertFalse((fixture.root/name).exists())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,176 @@
|
||||
"""CPU/path/admission tests only; no subprocess brain or scientific PASS."""
|
||||
import copy
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import isolated_execution as W
|
||||
|
||||
H = W.ap_helpers()
|
||||
|
||||
|
||||
class WorkerTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self.temp.name).resolve() / 'phase4aq-fixture'
|
||||
for name in ('inputs', 'updates', 'jobs', 'runs', 'receipts'):
|
||||
(self.root / name).mkdir(parents=True)
|
||||
self.authority = self.root / 'inputs' / 'authority.json'
|
||||
self.chain = self.root / 'updates' / 'chain-receipt.json'
|
||||
self.authority.write_text('{}'); self.chain.write_text('{}')
|
||||
self.jobfile = self.root / 'jobs' / 'one.json'
|
||||
self.job = dict(schema=W.SCHEMA, job_id='cpu-one', kind='validate_cpu',
|
||||
registration_sha256='1'*64, worker_sha256=H.digest(W.__file__),
|
||||
source_sha256={'validate_update_cpu.py': H.digest(W.MODEL/'validate_update_cpu.py')},
|
||||
input_sha256={str(p): H.digest(p) for p in (self.authority, self.chain)},
|
||||
output_dir=str(self.root/'runs'/'one'), receipt_file=str(self.root/'receipts'/'one.json'),
|
||||
budget=dict(root=str(self.root), output_cap_bytes=1024**2, minimum_free_reserve_bytes=1024**2),
|
||||
authority_file=str(self.authority), authority_sha256=H.digest(self.authority),
|
||||
update_dir=str(self.chain.parent), chain_sha256=H.digest(self.chain))
|
||||
|
||||
def tearDown(self):
|
||||
self.temp.cleanup()
|
||||
|
||||
def check(self, job=None):
|
||||
self.jobfile.write_text(json.dumps(self.job if job is None else job))
|
||||
return W.validate_job(H, self.jobfile, H.digest(self.jobfile))
|
||||
|
||||
def test_real_pinned_AP_helper_and_CPU_job(self):
|
||||
self.assertEqual(H.digest(W.AP), W.AP_SHA)
|
||||
job, paths, pins = self.check()
|
||||
self.assertEqual(job['kind'], 'validate_cpu')
|
||||
self.assertEqual(pins[W.AP], W.AP_SHA)
|
||||
self.assertEqual(paths['output'], self.root/'runs'/'one')
|
||||
|
||||
def test_wrong_or_missing_fields(self):
|
||||
changes = [('kind', 'brain'), ('job_id', '../x'), ('job_id', 'a/b'),
|
||||
('registration_sha256', ''), ('worker_sha256', '0'*64),
|
||||
('source_sha256', {}), ('input_sha256', {})]
|
||||
for key, value in changes:
|
||||
with self.subTest(key=key, value=value):
|
||||
job = copy.deepcopy(self.job); job[key] = value
|
||||
with self.assertRaises(ValueError): self.check(job)
|
||||
job = copy.deepcopy(self.job); job['extra'] = True
|
||||
with self.assertRaises(ValueError): self.check(job)
|
||||
|
||||
def test_source_bytes_are_checked_before_import(self):
|
||||
job = copy.deepcopy(self.job); job['source_sha256']['validate_update_cpu.py'] = '0'*64
|
||||
with self.assertRaisesRegex(ValueError, 'Pinned file changed'): self.check(job)
|
||||
|
||||
def test_parent_input_pin_and_chain_are_mandatory(self):
|
||||
for key in ('authority_sha256', 'chain_sha256'):
|
||||
job = copy.deepcopy(self.job); job[key] = '0'*64
|
||||
with self.subTest(key=key), self.assertRaises(ValueError): self.check(job)
|
||||
job = copy.deepcopy(self.job); del job['input_sha256'][str(self.chain)]
|
||||
with self.assertRaises(ValueError): self.check(job)
|
||||
|
||||
def test_partial_output_and_attempt_never_retried(self):
|
||||
output = Path(self.job['output_dir']); output.mkdir()
|
||||
with self.assertRaises(ValueError): self.check()
|
||||
output.rmdir()
|
||||
attempt = Path(self.job['receipt_file']+'.attempt.json'); attempt.write_text('{}')
|
||||
with self.assertRaises(ValueError): self.check()
|
||||
|
||||
def test_output_cannot_overlap_input_update_or_receipt(self):
|
||||
for path in (self.authority.parent/'child', self.chain.parent/'child',
|
||||
self.root/'receipts'/'child', self.root.parent/'escape'):
|
||||
job = copy.deepcopy(self.job); job['output_dir'] = str(path)
|
||||
with self.subTest(path=path), self.assertRaises(ValueError): self.check(job)
|
||||
|
||||
def test_linked_output_parent_rejected_when_supported(self):
|
||||
target = self.root/'runs'; linked = self.root/'linked'
|
||||
try: linked.symlink_to(target, target_is_directory=True)
|
||||
except OSError: self.skipTest('Platform does not allow test symlinks')
|
||||
job = copy.deepcopy(self.job); job['output_dir'] = str(linked/'one')
|
||||
with self.assertRaisesRegex(ValueError, 'Linked'): self.check(job)
|
||||
|
||||
def test_explicit_resource_limits(self):
|
||||
job, paths, _ = self.check()
|
||||
result = W.budget_check(H, job, paths)
|
||||
self.assertGreater(result['output_bytes'], 0)
|
||||
job['budget']['output_cap_bytes'] = 1
|
||||
with self.assertRaisesRegex(ValueError, 'Resource budget exceeded'): W.budget_check(H, job, paths)
|
||||
for field in ('output_cap_bytes', 'minimum_free_reserve_bytes'):
|
||||
job = copy.deepcopy(self.job); job['budget'][field] = 0
|
||||
with self.subTest(field=field), self.assertRaises(ValueError): self.check(job)
|
||||
|
||||
def test_fresh_process_loaders_are_not_reused(self):
|
||||
with self.assertRaisesRegex(ValueError, 'Fresh exec helper'): W.ap_helpers()
|
||||
|
||||
def unchanged(self):
|
||||
case=self.root/'inputs'/'case';case.mkdir()
|
||||
parent=self.root/'inputs'/'checkpoint';parent.mkdir()
|
||||
for p in (case/'spec.json',case/'requests.npz',parent/'checkpoint-manifest.json'):
|
||||
p.write_text('{}')
|
||||
before=self.root/'inputs'/'before.npz';bm=self.root/'inputs'/'before.json'
|
||||
after=self.root/'inputs'/'after.npz';am=self.root/'inputs'/'after.json'
|
||||
before.write_bytes(b'zero-values');after.write_bytes(b'zero-values')
|
||||
bm.write_text('{"phase":"before"}');am.write_text('{"phase":"after"}')
|
||||
files=(case/'spec.json',case/'requests.npz',parent/'checkpoint-manifest.json',before,bm,after,am,W.C_PATH)
|
||||
authority=dict(schema='conditioning-updated-boundary-v1',transition='epoch_update',diagnostic_mode='reference',
|
||||
registration_sha256='1'*64,expected_effective_weight_before_sha256='a'*64,expected_effective_weight_after_sha256='a'*64,
|
||||
parent=dict(directory=str(parent),checkpoint_manifest_sha256=H.digest(parent/'checkpoint-manifest.json')),
|
||||
case={key:dict(path=str(case/name),sha256=H.digest(case/name)) for key,name in (('spec','spec.json'),('requests','requests.npz'))},
|
||||
overlay_before={key:dict(path=str(p),sha256=H.digest(p)) for key,p in (('file',before),('manifest',bm))},
|
||||
overlay_after={key:dict(path=str(p),sha256=H.digest(p)) for key,p in (('file',after),('manifest',am))},frozen_inputs={})
|
||||
self.authority.write_text(json.dumps(authority))
|
||||
self.job=dict(schema=W.SCHEMA,job_id='unchanged-one',kind='unchanged',registration_sha256='1'*64,
|
||||
worker_sha256=H.digest(W.__file__),source_sha256={},input_sha256={str(p):H.digest(p) for p in (*files,self.authority)},
|
||||
output_dir=str(self.root/'runs'/'one'),receipt_file=str(self.root/'receipts'/'one.json'),
|
||||
budget=dict(root=str(self.root),output_cap_bytes=1024**2,minimum_free_reserve_bytes=1024**2),
|
||||
authority_file=str(self.authority),authority_sha256=H.digest(self.authority),case_dir=str(case),
|
||||
build_root=str(self.root/'build'),diagnostic_mode='reference',overlay_file=str(before),overlay_manifest=str(bm),
|
||||
checkpoint_dir=str(parent),checkpoint_sha256=H.digest(parent/'checkpoint-manifest.json'))
|
||||
return authority
|
||||
|
||||
def test_unchanged_binds_exact_before_not_equal_after_manifest(self):
|
||||
self.unchanged();job,paths,pins=self.check()
|
||||
self.assertEqual(W.bind_unchanged_authority(H,job,paths,pins)['transition'],'epoch_update')
|
||||
self.job['overlay_file']=str(self.root/'inputs'/'after.npz')
|
||||
self.job['overlay_manifest']=str(self.root/'inputs'/'after.json')
|
||||
job,paths,pins=self.check()
|
||||
with self.assertRaisesRegex(ValueError,'actual before'):W.bind_unchanged_authority(H,job,paths,pins)
|
||||
|
||||
def test_rehashed_wrong_authority_parent_mode_case_registration_rejected(self):
|
||||
original=self.unchanged()
|
||||
for field in ('parent','diagnostic_mode','registration_sha256','case'):
|
||||
value=copy.deepcopy(original)
|
||||
if field=='parent':value[field]['checkpoint_manifest_sha256']='f'*64
|
||||
elif field=='diagnostic_mode':value[field]='light'
|
||||
elif field=='registration_sha256':value[field]='f'*64
|
||||
else:value[field]['requests']['sha256']='f'*64
|
||||
self.authority.write_text(json.dumps(value))
|
||||
self.job['authority_sha256']=self.job['input_sha256'][str(self.authority)]=H.digest(self.authority)
|
||||
job,paths,pins=self.check()
|
||||
with self.subTest(field=field),self.assertRaises(ValueError):W.bind_unchanged_authority(H,job,paths,pins)
|
||||
|
||||
def test_unchanged_missing_nested_after_authority_pin_rejected(self):
|
||||
self.unchanged();del self.job['input_sha256'][str(self.root/'inputs'/'after.json')]
|
||||
job,paths,pins=self.check()
|
||||
with self.assertRaisesRegex(ValueError,'external input pin'):W.bind_unchanged_authority(H,job,paths,pins)
|
||||
|
||||
def test_unchanged_original_entry_already_seals_no_double_seal(self):
|
||||
self.unchanged();self.check()
|
||||
summary={'apl_component':{'environment':{'synthetic':True}},'complete':True,'steps':5}
|
||||
def simulated_entry(case,out,build,overlay,manifest,parent,*,mode):
|
||||
out.mkdir();H.save_json(out/'summary.json',summary)
|
||||
H.save_json(out/'checkpoint-manifest.json',{'synthetic_seal':True})
|
||||
return dict(summary,checkpoint_manifest_sha256=H.digest(out/'checkpoint-manifest.json'))
|
||||
runtime=SimpleNamespace(run_continued=Mock(side_effect=simulated_entry),
|
||||
load_checkpoint=Mock(return_value={'summary':summary}),
|
||||
seal_checkpoint=Mock(side_effect=AssertionError('Double seal would be a real blocker')))
|
||||
with patch.object(W,'ap_helpers',return_value=H),patch.object(H,'_clean_process') as clean, \
|
||||
patch.object(H,'_admit_brain',return_value={'synthetic_no_GPU':True}), \
|
||||
patch.object(H,'_load_source',return_value=runtime),patch.object(H,'_environment',return_value={'synthetic_no_GPU':True}), \
|
||||
patch.object(H,'_verify_precision'):
|
||||
result=W.execute(self.jobfile,H.digest(self.jobfile))
|
||||
runtime.run_continued.assert_called_once();runtime.load_checkpoint.assert_called_once();runtime.seal_checkpoint.assert_not_called()
|
||||
clean.assert_called_once_with('brain');self.assertTrue(result['complete'])
|
||||
self.assertFalse(result['process_exit_independently_observed'])
|
||||
self.assertFalse(result['scientific_learning_pass_claimed'])
|
||||
|
||||
|
||||
if __name__ == '__main__': unittest.main()
|
||||
@@ -0,0 +1,424 @@
|
||||
"""CPU synthetic fixtures only: no real brain, file receipts or science data."""
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
import learning_gates as g
|
||||
|
||||
|
||||
NODES = np.arange(6, dtype=np.int32)
|
||||
POPS = {'MBON': np.array([0, 1, 2], np.int32), 'legacyDownstream': NODES.copy(),
|
||||
'nonMBONDownstream': np.array([3, 4, 5], np.int32), 'MBON01': np.array([0], np.int32),
|
||||
'MBON12': np.array([1], np.int32)}
|
||||
C, N = g.M.CUES
|
||||
|
||||
|
||||
def sha(value):
|
||||
return hashlib.sha256(str(value).encode()).hexdigest()
|
||||
|
||||
|
||||
def registry():
|
||||
blocks = {}
|
||||
counter = 0
|
||||
for mode in g.M.MODES:
|
||||
for dan in g.M.DAN_TYPES:
|
||||
for cue in g.M.CUES:
|
||||
for rep in range(1, 6):
|
||||
block = f'{mode}/{dan}/{cue}/{rep}'
|
||||
base = 2**40 + counter * 10
|
||||
blocks[block] = dict(mode=mode, dan_type=dan, compartment_verbatim=g.DAN_COMPARTMENTS[dan],
|
||||
conditioned_cue=cue, replicate=rep,
|
||||
training_sources=[dict(stream_id=f'{block}/{split}/{assay}', seed=base + j, split=split)
|
||||
for j, (split, assay) in enumerate((('training', 'normal'), ('training', 'delayed'),
|
||||
('training', 'reversal'), ('design', 'order')))],
|
||||
evaluation_sources={cue: dict(stream_id=f'{block}/evaluation/{cue}', seed=base + 7 + j, split='evaluation')
|
||||
for j, cue in enumerate(g.M.CUES)},
|
||||
evaluation_input_sha256={cue: sha(f'{block}/input/{cue}') for cue in g.M.CUES})
|
||||
counter += 1
|
||||
return dict(schema=g.REGISTRY_SCHEMA, protocol_sha256=sha('synthetic-unregistered-protocol'),
|
||||
population_binding_sha256=sha('synthetic-population-binding'), nodes_raw_sha256=g.M._hash(NODES),
|
||||
population_membership_sha256=g.M.validate_populations(NODES, POPS)['membership_sha256'], blocks=blocks)
|
||||
|
||||
|
||||
def authority(reg):
|
||||
return dict(schema=g.AUTHORITY_SCHEMA, registry_sha256=g.descriptor_sha256(reg),
|
||||
verification_receipt_sha256=sha('SYNTHETIC-NOT-A-REAL-VERIFICATION'),
|
||||
execution_inventory_sha256=sha('SYNTHETIC-NOT-EXECUTED'), population_binding_sha256=reg['population_binding_sha256'])
|
||||
|
||||
|
||||
def state(direction=0, *, downstream=True, g_effect=True, offset=0):
|
||||
counts = [1, 1, 0, 1, 0, 0]
|
||||
if direction:
|
||||
counts[1 if direction > 0 else 0] += abs(direction)
|
||||
if downstream:
|
||||
counts[3] += abs(direction)
|
||||
events = sorted((10 + k * 20 + offset, i) for i, count in enumerate(counts) for k in range(count))
|
||||
conductance = np.zeros(6, np.float64)
|
||||
if direction and g_effect:
|
||||
conductance[0] = .002 * abs(direction)
|
||||
return dict(step=np.array([tick for tick, _ in events], np.int32),
|
||||
neuron_idx=np.array([i for _, i in events], np.int32), counts=np.array(counts, np.int32),
|
||||
v=np.full(6, -.052, np.float64), g=conductance, ref=np.zeros(6, np.int32))
|
||||
|
||||
|
||||
def states(conditioned=C, strength=0, *, neutral_strength=0, downstream=True):
|
||||
neutral = next(cue for cue in g.M.CUES if cue != conditioned)
|
||||
return {conditioned: state(strength, downstream=downstream), neutral: state(neutral_strength, downstream=downstream)}
|
||||
|
||||
|
||||
def pair(reg, block, label, values, *, delta, checkpoint, policy='common_frozen_reset'):
|
||||
return dict(schema=g.PAIR_SCHEMA, block_id=block, snapshot_id=f'{block}/{label}',
|
||||
receipt_sha256=sha(f'{block}/{label}/pair'),
|
||||
probe_receipt_sha256={cue: sha(f'{block}/{label}/probe/{cue}') for cue in g.M.CUES},
|
||||
evaluation_input_sha256=dict(reg['blocks'][block]['evaluation_input_sha256']),
|
||||
state_raw_sha256={cue: g.M.validate_state(values[cue], nodes=NODES, steps=1200)['hashes'] for cue in g.M.CUES},
|
||||
states=values, state_policy=policy, source_checkpoint_sha256=checkpoint, delta_sha256=delta,
|
||||
probe_steps=1200, cs_start_tick=0, cs_stop_tick_exclusive=1000, US_requested=False,
|
||||
weight_updates_enabled=False, feedback_to_training_or_idle=False)
|
||||
|
||||
|
||||
def rebind(pair_value):
|
||||
pair_value['state_raw_sha256'] = {cue: g.M.validate_state(pair_value['states'][cue], nodes=NODES, steps=1200)['hashes']
|
||||
for cue in g.M.CUES}
|
||||
|
||||
|
||||
def execution(block, arm, cue, *, initial=None):
|
||||
return dict(receipt_sha256=sha(f'{block}/{arm}/execution'), recording_verified=True, complete=True,
|
||||
completed_epochs=100, reinforcement_opportunities=50, terminal_pairings=50, epoch_duration_ms=120.,
|
||||
cs_duration_ms=100., us_tick=900, initial_delta_sha256=initial or sha('zero-delta'),
|
||||
terminal_delta_sha256=sha(f'{block}/{arm}/delta'), terminal_checkpoint_sha256=sha(f'{block}/{arm}/terminal'),
|
||||
neural_state_policy='fresh_epoch_delta_only', weight_rule='frozen_temporal_eligibility_v2', reinforced_cue=cue)
|
||||
|
||||
|
||||
def common(reg, block):
|
||||
value = reg['blocks'][block]
|
||||
return dict(replicate_id=block, replicate_unit='independent_training',
|
||||
training_stream_ids=[x['stream_id'] for x in value['training_sources']],
|
||||
evaluation_stream_ids=[value['evaluation_sources'][cue]['stream_id'] for cue in g.M.CUES])
|
||||
|
||||
|
||||
def blocks(reg, mode, dan, cue):
|
||||
return [key for key, value in reg['blocks'].items()
|
||||
if (value['mode'], value['dan_type'], value['conditioned_cue']) == (mode, dan, cue)]
|
||||
|
||||
|
||||
def reversal_rows(reg, mode='physiological', dan='PAM15', cue=C):
|
||||
rows = []
|
||||
neutral = next(x for x in g.M.CUES if x != cue)
|
||||
direction = 1 if dan == 'PAM15' else -1
|
||||
for block in blocks(reg, mode, dan, cue):
|
||||
acq = execution(block, 'acquisition', cue)
|
||||
executions = dict(acquisition=acq,
|
||||
reversal=execution(block, 'reversal', neutral, initial=acq['terminal_delta_sha256']),
|
||||
no_reversal=execution(block, 'no_reversal', cue, initial=acq['terminal_delta_sha256']))
|
||||
row = common(reg, block)
|
||||
row['execution'] = executions
|
||||
row['pre'] = pair(reg, block, 'pre', states(cue), delta=acq['initial_delta_sha256'], checkpoint=sha('reset'))
|
||||
values = dict(acquisition=states(cue, direction), reversal=states(cue, direction, neutral_strength=2 * direction),
|
||||
no_reversal=states(cue, 2 * direction))
|
||||
for arm, value in values.items():
|
||||
e = executions[arm]
|
||||
row[arm] = pair(reg, block, arm, value, delta=e['terminal_delta_sha256'], checkpoint=e['terminal_checkpoint_sha256'])
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
|
||||
def idle(block, branch, cue):
|
||||
source = execution(block, 'paired' if branch == 'trained' else 'frozen', cue)
|
||||
if branch == 'frozen':
|
||||
source['terminal_delta_sha256'] = source['initial_delta_sha256']
|
||||
checkpoints, previous = {}, source['terminal_checkpoint_sha256']
|
||||
for second in (0, 1, 10):
|
||||
current = sha(f'{block}/{branch}/idle-checkpoint/{second}')
|
||||
checkpoints[str(second)] = dict(checkpoint_sha256=current, parent_checkpoint_sha256=previous,
|
||||
elapsed_ticks=second * 10000, absolute_tick=1200 + second * 10000,
|
||||
delta_sha256=source['terminal_delta_sha256'], carry_sha256={key: sha(f'{block}/{branch}/{second}/{key}') for key in g.CARRY})
|
||||
previous = current
|
||||
return dict(source_checkpoint_sha256=source['terminal_checkpoint_sha256'], delta_sha256=source['terminal_delta_sha256'],
|
||||
idle_lineage_id=f'{block}/{branch}/idle10', idle_receipt_sha256=sha(f'{block}/{branch}/idle-receipt'),
|
||||
total_idle_ticks=100000, no_input=True, updates_disabled=True, reset_state=False,
|
||||
analytic_time_advance=False, one_second_is_prefix_of_ten_second=True, checkpoints=checkpoints, source_execution=source)
|
||||
|
||||
|
||||
def retention_rows(reg, mode='physiological', dan='PAM15', cue=C):
|
||||
rows = []
|
||||
direction = 1 if dan == 'PAM15' else -1
|
||||
for block in blocks(reg, mode, dan, cue):
|
||||
row = common(reg, block)
|
||||
row.update(execution={branch: idle(block, branch, cue) for branch in ('trained', 'frozen')}, pre={}, checkpoints={})
|
||||
for branch in ('trained', 'frozen'):
|
||||
e = row['execution'][branch]
|
||||
row['pre'][branch] = pair(reg, block, 'pre-' + branch, states(cue),
|
||||
delta=e['source_execution']['initial_delta_sha256'], checkpoint=sha('reset'))
|
||||
for second in (0, 1, 10):
|
||||
row['checkpoints'][str(second)] = {}
|
||||
for branch in ('trained', 'frozen'):
|
||||
e = row['execution'][branch]
|
||||
row['checkpoints'][str(second)][branch] = pair(reg, block, f'{branch}/{second}',
|
||||
states(cue, direction if branch == 'trained' else 0), delta=e['delta_sha256'],
|
||||
checkpoint=e['checkpoints'][str(second)]['checkpoint_sha256'], policy='continuous_checkpoint')
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
|
||||
def acquisition_rows(reg, mode='physiological', dan='PAM15', cue=C, assay='normal'):
|
||||
rows = []
|
||||
for block in blocks(reg, mode, dan, cue):
|
||||
row = common(reg, block)
|
||||
row.update(assay=assay, mode=mode, dan_type=dan, conditioned_cue=cue, arms={})
|
||||
for arm in g.M.ARMS:
|
||||
strength = (1 if dan == 'PAM15' else -1) if arm == 'paired' else 0
|
||||
metric = g.M.arm_metrics(states(cue), states(cue, strength), conditioned_cue=cue, nodes=NODES, populations=POPS)
|
||||
e = dict(complete=True, recording_verified=True, receipt_sha256=sha(f'{block}/{assay}/{arm}/execution'), assay=assay,
|
||||
epoch_duration_ms=180. if assay == 'delayed' else 120., cs_duration_ms=100., us_tick=1500 if assay == 'delayed' else 900,
|
||||
completed_epochs=150 if arm == 'unpaired' else 100, reinforcement_opportunities=0 if arm == 'CS-only' else 50, terminal_pairings=50)
|
||||
row['arms'][arm] = dict(metrics=metric, execution=e)
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
|
||||
class GatesTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.reg = registry()
|
||||
self.auth = authority(self.reg)
|
||||
|
||||
def evaluate(self, assay, rows, *, mode='physiological', dan='PAM15', cue=C):
|
||||
kwargs = dict(mode=mode, dan_type=dan, conditioned_cue=cue, registry=self.reg, authority=self.auth)
|
||||
if assay in ('normal', 'delayed'):
|
||||
return g.evaluate_acquisition(rows, assay=assay, **kwargs)
|
||||
return getattr(g, 'evaluate_' + assay)(rows, nodes=NODES, populations=POPS, downstream_policy=g.DOWNSTREAM_POLICY, **kwargs)
|
||||
|
||||
def test_registry_checks_real_seed_collision_and_exact_40_cells(self):
|
||||
for mutation in ('eval_train', 'eval_eval', 'train_train', 'duplicate_cell', '63bit', 'boolseed', 'extra_eval', 'missing_block'):
|
||||
reg = registry()
|
||||
values = list(reg['blocks'].values())
|
||||
if mutation == 'eval_train': values[0]['evaluation_sources'][C]['seed'] = values[1]['training_sources'][0]['seed']
|
||||
if mutation == 'eval_eval': values[1]['evaluation_sources'][C]['seed'] = values[0]['evaluation_sources'][C]['seed']
|
||||
if mutation == 'train_train': values[1]['training_sources'][0]['stream_id'] = values[0]['training_sources'][0]['stream_id']
|
||||
if mutation == 'duplicate_cell': values[1]['replicate'] = values[0]['replicate']
|
||||
if mutation == '63bit': values[0]['training_sources'][0]['seed'] = 2**63
|
||||
if mutation == 'boolseed': values[0]['training_sources'][0]['seed'] = True
|
||||
if mutation == 'extra_eval': values[0]['evaluation_sources']['extra'] = values[0]['evaluation_sources'][C]
|
||||
if mutation == 'missing_block': reg['blocks'].pop(next(iter(reg['blocks'])))
|
||||
with self.subTest(mutation=mutation), self.assertRaises(ValueError):
|
||||
g.validate_registry(reg, expected_sha256=g.descriptor_sha256(reg))
|
||||
self.assertEqual(g.validate_registry(self.reg, expected_sha256=self.auth['registry_sha256'])['blocks'], 40)
|
||||
|
||||
def test_registry_hash_and_population_mutation_rejected(self):
|
||||
self.reg['protocol_sha256'] = sha('other')
|
||||
with self.assertRaisesRegex(ValueError, 'changed'):
|
||||
self.evaluate('reversal', reversal_rows(self.reg))
|
||||
self.reg = registry(); self.auth = authority(self.reg)
|
||||
bad = dict(POPS, nonMBONDownstream=np.array([3, 4], np.int32))
|
||||
with self.assertRaises(ValueError):
|
||||
g.evaluate_reversal(reversal_rows(self.reg), mode='physiological', dan_type='PAM15', conditioned_cue=C,
|
||||
registry=self.reg, authority=self.auth, nodes=NODES, populations=bad, downstream_policy=g.DOWNSTREAM_POLICY)
|
||||
|
||||
def test_all_four_assays_both_signs_reciprocal_cues_and_no_claims(self):
|
||||
for assay, factory in (('normal', acquisition_rows), ('delayed', acquisition_rows), ('reversal', reversal_rows), ('retention', retention_rows)):
|
||||
for dan in g.M.DAN_TYPES:
|
||||
for cue in g.M.CUES:
|
||||
rows = factory(self.reg, dan=dan, cue=cue, **({'assay': assay} if assay in ('normal', 'delayed') else {}))
|
||||
result = self.evaluate(assay, rows, dan=dan, cue=cue)
|
||||
with self.subTest(assay=assay, dan=dan, cue=cue):
|
||||
self.assertTrue(result['predicate_pass'])
|
||||
self.assertEqual(result['successful_same_replicate_conjunctions'], 5)
|
||||
self.assertFalse(result['scientific_learning_pass_claimed'])
|
||||
self.assertFalse(result['external_authority_verified'])
|
||||
self.assertFalse(result['data_backed_claimed'])
|
||||
json.dumps(result, allow_nan=False)
|
||||
|
||||
def test_reversal_zero_is_failure_but_legacy_style_inequality_is_true(self):
|
||||
rows = reversal_rows(self.reg)
|
||||
for row in rows:
|
||||
row['reversal']['states'] = states(C, 1, neutral_strength=1); rebind(row['reversal'])
|
||||
result = self.evaluate('reversal', rows)
|
||||
self.assertFalse(result['predicate_pass'])
|
||||
self.assertTrue(all(row['legacy_style_sign_inequality_on_registered_S'] for row in result['replicates']))
|
||||
|
||||
def test_reversal_old_cue_only_and_mbon_only_cannot_satisfy_new_downstream_gate(self):
|
||||
for only_old_cue in (True, False):
|
||||
rows = reversal_rows(self.reg)
|
||||
for row in rows:
|
||||
if only_old_cue:
|
||||
row['reversal']['states'] = states(C, -1)
|
||||
else:
|
||||
row['reversal']['states'][N] = state(2, downstream=False)
|
||||
rebind(row['reversal'])
|
||||
result = self.evaluate('reversal', rows)
|
||||
self.assertFalse(result['predicate_pass'])
|
||||
if not only_old_cue:
|
||||
change = result['replicates'][0]['acquisition_to_reversal_changes_by_cue'][N]['populations']
|
||||
self.assertTrue(change['legacyDownstream']['events_changed'])
|
||||
self.assertFalse(change['nonMBONDownstream']['events_changed'])
|
||||
|
||||
def test_reversal_same_replicate_conjunction_and_exact_three(self):
|
||||
rows = reversal_rows(self.reg)
|
||||
rows[2]['no_reversal']['states'] = states(C, -1); rebind(rows[2]['no_reversal'])
|
||||
rows[3]['reversal']['states'] = states(C, 1, neutral_strength=1); rebind(rows[3]['reversal'])
|
||||
rows[4]['reversal']['states'][N] = state(2, downstream=False); rebind(rows[4]['reversal'])
|
||||
result = self.evaluate('reversal', rows)
|
||||
self.assertEqual(result['successful_same_replicate_conjunctions'], 2)
|
||||
self.assertFalse(result['predicate_pass'])
|
||||
rows[2] = reversal_rows(self.reg)[2]
|
||||
self.assertTrue(self.evaluate('reversal', rows)['predicate_pass'])
|
||||
|
||||
def test_retention_same_replicate_at_both_times_not_separate_time_majorities(self):
|
||||
rows = retention_rows(self.reg)
|
||||
for index, times in ((2, ('10',)), (3, ('1',)), (4, ('1', '10'))):
|
||||
for second in times:
|
||||
p = rows[index]['checkpoints'][second]['trained']
|
||||
p['states'] = states(); rebind(p)
|
||||
result = self.evaluate('retention', rows)
|
||||
self.assertEqual(result['successful_same_replicate_conjunctions'], 2)
|
||||
self.assertFalse(result['predicate_pass'])
|
||||
rows[2] = retention_rows(self.reg)[2]
|
||||
self.assertTrue(self.evaluate('retention', rows)['predicate_pass'])
|
||||
|
||||
def test_retention_frozen_equality_opposite_sign_and_no_nonmbon_change_fail(self):
|
||||
for variant in ('equal_frozen', 'opposite', 'mbon_only'):
|
||||
rows = retention_rows(self.reg)
|
||||
for row in rows:
|
||||
for second in ('1', '10'):
|
||||
pair_value = row['checkpoints'][second]['trained']
|
||||
if variant == 'equal_frozen':
|
||||
pair_value = row['checkpoints'][second]['frozen']; pair_value['states'] = states(C, 1)
|
||||
elif variant == 'opposite': pair_value['states'] = states(C, -1)
|
||||
else: pair_value['states'] = states(C, 1, downstream=False)
|
||||
rebind(pair_value)
|
||||
self.assertFalse(self.evaluate('retention', rows)['predicate_pass'])
|
||||
|
||||
def test_retention_chain_full_state_clock_and_probe_policy_mutations_rejected(self):
|
||||
for variant in ('clock', 'delta', 'parent', 'queue', 'reset', 'analytic', 'prefix', 'missing_time', 'input', 'feedback', 'newUS', 'short_probe', 'fresh_probe', 'raw_state'):
|
||||
rows = retention_rows(self.reg)
|
||||
execution_value = rows[0]['execution']['trained']
|
||||
cp = execution_value['checkpoints']['10']
|
||||
p = rows[0]['checkpoints']['10']['trained']
|
||||
if variant == 'clock': cp['absolute_tick'] += 1
|
||||
if variant == 'delta': cp['delta_sha256'] = sha('changed')
|
||||
if variant == 'parent': cp['parent_checkpoint_sha256'] = execution_value['source_checkpoint_sha256']
|
||||
if variant == 'queue': cp['carry_sha256'].pop('apl_pending')
|
||||
if variant == 'reset': execution_value['reset_state'] = True
|
||||
if variant == 'analytic': execution_value['analytic_time_advance'] = True
|
||||
if variant == 'prefix': execution_value['one_second_is_prefix_of_ten_second'] = False
|
||||
if variant == 'missing_time': rows[0]['checkpoints'].pop('0')
|
||||
if variant == 'input': p['evaluation_input_sha256'][C] = sha('other')
|
||||
if variant == 'feedback': p['feedback_to_training_or_idle'] = True
|
||||
if variant == 'newUS': p['US_requested'] = True
|
||||
if variant == 'short_probe': p['probe_steps'] = 1000
|
||||
if variant == 'fresh_probe': p['state_policy'] = 'common_frozen_reset'
|
||||
if variant == 'raw_state': p['states'][C]['v'][0] += .001
|
||||
with self.subTest(variant=variant), self.assertRaises(ValueError): self.evaluate('retention', rows)
|
||||
|
||||
def test_reversal_delta_lineage_terminal_inventory_and_receipt_mutations_rejected(self):
|
||||
for variant in ('resetdelta', 'early', 'epochs', 'cue', 'receipt', 'snapshot_receipt', 'probeAB', 'evaldraw', 'wrongcell', 'trainstream'):
|
||||
rows = reversal_rows(self.reg)
|
||||
e = rows[0]['execution']['reversal']
|
||||
if variant == 'resetdelta': e['initial_delta_sha256'] = sha('zero')
|
||||
if variant == 'early': e['terminal_pairings'] = 20
|
||||
if variant == 'epochs': e['completed_epochs'] = 99
|
||||
if variant == 'cue': e['reinforced_cue'] = C
|
||||
if variant == 'receipt': e['receipt_sha256'] = rows[0]['execution']['acquisition']['receipt_sha256']
|
||||
if variant == 'snapshot_receipt': rows[0]['reversal']['receipt_sha256'] = rows[0]['acquisition']['receipt_sha256']
|
||||
if variant == 'probeAB': rows[0]['reversal']['probe_receipt_sha256'][N] = rows[0]['reversal']['probe_receipt_sha256'][C]
|
||||
if variant == 'evaldraw': rows[0]['replicate_unit'] = 'evaluation'
|
||||
if variant == 'wrongcell': rows[1]['replicate_id'] = rows[0]['replicate_id']
|
||||
if variant == 'trainstream': rows[0]['training_stream_ids'] = rows[1]['training_stream_ids']
|
||||
with self.subTest(variant=variant), self.assertRaises(ValueError): self.evaluate('reversal', rows)
|
||||
|
||||
def test_acquisition_controls_and_frozen_gate_are_preserved(self):
|
||||
for variant in ('missing_control', 'delayed_timing', 'metric_mutation', 'population'):
|
||||
rows = acquisition_rows(self.reg, assay='delayed')
|
||||
if variant == 'missing_control': rows[0]['arms'].pop('DAN-only')
|
||||
if variant == 'delayed_timing': rows[0]['arms']['frozen']['execution']['us_tick'] = 900
|
||||
if variant == 'metric_mutation': rows[0]['arms']['paired']['metrics']['rawS'] = 999.
|
||||
if variant == 'population': rows[0]['arms']['paired']['metrics']['cues'][C]['nodes_raw_sha256'] = sha('other')
|
||||
with self.subTest(variant=variant), self.assertRaises(ValueError): self.evaluate('delayed', rows)
|
||||
|
||||
def normal_reports(self):
|
||||
return [self.evaluate('normal', acquisition_rows(self.reg, mode, dan, cue), mode=mode, dan=dan, cue=cue)
|
||||
for mode in g.M.MODES for dan in g.M.DAN_TYPES for cue in g.M.CUES]
|
||||
|
||||
def test_cohort_exact_eight_cells_missing_not_run_and_mutation_rejected(self):
|
||||
reports = self.normal_reports()
|
||||
result = g.summarize_cohort(reports, registry=self.reg, authority=self.auth, required_assays=('normal',))
|
||||
self.assertTrue(result['all_functional_predicates_pass'])
|
||||
self.assertFalse(result['legacy_H_and_integrity_gates_included'])
|
||||
missing = g.summarize_cohort(reports[:-1], registry=self.reg, authority=self.auth, required_assays=('normal',))
|
||||
self.assertIsNone(missing['all_functional_predicates_pass'])
|
||||
self.assertEqual(sum(x['status'] == 'NOT-RUN' for x in missing['table']), 1)
|
||||
for variant in ('duplicate', 'predicate', 'conjunction', 'controlgain', 'unsupportedclaim'):
|
||||
changed = copy.deepcopy(reports)
|
||||
if variant == 'duplicate': changed[-1] = changed[0]
|
||||
if variant == 'predicate': changed[0]['predicate_pass'] = False
|
||||
if variant == 'conjunction': changed[0]['replicates'][0]['conjunction_pass'] = False
|
||||
if variant == 'controlgain': next(iter(changed[0]['legacy_control_MBON_gains'].values()))[changed[0]['replicates'][0]['replicate_id']] = 900.
|
||||
if variant == 'unsupportedclaim': changed[0]['scientific_learning_pass_claimed'] = True
|
||||
with self.subTest(variant=variant), self.assertRaises(ValueError):
|
||||
g.summarize_cohort(changed, registry=self.reg, authority=self.auth, required_assays=('normal',))
|
||||
|
||||
def test_legacy_H_mapping_absent_and_both_DAN_control_sources_explicit(self):
|
||||
reports = self.normal_reports()
|
||||
self.assertEqual(g.legacy_h_cohort_audit(reports, registry=self.reg, authority=self.auth, declared_mapping=None)['status'], 'NOT-TESTABLE')
|
||||
good = g.legacy_h_cohort_audit(reports, registry=self.reg, authority=self.auth, declared_mapping=g.H_MAPPING)
|
||||
self.assertEqual(len(good['groups']), 4)
|
||||
self.assertTrue(good['both_pass'])
|
||||
rows = acquisition_rows(self.reg, dan='PPL103')
|
||||
for row in rows:
|
||||
row['arms']['random reward']['metrics'] = g.M.arm_metrics(states(), states(C, -2), conditioned_cue=C, nodes=NODES, populations=POPS)
|
||||
replacement = self.evaluate('normal', rows, dan='PPL103')
|
||||
reports = [replacement if (x['mode'], x['dan_type'], x['conditioned_cue']) == ('physiological', 'PPL103', C) else x for x in reports]
|
||||
result = g.legacy_h_cohort_audit(reports, registry=self.reg, authority=self.auth, declared_mapping=g.H_MAPPING)
|
||||
group = next(x for x in result['groups'] if x['mode'] == 'physiological' and x['conditioned_cue'] == C)
|
||||
self.assertTrue(group['control_sources']['PAM15']['predicate_pass'])
|
||||
self.assertFalse(group['control_sources']['PPL103']['predicate_pass'])
|
||||
self.assertFalse(result['both_pass'])
|
||||
|
||||
def test_full_cohort_recomputes_followup_predicates_and_keeps_assay_majorities_separate(self):
|
||||
reports = []
|
||||
for mode in g.M.MODES:
|
||||
for dan in g.M.DAN_TYPES:
|
||||
for cue in g.M.CUES:
|
||||
for assay, factory in (('normal', acquisition_rows), ('delayed', acquisition_rows),
|
||||
('reversal', reversal_rows), ('retention', retention_rows)):
|
||||
rows = factory(self.reg, mode, dan, cue, **({'assay': assay} if assay in ('normal', 'delayed') else {}))
|
||||
reports.append(self.evaluate(assay, rows, mode=mode, dan=dan, cue=cue))
|
||||
result = g.summarize_cohort(reports, registry=self.reg, authority=self.auth, required_assays=g.ASSAYS)
|
||||
self.assertEqual(len(result['table']), 32)
|
||||
self.assertTrue(result['all_functional_predicates_pass'])
|
||||
for variant in ('reversal_sign', 'reversal_predicate', 'retention_sign', 'retention_predicate', 'retention_time0'):
|
||||
changed = copy.deepcopy(reports)
|
||||
rev = next(x for x in changed if x['assay'] == 'reversal')['replicates'][0]
|
||||
ret = next(x for x in changed if x['assay'] == 'retention')['replicates'][0]
|
||||
if variant == 'reversal_sign': rev['rawS']['reversal'] = 999.
|
||||
if variant == 'reversal_predicate': rev['predicates']['strict_three_signed_relations'] = False
|
||||
if variant == 'retention_sign': ret['times']['10']['rawS_trained'] = 999.
|
||||
if variant == 'retention_predicate': ret['times']['10']['predicates']['beyond_time_matched_frozen'] = False
|
||||
if variant == 'retention_time0': ret['times']['0']['contributes_to_gate'] = True
|
||||
with self.subTest(variant=variant), self.assertRaises(ValueError):
|
||||
g.summarize_cohort(changed, registry=self.reg, authority=self.auth, required_assays=g.ASSAYS)
|
||||
|
||||
def test_frozen_retention_source_cannot_claim_updated_delta(self):
|
||||
rows = retention_rows(self.reg)
|
||||
rows[0]['execution']['frozen']['source_execution']['initial_delta_sha256'] = sha('another-zero')
|
||||
with self.assertRaisesRegex(ValueError, 'Frozen training'):
|
||||
self.evaluate('retention', rows)
|
||||
|
||||
def test_inputs_not_mutated_and_output_does_not_alias_inputs(self):
|
||||
rows = reversal_rows(self.reg)
|
||||
before = copy.deepcopy(rows)
|
||||
result = self.evaluate('reversal', rows)
|
||||
for old, new in zip(before, rows):
|
||||
for snapshot in ('pre', 'acquisition', 'reversal', 'no_reversal'):
|
||||
for cue in g.M.CUES:
|
||||
for key in g.M.STATE_KEYS:
|
||||
np.testing.assert_array_equal(old[snapshot]['states'][cue][key], new[snapshot]['states'][cue][key])
|
||||
result['replicates'][0]['metrics']['acquisition']['rawS'] = 888.
|
||||
self.assertEqual(self.evaluate('reversal', rows)['replicates'][0]['rawS']['acquisition'], 1.)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,129 @@
|
||||
"""Pure temporary preparation integration; all old context/Git/biology mocked.
|
||||
|
||||
No historical files, sampling, brain, source-module execution or GPU is used.
|
||||
Real plan/anatomy/complete-source authentication belongs to separate validation.
|
||||
"""
|
||||
import copy
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import Mock,patch
|
||||
|
||||
import numpy as np
|
||||
|
||||
import prepare_execution as P
|
||||
|
||||
|
||||
def save(path,value):
|
||||
path.parent.mkdir(parents=True,exist_ok=True);path.write_text(json.dumps(value),encoding='utf-8')
|
||||
|
||||
|
||||
class PrepareFixture:
|
||||
def __init__(self,root):
|
||||
self.root=root;self.model=root/'models/conditioning-execution-v1';self.model.mkdir(parents=True)
|
||||
(self.model/'synthetic.py').write_text('# synthetic source only\n')
|
||||
self.exp=root/'experiments/phase4aq-fixture';self.exp.mkdir(parents=True)
|
||||
self.ap=root/'experiments/phase4ap-fixture';self.ap.mkdir()
|
||||
self.ao=root/'experiments/phase4ao-fixture';self.ao.mkdir()
|
||||
self.checkpoint=self.ap/'runs/D1--reference--epoch-001';self.checkpoint.mkdir(parents=True)
|
||||
save(self.checkpoint/'checkpoint-manifest.json',{'synthetic':True})
|
||||
self.before=root/'before.npz';self.bm=root/'before.json'
|
||||
np.savez_compressed(self.before,edge_id=np.array([0],np.int64),plastic_delta_mv=np.array([0.],np.float32));save(self.bm,{'synthetic':'before'})
|
||||
self.mapping=root/'mapping.npz'
|
||||
np.savez_compressed(self.mapping,edge_id=np.array([0],np.int64),source_neuron_idx=np.array([1],np.int32),
|
||||
target_neuron_idx=np.array([2],np.int32),target_compartment_verbatim=np.array(["y5B'2a"]))
|
||||
self.authority=self.ap/'jobs/D1--reference--epoch-001.authority.json'
|
||||
save(self.authority,dict(checkpoint_dir=str(self.checkpoint),checkpoint_manifest_sha256=P.digest(self.checkpoint/'checkpoint-manifest.json'),
|
||||
files={'candidate_map':P.A.pin(self.mapping),'overlay_before':P.A.pin(self.before),'overlay_manifest_before':P.A.pin(self.bm)}))
|
||||
update=self.ap/'updates/D1--reference--epoch-001';update.mkdir(parents=True)
|
||||
for name in ('chain-receipt.json','update-receipt.json','delta-after.npz','overlay-manifest.json'):(update/name).write_bytes(b'synthetic')
|
||||
save(self.ap/'cases/D1--reference--epoch-001/spec.json',{'synthetic':'pinned-template'})
|
||||
static=self.ao/'inputs/static';static.mkdir(parents=True)
|
||||
self.populations=static/'populations.npz'
|
||||
np.savez_compressed(self.populations,PAM15=np.array([3,4,5,6],np.int32),Kenyon_Cell=np.array([1],np.int32))
|
||||
self.tables={}
|
||||
for cue in ('A','B'):
|
||||
self.tables[cue]={'targets':np.array([10,11],np.int32),'rates_hz':np.array([1.,2.],np.float32)}
|
||||
np.savez_compressed(static/(cue+'-rates.npz'),**self.tables[cue])
|
||||
self.fullplan=self.ao/'protocol/full-trial-plan.json';save(self.fullplan,{'synthetic':'not sampled'})
|
||||
pins={str(p):P.digest(p) for p in (self.before,self.bm,self.mapping,self.populations,self.fullplan)}
|
||||
self.reg=dict(input_sha256=pins,source_sha256={},prepared_file_sha256={},
|
||||
initial_overlay={'overlay_file':str(self.before),'overlay_manifest':str(self.bm)})
|
||||
self.plan=dict(imported_parents={'D1':dict(role='AP.D1.reference.epoch001',checkpoint_manifest=str(self.checkpoint/'checkpoint-manifest.json'),
|
||||
sha256=P.digest(self.checkpoint/'checkpoint-manifest.json'))},initial_overlay={'overlay_file':P.A.pin(self.before),'overlay_manifest':P.A.pin(self.bm)},
|
||||
calls=[{'call_id':'ref','case_group':'shared'},{'call_id':'light','case_group':'shared'}])
|
||||
self.old=SimpleNamespace(C=SimpleNamespace(load_checkpoint=Mock(return_value={'fresh':True,'steps':1200})),
|
||||
helper=lambda:SimpleNamespace(verify_seal=Mock(return_value={'synthetic_verified':True})),
|
||||
previous_integrity=Mock(return_value={'synthetic_old_checksum':True}))
|
||||
self.inputs=SimpleNamespace(load_rate_tables=Mock(return_value={'tables':copy.deepcopy(self.tables),'audit':{'synthetic_no_sampler':True}}))
|
||||
self.mechanical=Mock(return_value=({'tick':np.array([1199],np.int32),'neuron_idx':np.array([1],np.int32)}, {'synthetic':True}))
|
||||
self.planobj=SimpleNamespace(build_plan=lambda:copy.deepcopy(self.plan),validate_plan=Mock(return_value=True),
|
||||
derive_case_spec=lambda template,call_id,**kw:{'steps':1000,'case_group':'shared'},mechanical_requests=self.mechanical)
|
||||
|
||||
def git(self,command):
|
||||
if command[-2:]==['rev-parse','HEAD']:return b'a'*40+b'\n'
|
||||
if command[-2]=='show':return (self.root/command[-1].split(':',1)[1]).read_bytes()
|
||||
raise AssertionError('Unexpected external command')
|
||||
|
||||
def run(self,git=None):
|
||||
with patch.object(P,'ROOT',self.root),patch.object(P,'MODEL',self.model),patch.object(P,'EXP',self.exp), \
|
||||
patch.object(P,'AP',self.ap),patch.object(P,'AO',self.ao),patch.object(P,'PLAN',self.planobj), \
|
||||
patch.object(P,'old_context',return_value=(self.old,self.reg,{})), \
|
||||
patch.object(P.subprocess,'check_output',side_effect=self.git if git is None else git), \
|
||||
patch.object(P.shutil,'disk_usage',return_value=SimpleNamespace(free=100*1024**3)), \
|
||||
patch.dict(sys.modules,{'conditioning_preflight_inputs':self.inputs}):
|
||||
return P.prepare()
|
||||
|
||||
|
||||
class PreparationTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp=tempfile.TemporaryDirectory();self.f=PrepareFixture(Path(self.tmp.name).resolve())
|
||||
def tearDown(self):self.tmp.cleanup()
|
||||
|
||||
def test_exclusive_registration_source_snapshot_and_shared_case(self):
|
||||
sha=self.f.run();reg=P.read(self.f.exp/'protocol/preregistered.json')
|
||||
self.assertEqual(sha,P.digest(self.f.exp/'protocol/preregistered.json'))
|
||||
self.assertEqual(set(reg['case_templates']),{'shared'})
|
||||
self.assertEqual((self.f.exp/'protocol/source-snapshot/synthetic.py').read_bytes(),(self.f.model/'synthetic.py').read_bytes())
|
||||
self.assertFalse(reg['brain_or_sampler_run_during_preparation']);self.assertFalse(reg['future_hashes_fabricated'])
|
||||
self.assertFalse(reg['scientific_acquisition_authorized']);self.assertFalse(reg['learning_success_claimed'])
|
||||
self.f.inputs.load_rate_tables.assert_called_once_with(self.f.root)
|
||||
self.f.old.C.load_checkpoint.assert_called_once_with(self.f.checkpoint,self.f.plan['imported_parents']['D1']['sha256'])
|
||||
with self.assertRaisesRegex(ValueError,'empty experiment'):self.f.run()
|
||||
|
||||
def test_uncommitted_source_blob_rejected_before_new_outputs(self):
|
||||
def mismatch(command):return b'a'*40+b'\n' if command[-2:]==['rev-parse','HEAD'] else b'wrong committed source'
|
||||
with self.assertRaisesRegex(ValueError,'committed blob'):self.f.run(git=mismatch)
|
||||
self.assertEqual(list(self.f.exp.iterdir()),[])
|
||||
|
||||
def test_shared_template_must_be_fully_equal(self):
|
||||
self.f.planobj.derive_case_spec=lambda template,call_id,**kw:{'steps':1000,'wrong_mode_leak':call_id}
|
||||
with self.assertRaisesRegex(ValueError,'Shared comparison case templates differ'):self.f.run()
|
||||
self.assertFalse((self.f.exp/'protocol/preregistered.json').exists())
|
||||
|
||||
def test_pinned_rate_arrays_need_dtype_and_bits_not_json_similarity(self):
|
||||
self.f.inputs.load_rate_tables.return_value['tables']['A']['rates_hz']=self.f.tables['A']['rates_hz'].astype(np.float64)
|
||||
with self.assertRaisesRegex(ValueError,'PN mapping differs'):self.f.run()
|
||||
self.assertFalse((self.f.exp/'protocol/preregistered.json').exists())
|
||||
|
||||
def test_candidate_source_outside_KC_is_not_silently_selected(self):
|
||||
np.savez_compressed(self.f.populations,PAM15=np.array([3,4,5,6],np.int32),Kenyon_Cell=np.array([99],np.int32))
|
||||
self.f.reg['input_sha256'][str(self.f.populations)]=P.digest(self.f.populations)
|
||||
with self.assertRaisesRegex(ValueError,'outside original KC'):self.f.run()
|
||||
|
||||
def test_imported_parent_authority_must_match_selected_checkpoint(self):
|
||||
value=P.read(self.f.authority);value['checkpoint_manifest_sha256']='f'*64;save(self.f.authority,value)
|
||||
with self.assertRaisesRegex(ValueError,'selected parent'):self.f.run()
|
||||
self.assertFalse((self.f.exp/'protocol/preregistered.json').exists())
|
||||
|
||||
def test_no_bytecode_or_nested_source_dirs_in_inventory(self):
|
||||
with patch.object(P,'MODEL',self.f.model):
|
||||
self.assertEqual(len(P.source_inventory()),1)
|
||||
(self.f.model/'__pycache__').mkdir()
|
||||
with self.assertRaisesRegex(ValueError,'source files'):P.source_inventory()
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,573 @@
|
||||
"""Synthetic CPU admission/state/AST tests only. No GPU or scientific input."""
|
||||
import ast
|
||||
import copy
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
from types import SimpleNamespace, ModuleType
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
|
||||
import updated_continuation as m
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
AJ = ROOT / 'apl-timing-lab-v1/gpu_timing.py'
|
||||
|
||||
|
||||
def save(path, value):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(value, sort_keys=True, allow_nan=False), encoding='utf-8')
|
||||
|
||||
|
||||
def pin(path):
|
||||
return dict(path=str(path), sha256=m._digest(path))
|
||||
|
||||
|
||||
class ArrayTarget:
|
||||
def __init__(self, a):
|
||||
self.a = np.array(a, copy=True)
|
||||
|
||||
def copy_(self, a):
|
||||
self.a[...] = a
|
||||
|
||||
def any(self):
|
||||
return np.asarray(self.a.any())
|
||||
|
||||
def detach(self):
|
||||
return self
|
||||
|
||||
def cpu(self):
|
||||
return self
|
||||
|
||||
def numpy(self):
|
||||
return self.a
|
||||
|
||||
|
||||
def tiny_parent():
|
||||
parent = dict(global_next_tick=41, state=dict(v=np.array([-.051, -.047], np.float64),
|
||||
g=np.array([-0., .00013], np.float64), ref=np.array([22, 3], np.int32)),
|
||||
terminal=dict(spike_ring=np.zeros((19, 2), np.uint8), next_tick=np.asarray(5, np.int64),
|
||||
apl_pending=np.arange(36, dtype=np.float32).reshape(18, 2), apl_state=np.array([.5, 1.], np.float32)))
|
||||
parent['terminal']['spike_ring'][4, 1] = 1
|
||||
return parent
|
||||
|
||||
|
||||
class RuntimeTests(unittest.TestCase):
|
||||
def runtime(self):
|
||||
obj = object.__new__(m.UpdatedRuntime)
|
||||
obj.parent, obj.installations, obj.restorations = tiny_parent(), 1, 0
|
||||
obj.authority = {'value': {'expected_effective_weight_after_sha256': 'a'*64}}
|
||||
obj.torch = SimpleNamespace(float64=np.float64, float32=np.float32, int32=np.int32, uint8=np.uint8)
|
||||
return obj
|
||||
|
||||
def targets(self):
|
||||
state = [ArrayTarget(np.zeros(2, dtype)) for dtype in (np.float64, np.float64, np.int32, np.int32)]
|
||||
return [*state, ArrayTarget(np.zeros((19, 2), np.uint8)), ArrayTarget(np.zeros((18, 2), np.float32)),
|
||||
SimpleNamespace(state=ArrayTarget(np.zeros(2, np.float32))), lambda a, dtype: np.array(a, dtype=dtype)]
|
||||
|
||||
def test_restore_all_bytes_and_no_retroactive_g_rescale(self):
|
||||
obj, args = self.runtime(), self.targets()
|
||||
before = {name:a.tobytes() for name,a in obj.parent['state'].items()}
|
||||
obj.restore(*args)
|
||||
self.assertEqual(args[1].a.tobytes(), before['g'])
|
||||
self.assertEqual(args[0].a.tobytes(), before['v'])
|
||||
self.assertEqual(args[2].a.tobytes(), before['ref'])
|
||||
self.assertFalse(args[3].a.any())
|
||||
self.assertTrue(m._same(args[4].a, m.C.rotate_spike_ring(obj.parent['terminal']['spike_ring'], 5)))
|
||||
self.assertTrue(m._same(args[5].a, obj.parent['terminal']['apl_pending']))
|
||||
self.assertTrue(m._same(args[6].state.a, obj.parent['terminal']['apl_state']))
|
||||
self.assertFalse(obj.restore_audit['existing_g_rescaled'])
|
||||
self.assertTrue(obj.restore_audit['pending_spike_arrivals_use_current_installed_weight'])
|
||||
self.assertEqual(before, {name:a.tobytes() for name,a in obj.parent['state'].items()})
|
||||
with self.assertRaisesRegex(ValueError, 'once'):
|
||||
obj.restore(*args)
|
||||
|
||||
def test_restore_rejects_nonzero_counts_or_before_installation(self):
|
||||
obj, args = self.runtime(), self.targets()
|
||||
obj.installations = 0
|
||||
with self.assertRaises(ValueError): obj.restore(*args)
|
||||
obj.installations = 1
|
||||
args[3].a[0] = 1
|
||||
with self.assertRaisesRegex(ValueError, 'counts'): obj.restore(*args)
|
||||
|
||||
def test_copy_corruption_is_not_hidden_by_receipt(self):
|
||||
obj, args = self.runtime(), self.targets()
|
||||
args[1].copy_ = lambda value: args[1].a.fill(0.)
|
||||
with self.assertRaisesRegex(ValueError, 'state bytes: g'): obj.restore(*args)
|
||||
|
||||
def test_authorized_new_hash_not_parent_old_hash_and_no_double_install(self):
|
||||
obj = self.runtime(); obj.installations = 0
|
||||
def synthetic_original_install(target, *args, **kwargs):
|
||||
target.installations += 1
|
||||
target.effective_sha = 'a'*64
|
||||
obj.parent['summary'] = {'effective_weights_raw_sha256':'b'*64}
|
||||
with patch.object(m.R._Runtime, 'install', synthetic_original_install):
|
||||
obj.install(None)
|
||||
self.assertEqual(obj.installations, 1)
|
||||
with self.assertRaisesRegex(ValueError, 'Double'): obj.install(None)
|
||||
obj.installations = 0
|
||||
obj.authority['value']['expected_effective_weight_after_sha256'] = 'c'*64
|
||||
with patch.object(m.R._Runtime, 'install', synthetic_original_install):
|
||||
with self.assertRaisesRegex(ValueError, 'authorized after'): obj.install(None)
|
||||
|
||||
def test_actual_source_AST_keeps_only_frozen_restore_and_admission(self):
|
||||
for mode in ('reference', 'light'):
|
||||
aj = ModuleType('synthetic_aj'); aj.__file__ = str(AJ)
|
||||
old = dict(aj.__dict__)
|
||||
runtime = SimpleNamespace(write_json=lambda *_:None, audit_sequence=lambda *_:None)
|
||||
function, audit = m.compile_updated(aj, runtime, mode)
|
||||
self.assertTrue(audit['full_AST_rollback_identical'])
|
||||
self.assertTrue(audit['kernels_sorting_and_local_ring_math_unchanged'])
|
||||
self.assertEqual(old, aj.__dict__)
|
||||
self.assertIs(function.__globals__['_runtime'], runtime)
|
||||
self.assertIs(function.__globals__['_continuation'], runtime)
|
||||
self.assertEqual(function.__globals__['__file__'], str(Path(m.__file__).resolve()))
|
||||
|
||||
def test_pending_source_uses_new_weight_and_old_APL_sample(self):
|
||||
# Independent numerical toy: a source emitted before boundary arrives
|
||||
# afterwards; no captured edge weight is stored in the source ring.
|
||||
for cut in (5, 17, 18, 19, 20, 41):
|
||||
source_tick = cut - 1
|
||||
ring = np.zeros((19, 2), np.uint8); ring[source_tick % 19, 0] = 1
|
||||
child = m.C.rotate_spike_ring(ring, cut)
|
||||
g = np.float64(.00013)
|
||||
delta = np.float32(-.00275)
|
||||
base = np.float64(.000275)
|
||||
after = np.add(base, np.multiply(np.float64(delta), np.float64(.001)))
|
||||
arrived = []
|
||||
for tick in range(19):
|
||||
child[tick % 19] = 0
|
||||
if cut+tick >= 18 and child[(tick-18) % 19, 0]:
|
||||
g = np.add(g, after); arrived.append(tick)
|
||||
self.assertEqual(arrived, [17])
|
||||
self.assertEqual(g.tobytes(), np.add(np.float64(.00013), after).tobytes())
|
||||
self.assertNotEqual(g.tobytes(), np.add(np.float64(.00013), base).tobytes())
|
||||
initial = np.arange(36, dtype=np.float32).reshape(18, 2)
|
||||
generated = np.ones((5, 2), np.float32)
|
||||
joined = np.concatenate((initial, generated))
|
||||
self.assertTrue(m.C.audit_carried_sequence(generated, joined[:5], joined[5:], initial)['pass_all'])
|
||||
source = (ROOT/'author-runtime-lab-v1/author_ext.cu').read_text()
|
||||
self.assertIn('weights[edges[j]]', source)
|
||||
|
||||
|
||||
class AdmissionFixture:
|
||||
"""Private tiny input scaffolding. Actual production loaders are mocked."""
|
||||
def __init__(self, root):
|
||||
self.root=root; self.case=root/'case'; self.case.mkdir()
|
||||
self.parentdir=root/'parent'; self.parentdir.mkdir()
|
||||
self.graph=root/'graph'; self.graph.mkdir(); self.apl=root/'apl'; self.apl.mkdir()
|
||||
self.coeff=root/'coeff.json'; save(self.coeff, {})
|
||||
for name in m.GRAPH_FILES: (self.graph/name).write_bytes(b'synthetic graph '+name.encode())
|
||||
for name in m.APL_FILES: (self.apl/name).write_bytes(b'synthetic apl '+name.encode())
|
||||
self.before=root/'before.npz'; self.before.write_bytes(b'before snapshot')
|
||||
self.bm=root/'before.json'; save(self.bm, {'synthetic':True})
|
||||
self.after=root/'after.npz'; self.after.write_bytes(b'after snapshot')
|
||||
self.am=root/'after.json'; save(self.am, {'synthetic':False})
|
||||
(self.parentdir/'overlay-input.npz').write_bytes(self.before.read_bytes())
|
||||
(self.parentdir/'overlay-manifest.json').write_bytes(self.bm.read_bytes())
|
||||
save(self.parentdir/m.MANIFEST, {'synthetic':True})
|
||||
self.parentpin=m._digest(self.parentdir/m.MANIFEST)
|
||||
self.spec=dict(steps=5,max_steps=5,dt_ms=.1,duration_ms=.5,apl_delay_steps=18,
|
||||
record_history=False,within_trial_weight_updates=False,model={'fixed':1},apl={'fixed':2},
|
||||
graph_dir=str(self.graph),apl_bundle_dir=str(self.apl),coefficients_path=str(self.coeff),
|
||||
parent_checkpoint_manifest_sha256=self.parentpin,global_tick_offset=41)
|
||||
save(self.case/'spec.json',self.spec)
|
||||
np.savez_compressed(self.case/'requests.npz',tick=np.empty(0,np.int32),neuron_idx=np.empty(0,np.int32))
|
||||
lab=ROOT/'olfactory-conditioning-lab-v1'
|
||||
self.sources={name:lab/(name.removesuffix('_source')+'.py') for name in m.SOURCE_PINS}
|
||||
self.sources['phase4j_source']=ROOT/'models/male-cns-lif/phase4j.py'
|
||||
if not self.sources['phase4j_source'].exists(): self.sources['phase4j_source']=ROOT/'mb-physiology-v1/phase4j.py'
|
||||
self.sources['am_overlay_source']=ROOT/'wholebrain-plastic-interface-v1/overlay.py'
|
||||
self.sources['eligibility_bridge_source']=ROOT/'wholebrain-plastic-interface-v1/eligibility_bridge.py'
|
||||
self.sources['updated_continuation_source']=Path(m.__file__).resolve()
|
||||
self.sources['cpu_validator_source']=Path(m.__file__).resolve().parent/'validate_update_cpu.py'
|
||||
frozen={str(p):m._digest(p) for p in [*(self.graph/n for n in m.GRAPH_FILES),*(self.apl/n for n in m.APL_FILES),self.coeff]}
|
||||
frozen.update({str((ROOT/relative).resolve()):sha for relative,sha in m.R.PINS.items()})
|
||||
self.value=dict(schema=m.SCHEMA,boundary_id='synthetic',registration_sha256='a'*64,
|
||||
transition='epoch_update',diagnostic_mode='light',input_policy='empty_idle',
|
||||
case={'spec':pin(self.case/'spec.json'),'requests':pin(self.case/'requests.npz')},
|
||||
parent={'directory':str(self.parentdir),'checkpoint_manifest_sha256':self.parentpin},global_tick_offset=41,
|
||||
overlay_before={'file':pin(self.before),'manifest':pin(self.bm)},overlay_after={'file':pin(self.after),'manifest':pin(self.am)},
|
||||
expected_effective_weight_before_sha256='b'*64,expected_effective_weight_after_sha256='c'*64,
|
||||
update=None,cpu_validation=None,source_files={k:pin(p) for k,p in self.sources.items()},frozen_inputs=frozen)
|
||||
self.path=root/'authority.json'; self.refresh()
|
||||
self.plan={'edge_id':np.array([1],np.int64),'plastic_delta_mv':np.array([0],np.float32),'base_candidate_mv':np.array([.275],np.float32)}
|
||||
self.meta=dict(mask_path=str(root/'mask.npy'),mask_sha256='m'*64,base_candidate_path=str(root/'base.npy'),
|
||||
base_candidate_sha256='d'*64,aj_model_dir=str(ROOT/'apl-timing-lab-v1'),
|
||||
am_overlay_path=str(self.sources['am_overlay_source']),am_overlay_sha256=m.R.AM_OVERLAY_SHA)
|
||||
self.parent=dict(fresh=True,global_tick_offset=0,global_next_tick=41,steps=41,directory=self.parentdir,
|
||||
manifest_sha256=self.parentpin,manifest={'schema':'phase4an-checkpoint-v1'},
|
||||
summary={'effective_weights_raw_sha256':'b'*64,'input_sha256':{'coefficients.json':m._digest(self.coeff),'base_weights.npy':m._digest(self.graph/'weights.npy')}},
|
||||
overlay={'delta_raw_sha256':m.R._raw(self.plan['plastic_delta_mv'])},ancestry_directories=[self.parentdir])
|
||||
self.helper=object()
|
||||
|
||||
def refresh(self): save(self.path,self.value)
|
||||
|
||||
def admit(self, effective=None):
|
||||
with patch.object(m,'load_checkpoint',return_value=self.parent), patch.object(m.C,'_parent_spec',return_value=self.spec), \
|
||||
patch.object(m.R,'load_overlay',return_value=(self.helper,self.plan,self.meta,{})), \
|
||||
patch.object(m,'_expected_effective',side_effect=['b'*64,'c'*64] if effective is None else effective), \
|
||||
patch.object(m,'_epoch_update',return_value={'pass_all':True}) as ep:
|
||||
result=m.validate_authority(self.path,m._digest(self.path))
|
||||
return result,ep.call_count
|
||||
|
||||
|
||||
class AdmissionTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp=tempfile.TemporaryDirectory(); self.f=AdmissionFixture(Path(self.tmp.name).resolve())
|
||||
def tearDown(self): self.tmp.cleanup()
|
||||
|
||||
def test_all_actual_frozen_sources_and_return_contract(self):
|
||||
result,calls=self.f.admit()
|
||||
self.assertEqual(calls,1)
|
||||
for key in ('value','authority','authority_sha256','paths','pins','parent','case_dir','spec','helper',
|
||||
'sources','before_plan','after_plan','before_meta','after_meta'):
|
||||
self.assertIn(key,result)
|
||||
self.assertEqual(result['update_root_authority_sha256'],m._digest(self.f.path))
|
||||
self.assertNotIn('torch',result)
|
||||
|
||||
def test_wrong_absolute_clock_and_wrong_case_parent(self):
|
||||
for field,new in (('global_tick_offset',40),('parent_checkpoint_manifest_sha256','f'*64)):
|
||||
with self.subTest(field=field):
|
||||
original=copy.deepcopy(self.f.spec)
|
||||
self.f.spec[field]=new;save(self.f.case/'spec.json',self.f.spec)
|
||||
self.f.value['case']['spec']=pin(self.f.case/'spec.json');self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'Case parent/clock'):self.f.admit()
|
||||
self.f.spec=original;save(self.f.case/'spec.json',original)
|
||||
self.f.value['case']['spec']=pin(self.f.case/'spec.json');self.f.refresh()
|
||||
self.f.value['global_tick_offset']=42;self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'absolute continuation clock'):self.f.admit()
|
||||
|
||||
def test_second_update_is_rejected(self):
|
||||
self.f.parent['fresh']=False
|
||||
with self.assertRaisesRegex(ValueError,'only once'):self.f.admit()
|
||||
|
||||
def test_authority_hash_and_actual_before_copy_not_self_asserted(self):
|
||||
with self.assertRaisesRegex(ValueError,'changed'):
|
||||
m.validate_authority(self.f.path,'e'*64)
|
||||
(self.f.parentdir/'overlay-input.npz').write_bytes(b'wrong bytes')
|
||||
with self.assertRaisesRegex(ValueError,'Before snapshot'):self.f.admit()
|
||||
|
||||
def test_empty_idle_rejects_requests_probe_does_not_claim_semantics(self):
|
||||
np.savez_compressed(self.f.case/'requests.npz',tick=np.array([0],np.int32),neuron_idx=np.array([1],np.int32))
|
||||
self.f.value['case']['requests']=pin(self.f.case/'requests.npz');self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'empty_idle'):self.f.admit()
|
||||
self.f.value['input_policy']='externally_pinned_CS_probe';self.f.refresh()
|
||||
self.assertEqual(self.f.admit()[0]['value']['input_policy'],'externally_pinned_CS_probe')
|
||||
|
||||
def test_extra_fields_or_source_replacement_fail(self):
|
||||
self.f.value['trust_me']=True;self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'schema'):self.f.admit()
|
||||
del self.f.value['trust_me']
|
||||
self.f.value['source_files']['conditioning_update_source']['sha256']='f'*64;self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'Frozen source'):self.f.admit()
|
||||
|
||||
def test_missing_compiled_pin_not_accepted(self):
|
||||
del self.f.value['frozen_inputs'][str((ROOT/'author-runtime-lab-v1/author_ext.cu').resolve())];self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'dependency authority'):self.f.admit()
|
||||
|
||||
def test_identical_CPU_validator_copy_is_not_the_actual_executor_path(self):
|
||||
copied=self.f.root/'validator-copy.py'
|
||||
copied.write_bytes(self.f.sources['cpu_validator_source'].read_bytes())
|
||||
self.f.value['source_files']['cpu_validator_source']=pin(copied);self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'validator source path'):self.f.admit()
|
||||
|
||||
def idle(self):
|
||||
self.f.value.update(transition='idle',update=None,cpu_validation=None,
|
||||
expected_effective_weight_after_sha256='b'*64,overlay_after=copy.deepcopy(self.f.value['overlay_before']))
|
||||
self.f.parent.update(fresh=False,manifest={'schema':m.CHECKPOINT_SCHEMA},input_policy='empty_idle',
|
||||
update_root_authority_sha256='e'*64)
|
||||
self.f.refresh()
|
||||
|
||||
def test_idle_retains_original_update_root_no_E_or_cpu_recompute(self):
|
||||
self.idle()
|
||||
result,calls=self.f.admit(['b'*64,'b'*64])
|
||||
self.assertEqual(calls,0)
|
||||
self.assertEqual(result['update_root_authority_sha256'],'e'*64)
|
||||
self.assertIsNone(result['paths']['epoch_authority'])
|
||||
self.assertIsNone(result['paths']['cpu_validation'])
|
||||
|
||||
def test_probe_parent_cannot_flow_back_into_idle_or_another_probe(self):
|
||||
self.idle();self.f.parent['input_policy']='externally_pinned_CS_probe'
|
||||
for policy in ('empty_idle','externally_pinned_CS_probe'):
|
||||
self.f.value['input_policy']=policy;self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'probe branch'):self.f.admit(['b'*64,'b'*64])
|
||||
|
||||
def test_idle_cannot_authorize_a_second_snapshot_change(self):
|
||||
self.idle()
|
||||
self.f.value['overlay_after']={'file':pin(self.f.after),'manifest':pin(self.f.am)};self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'Idle changed'):self.f.admit(['b'*64,'b'*64])
|
||||
self.idle();self.f.value['update']={};self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'no new update'):self.f.admit(['b'*64,'b'*64])
|
||||
|
||||
def test_wrong_expected_weight_hash(self):
|
||||
self.f.value['expected_effective_weight_after_sha256']='e'*64;self.f.refresh()
|
||||
with self.assertRaisesRegex(ValueError,'After effective'):self.f.admit()
|
||||
|
||||
def test_output_and_build_reject_entire_ancestry_before_Torch(self):
|
||||
admitted,_=self.f.admit()
|
||||
ancestor=self.f.root/'ancestor';ancestor.mkdir()
|
||||
admitted['parent']['ancestry_directories'].append(ancestor)
|
||||
for output,build in ((ancestor/'out',self.f.root/'build'),(self.f.root/'out',ancestor/'build')):
|
||||
with patch.object(m,'validate_authority',return_value=admitted),patch.object(m.R,'_load') as loader:
|
||||
with self.assertRaises(ValueError):m.run(self.f.path,m._digest(self.f.path),output,build)
|
||||
loader.assert_not_called()
|
||||
self.assertFalse(output.exists());self.assertFalse(build.exists())
|
||||
|
||||
def test_dtype_sorting_and_request_schema_reject(self):
|
||||
for ticks,nodes in ((np.array([0],np.int64),np.array([1],np.int32)),
|
||||
(np.array([1,0],np.int32),np.array([1,1],np.int32)),
|
||||
(np.array([5],np.int32),np.array([1],np.int32))):
|
||||
np.savez_compressed(self.f.case/'requests.npz',tick=ticks,neuron_idx=nodes)
|
||||
with self.assertRaises(ValueError):m._requests(self.f.case/'requests.npz',self.f.spec,'externally_pinned_CS_probe')
|
||||
|
||||
|
||||
class CheckpointDispatchTests(unittest.TestCase):
|
||||
def test_old_checkpoint_is_honestly_dispatched_to_old_C(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root=Path(tmp);save(root/m.MANIFEST,{'schema':'phase4an-checkpoint-v1'})
|
||||
with patch.object(m.C,'load_checkpoint',return_value={'fresh':True}) as old:
|
||||
self.assertEqual(m.load_checkpoint(root,m._digest(root/m.MANIFEST)),{'fresh':True})
|
||||
old.assert_called_once()
|
||||
|
||||
def test_new_checkpoint_cannot_copy_old_provenance(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root=Path(tmp)
|
||||
save(root/'runtime-provenance.json',{'schema':'phase4an-continuation-runtime-v1','complete':True})
|
||||
with self.assertRaisesRegex(ValueError,'genuine new'):m._record(root,{root})
|
||||
|
||||
def test_new_checkpoint_cycle_and_wrong_external_pin(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root=Path(tmp).resolve();save(root/m.MANIFEST,{'schema':m.CHECKPOINT_SCHEMA})
|
||||
with self.assertRaisesRegex(ValueError,'External checkpoint'):m.load_checkpoint(root,'e'*64)
|
||||
with self.assertRaisesRegex(ValueError,'cycle'):m.load_checkpoint(root,m._digest(root/m.MANIFEST),_seen={root})
|
||||
|
||||
|
||||
class NewCheckpointFixture:
|
||||
def __init__(self, f):
|
||||
self.f=f;self.admitted,_=f.admit();self.out=f.root/'new-output';self.out.mkdir()
|
||||
self.parent=self.admitted['parent'];self.parent.update(tiny_parent())
|
||||
self.state=dict(step=np.array([0],np.int32),neuron_idx=np.array([1],np.int32),counts=np.array([0,1],np.int32),
|
||||
v=np.array([-.05,-.052],np.float64),g=np.array([0.,-.003],np.float64),ref=np.array([0,18],np.int32))
|
||||
# Production APL dimensions, tiny canonical neural dimension only in tests.
|
||||
self.parent['terminal']['apl_pending']=np.zeros((18,4064),np.float32)
|
||||
self.parent['terminal']['apl_pending'][1,0]=np.float32(.5)
|
||||
ring=m.C.rotate_spike_ring(self.parent['terminal']['spike_ring'],5)
|
||||
for tick in range(5):ring[tick]=0
|
||||
ring[0,1]=1
|
||||
self.terminal=dict(spike_ring=ring,apl_pending=np.zeros((18,4064),np.float32),
|
||||
apl_state=np.array([1.,2.],np.float32),next_tick=np.asarray(5,np.int64))
|
||||
np.savez_compressed(self.out/'state.npz',**self.state)
|
||||
np.savez_compressed(self.out/'terminal-queues.npz',**self.terminal)
|
||||
np.save(self.out/'apl-pending-tail.float32.npy',self.terminal['apl_pending'])
|
||||
save(self.out/'apl-timing-audit.json',dict(pending_raw_sha256=m.R._raw(self.terminal['apl_pending']),
|
||||
apl_delay_steps=18,brain_tail_advanced=False,final_apl_state_u32_bits=self.terminal['apl_state'].view(np.uint32).tolist(),
|
||||
global_tick_offset=41,global_next_tick=46,initial_queue_raw_sha256=m.R._raw(self.parent['terminal']['apl_pending'])))
|
||||
self.summary=dict(complete=True,pass_all=True,all_finite=True,steps=5,completed_ticks=5,nodes=2,edges=6,
|
||||
precision='float64',apl_precision='float32',within_trial_weight_updates=False,checkpoint_continuation_used=True,
|
||||
global_tick_offset=41,global_next_tick=46,explicit_steps_executed=5,max_steps=5,hidden_early_stop=False,
|
||||
entire_neural_trial_executed=True,record_history=False,counts_scope='segment_only_not_lifetime',event_tick_scope='segment_local',
|
||||
weight_update_at_boundary_authorized=True,frozen_same_weight_retention_claimed=False,
|
||||
parent_checkpoint_manifest_sha256=self.parent['manifest_sha256'],diagnostic_mode='light',
|
||||
boundary_authority_sha256=self.admitted['authority_sha256'],update_root_authority_sha256=self.admitted['update_root_authority_sha256'],
|
||||
updated_boundary_schema=m.SCHEMA,boundary_transition='epoch_update',input_policy='empty_idle',effective_weights_raw_sha256='c'*64,
|
||||
input_sha256={'spec.json':m._digest(f.case/'spec.json'),'requests.npz':m._digest(f.case/'requests.npz'),
|
||||
'base_weights.npy':m._digest(f.graph/'weights.npy'),'coefficients.json':m._digest(f.coeff)})
|
||||
save(self.out/'summary.json',self.summary)
|
||||
save(self.out/'finite-audit.json',dict(all_finite=True,first_failure_tick=-1,finite_observed_ticks=5))
|
||||
save(self.out/'overlay-audit.json',dict(complete=True,weights_updated_during_run=False,effective_weights_raw_sha256='c'*64,
|
||||
delta_raw_sha256=m.R._raw(f.plan['plastic_delta_mv']),mask_sha256=m.R.MASK_SHA,am_helper_sha256=m.R.AM_OVERLAY_SHA))
|
||||
(self.out/'overlay-input.npz').write_bytes(f.after.read_bytes())
|
||||
(self.out/'overlay-manifest.json').write_bytes(f.am.read_bytes())
|
||||
_,audit=m.C.derive_continued(AJ.read_bytes(),'light')
|
||||
self.provenance=dict(schema=m.PROVENANCE_SCHEMA,complete=True,mode='light',source_file=str(Path(m.__file__).resolve()),
|
||||
source_sha256=m._digest(m.__file__),authority_file=str(f.path),authority_sha256=self.admitted['authority_sha256'],ast=audit,
|
||||
input_sha256=self.admitted['pins'],old_globals_patched=False,weights_updated_during_run=False,U_recomputed_here=False,
|
||||
learning_pass_claimed=False,parent_checkpoint_manifest_sha256=f.parentpin,global_tick_offset=41,global_next_tick=46,
|
||||
external_CPU_validation_receipt_bound=True,external_registration_process_and_probe_semantics_verified_here=False)
|
||||
restored=dict(v=self.parent['state']['v'],g=self.parent['state']['g'],ref=self.parent['state']['ref'],
|
||||
spike_ring=m.C.rotate_spike_ring(self.parent['terminal']['spike_ring'],5),apl_pending=self.parent['terminal']['apl_pending'],
|
||||
apl_state=self.parent['terminal']['apl_state'])
|
||||
save(self.out/'boundary-restore-audit.json',dict(restored_raw_sha256={k:m.R._raw(a) for k,a in restored.items()},
|
||||
all_state_and_queue_bytes_exact=True,existing_g_rescaled=False,retroactive_arrival_reweighting=False,
|
||||
pending_spike_arrivals_use_current_installed_weight=True,pending_APL_samples_preserved=True,
|
||||
boundary_installations=1,restorations=1,learning_pass_claimed=False))
|
||||
self.receipt=dict(schema='conditioning-updated-receipt-v1',complete=True,authority_file=str(f.path),
|
||||
authority_sha256=self.admitted['authority_sha256'],parent_checkpoint_dir=str(f.parentdir),parent_checkpoint_manifest_sha256=f.parentpin,
|
||||
global_tick_offset=41,global_next_tick=46,segment_steps=5,update_root_authority_sha256=self.admitted['update_root_authority_sha256'],
|
||||
input_policy='empty_idle',weights_updated_during_run=False,counts_scope='segment_only_not_lifetime',
|
||||
checkpoint_continuation_verified_by_GPU_comparison=False,learning_pass_claimed=False)
|
||||
self.rebind()
|
||||
|
||||
def rebind(self):
|
||||
for key,name in (('summary_sha256','summary.json'),('finite_audit_sha256','finite-audit.json'),
|
||||
('terminal_queues_sha256','terminal-queues.npz'),('overlay_audit_sha256','overlay-audit.json'),('state_sha256','state.npz')):
|
||||
self.provenance[key]=m._digest(self.out/name)
|
||||
save(self.out/'runtime-provenance.json',self.provenance)
|
||||
payload=m.C._tree_hashes(self.out);payload.pop(m.RECEIPT,None)
|
||||
self.receipt['payload_sha256']=payload;save(self.out/m.RECEIPT,self.receipt)
|
||||
|
||||
def record(self):
|
||||
with patch.object(m,'validate_authority',return_value=self.admitted),patch.object(m.C,'N',2),patch.object(m.C,'E',6):
|
||||
return m._record(self.out,{self.out})
|
||||
|
||||
|
||||
class NewCheckpointTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp=tempfile.TemporaryDirectory();self.f=NewCheckpointFixture(AdmissionFixture(Path(self.tmp.name).resolve()))
|
||||
def tearDown(self):self.tmp.cleanup()
|
||||
|
||||
def test_full_payload_exclusive_seal_round_trip(self):
|
||||
self.assertEqual(self.f.record()['global_next_tick'],46)
|
||||
with patch.object(m,'validate_authority',return_value=self.f.admitted),patch.object(m.C,'N',2),patch.object(m.C,'E',6):
|
||||
sealed=m.seal_checkpoint(self.f.out)
|
||||
loaded=m.load_checkpoint(self.f.out,sealed['sha256'])
|
||||
self.assertEqual(loaded['manifest']['schema'],m.CHECKPOINT_SCHEMA)
|
||||
self.assertTrue(m._same(loaded['state']['g'],self.f.state['g']))
|
||||
self.assertFalse(loaded['manifest']['checkpoint_continuation_verified_by_GPU_comparison'])
|
||||
with self.assertRaisesRegex(ValueError,'already sealed'):m.seal_checkpoint(self.f.out)
|
||||
(self.f.out/'extra.json').write_text('{}')
|
||||
with self.assertRaisesRegex(ValueError,'inventory'):m.load_checkpoint(self.f.out,sealed['sha256'])
|
||||
|
||||
def test_rehashed_wrong_parent_and_clock_still_rejected(self):
|
||||
self.f.provenance['parent_checkpoint_manifest_sha256']='f'*64;self.f.rebind()
|
||||
with self.assertRaisesRegex(ValueError,'boundary/clock'):self.f.record()
|
||||
self.f.provenance['parent_checkpoint_manifest_sha256']=self.f.f.parentpin
|
||||
self.f.summary['global_next_tick']=47;save(self.f.out/'summary.json',self.f.summary);self.f.rebind()
|
||||
with self.assertRaisesRegex(ValueError,'global_next_tick'):self.f.record()
|
||||
|
||||
def test_rehashed_changed_unconsumed_queue_rejected(self):
|
||||
self.f.terminal['spike_ring'][18,0]^=np.uint8(1)
|
||||
np.savez_compressed(self.f.out/'terminal-queues.npz',**self.f.terminal);self.f.rebind()
|
||||
with self.assertRaisesRegex(ValueError,'Unwritten carried'):self.f.record()
|
||||
|
||||
def test_rehashed_restoration_g_receipt_not_trusted(self):
|
||||
path=self.f.out/'boundary-restore-audit.json';value=m.R._read_json(path)
|
||||
value['restored_raw_sha256']['g']='f'*64;save(path,value);self.f.rebind()
|
||||
with self.assertRaisesRegex(ValueError,'Boundary restore'):self.f.record()
|
||||
|
||||
def test_actual_state_dtype_rejected_after_rehash(self):
|
||||
self.f.state['g']=self.f.state['g'].astype(np.float32)
|
||||
np.savez_compressed(self.f.out/'state.npz',**self.f.state);self.f.rebind()
|
||||
with self.assertRaisesRegex(ValueError,'parent g'):self.f.record()
|
||||
|
||||
|
||||
class EpochChainFixture:
|
||||
"""Full candidate cardinality and actual metadata bindings; no U execution.
|
||||
|
||||
Q is mocked explicitly: its frozen pure arithmetic has separate tests.
|
||||
This fixture exercises E/CPU file chain and supplied full-array authority.
|
||||
"""
|
||||
def __init__(self,root):
|
||||
self.f=AdmissionFixture(root);f=self.f
|
||||
self.update=root/'postprocess';self.update.mkdir()
|
||||
self.before={'edge_id':np.arange(14232,dtype=np.int64),'plastic_delta_mv':np.zeros(14232,np.float32),
|
||||
'base_candidate_mv':np.full(14232,.275,np.float32)}
|
||||
self.after={k:a.copy() for k,a in self.before.items()};self.after['plastic_delta_mv'][0]=np.float32(-.00275)
|
||||
kc=np.arange(4064,dtype=np.int32);source=(np.arange(14232)%4064).astype(np.int32);target=np.full(14232,4500,np.int32)
|
||||
comp=np.full(14232,"y5B'2a")
|
||||
np.save(f.apl/'kc_globals.npy',kc);np.save(root/'kc.npy',kc);np.save(root/'mask.npy',self.before['edge_id'])
|
||||
np.save(root/'base.npy',self.before['base_candidate_mv']);np.save(f.graph/'src.npy',source);np.save(f.graph/'dst.npy',target)
|
||||
np.savez_compressed(root/'map.npz',edge_id=self.before['edge_id'],source_neuron_idx=source,target_neuron_idx=target,target_compartment_verbatim=comp)
|
||||
np.savez_compressed(f.before,edge_id=self.before['edge_id'],plastic_delta_mv=self.before['plastic_delta_mv'])
|
||||
self.bm={**f.meta,'mask_sha256':m._digest(root/'mask.npy'),'base_candidate_sha256':m._digest(root/'base.npy')}
|
||||
save(f.bm,self.bm)
|
||||
self.afterfile=self.update/'delta-after.npz';np.savez_compressed(self.afterfile,edge_id=self.after['edge_id'],plastic_delta_mv=self.after['plastic_delta_mv'])
|
||||
self.am={**self.bm,'parent_snapshot_sha256':m._digest(f.before)};save(self.update/'overlay-manifest.json',self.am)
|
||||
self.state=dict(step=np.array([0],np.int32),neuron_idx=np.array([0],np.int32),counts=np.array([1],np.int32),
|
||||
v=np.array([-.05]),g=np.array([.001]),ref=np.array([18],np.int32))
|
||||
np.savez_compressed(f.parentdir/'state.npz',**self.state)
|
||||
self.parent=dict(fresh=True,global_tick_offset=0,steps=4,directory=f.parentdir,manifest_sha256=f.parentpin,state=self.state,
|
||||
summary={'diagnostic_mode':'light','effective_weights_raw_sha256':'b'*64},
|
||||
manifest={'files_sha256':{'state.npz':m._digest(f.parentdir/'state.npz')}},provenance={'input_sha256':{}})
|
||||
self.epaths=dict(spec=f.case/'spec.json',requests=f.case/'requests.npz',overlay_before=f.before,overlay_manifest_before=f.bm,
|
||||
state=f.parentdir/'state.npz',kc=root/'kc.npy',canonical_kc=f.apl/'kc_globals.npy',candidate_map=root/'map.npz',
|
||||
mask=root/'mask.npy',base_candidate=root/'base.npy',**{key:f.sources[key] for key in m.E_SOURCE_ROLES})
|
||||
self.epath=root/'epoch-authority.json'
|
||||
frozen={str(p):m._digest(p) for p in [*(f.graph/n for n in m.GRAPH_FILES),*(f.apl/n for n in m.APL_FILES),f.coeff]}
|
||||
frozen.update({str((ROOT/relative).resolve()):sha for relative,sha in m.R.PINS.items()})
|
||||
command=dict(steps=4,compartment="y5B'2a",us_tick=3,d_command=1.,frozen=False,trace_backend='numpy')
|
||||
self.evalue=dict(schema='phase4an-epoch-postprocess-authority-v1',epoch_id='synthetic-e0',diagnostic_mode='light',command=command,
|
||||
checkpoint_dir=str(f.parentdir),checkpoint_manifest_sha256=f.parentpin,files={role:pin(path) for role,path in self.epaths.items()},frozen_inputs=frozen)
|
||||
save(self.epath,self.evalue)
|
||||
self.epins={str(self.epath):m._digest(self.epath),str(f.parentdir/m.MANIFEST):f.parentpin,
|
||||
**{str(p):m._digest(p) for p in self.epaths.values()},**frozen}
|
||||
self.parent['provenance']['input_sha256']={str(self.epaths[k]):m._digest(self.epaths[k]) for k in ('spec','requests','overlay_before','overlay_manifest_before')}
|
||||
arrays=dict(step=self.state['step'],neuron_idx=self.state['neuron_idx'],kc=kc,candidate_edge_id=self.before['edge_id'],
|
||||
candidate_sources=source,candidate_targets=target,candidate_compartments=comp,delta_before=self.before['plastic_delta_mv'],base_candidate=self.before['base_candidate_mv'])
|
||||
self.receipt=dict(input_arrays={k:m._evidence(a) for k,a in arrays.items()},command=dict(steps=4,n_neurons=5000,
|
||||
compartment="y5B'2a",us_tick=3,D_scheduled=1.,frozen=False,trace_backend='numpy'),payload_sha256='d'*64)
|
||||
save(self.update/'update-receipt.json',self.receipt)
|
||||
self.chain=dict(schema='phase4an-epoch-postprocess-chain-v1',complete=True,epoch_id='synthetic-e0',authority_file=str(self.epath),
|
||||
authority_sha256=m._digest(self.epath),coordinator_source_sha256=m.SOURCE_PINS['conditioning_epoch_source'],command=command,
|
||||
diagnostic_mode='light',source_neural_checkpoint_dir=str(f.parentdir),source_neural_checkpoint_manifest_sha256=f.parentpin,
|
||||
before_overlay_file_sha256=m._digest(f.before),before_overlay_manifest_sha256=m._digest(f.bm),
|
||||
after_overlay_file_sha256=m._digest(self.afterfile),after_overlay_manifest_sha256=m._digest(self.update/'overlay-manifest.json'),
|
||||
source_state_file_sha256=m._digest(self.epaths['state']),source_spec_sha256=m._digest(self.epaths['spec']),
|
||||
source_requests_sha256=m._digest(self.epaths['requests']),input_files_sha256=self.epins,
|
||||
output_files_sha256={name:m._digest(self.update/name) for name in m.UPDATE_FILES if name!='chain-receipt.json'},
|
||||
runtime_delta_before_raw_sha256=m.R._raw(self.before['plastic_delta_mv']),runtime_effective_weights_raw_sha256='b'*64,
|
||||
update_receipt_payload_sha256='d'*64,runtime_learned_manifest_loader_verified=True,input_and_checkpoint_bytes_reverified=True,
|
||||
candidate_endpoints_equal_graph=True,KC_equals_supplied_canonical_membership=True,weights_installed=False,
|
||||
brain_executed=False,learning_pass_claimed=False,candidate_generated=False)
|
||||
save(self.update/'chain-receipt.json',self.chain)
|
||||
self.paths=dict(before_overlay=f.before,before_manifest=f.bm,after_overlay=self.afterfile,after_manifest=self.update/'overlay-manifest.json')
|
||||
self.value=dict(update={'epoch_authority':pin(self.epath),'files':{name:pin(self.update/name) for name in m.UPDATE_FILES}})
|
||||
self.cp=root/'cpu-validation.json'
|
||||
self.cpu=dict(schema='conditioning-update-cpu-validation-v1',complete=True,epoch_authority_sha256=m._digest(self.epath),
|
||||
parent_checkpoint_manifest_sha256=f.parentpin,update_files_sha256={name:m._digest(self.update/name) for name in m.UPDATE_FILES},
|
||||
before_overlay_sha256=m._digest(f.before),before_manifest_sha256=m._digest(f.bm),after_overlay_sha256=m._digest(self.afterfile),
|
||||
after_manifest_sha256=m._digest(self.update/'overlay-manifest.json'),before_delta_raw_sha256=m.R._raw(self.before['plastic_delta_mv']),
|
||||
after_delta_raw_sha256=m.R._raw(self.after['plastic_delta_mv']),update_receipt_payload_sha256='d'*64,
|
||||
validator_source=pin(f.sources['cpu_validator_source']),frozen_U_source_sha256=m.SOURCE_PINS['conditioning_update_source'],
|
||||
frozen_U_verify_receipt_recomputed=True,actual_sealed_events_used=True,full_candidate_mapping_verified=True,
|
||||
brain_executed=False,learning_pass_claimed=False)
|
||||
save(self.cp,self.cpu);self.value['cpu_validation']=pin(self.cp)
|
||||
|
||||
def run(self):
|
||||
pins={str(p):m._digest(p) for p in [*self.paths.values(),*self.f.sources.values()]}
|
||||
with patch.object(m,'_Q',return_value=SimpleNamespace(audit_delta_binding=lambda *a,**k:{'pass_all':True})), \
|
||||
patch.object(m.C,'_parent_spec',return_value=self.f.spec),patch.object(m.C,'N',5000):
|
||||
return m._epoch_update(self.value,self.paths,self.f.sources,pins,self.parent,self.before,self.after,self.bm,self.am)
|
||||
|
||||
|
||||
class EpochChainTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp=tempfile.TemporaryDirectory();self.f=EpochChainFixture(Path(self.tmp.name).resolve())
|
||||
def tearDown(self):self.tmp.cleanup()
|
||||
|
||||
def test_full_four_files_actual_inputs_and_cpu_schema_bind(self):
|
||||
self.assertTrue(self.f.run()['pass_all'])
|
||||
|
||||
def test_chain_wrong_parent_rehashed_still_rejected(self):
|
||||
self.f.chain['source_neural_checkpoint_manifest_sha256']='e'*64
|
||||
save(self.f.update/'chain-receipt.json',self.f.chain)
|
||||
self.f.value['update']['files']['chain-receipt.json']=pin(self.f.update/'chain-receipt.json')
|
||||
with self.assertRaisesRegex(ValueError,'Original E chain'):self.f.run()
|
||||
|
||||
def test_cpu_no_recomputation_or_wrong_after_raw_rejected(self):
|
||||
for key,value in (('frozen_U_verify_receipt_recomputed',False),('after_delta_raw_sha256','e'*64)):
|
||||
original=copy.deepcopy(self.f.cpu);self.f.cpu[key]=value;save(self.f.cp,self.f.cpu)
|
||||
self.f.value['cpu_validation']=pin(self.f.cp)
|
||||
with self.assertRaisesRegex(ValueError,'CPU recomputation'):self.f.run()
|
||||
self.f.cpu=original
|
||||
|
||||
def test_update_four_file_hash_changed_or_extra_file(self):
|
||||
(self.f.update/'extra.json').write_text('{}')
|
||||
with self.assertRaisesRegex(ValueError,'four-file'):self.f.run()
|
||||
|
||||
def test_actual_array_not_receipt_booleans_is_checked(self):
|
||||
self.f.parent['state']['step'][0]=1
|
||||
with self.assertRaisesRegex(ValueError,'actual array binding'):self.f.run()
|
||||
|
||||
def test_candidate_endpoint_change_rejected_even_with_same_shape(self):
|
||||
mapping=m.C._npz(self.f.epaths['candidate_map'],('edge_id','source_neuron_idx','target_neuron_idx','target_compartment_verbatim'))
|
||||
mapping['source_neuron_idx'][0]=22
|
||||
np.savez_compressed(self.f.epaths['candidate_map'],**mapping)
|
||||
with self.assertRaisesRegex(ValueError,'changed'):self.f.run()
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,68 @@
|
||||
"""CPU-only chain/mutation/real-source loading tests; no production events."""
|
||||
import copy
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
import validate_update_cpu as V
|
||||
|
||||
|
||||
class ValidationTests(unittest.TestCase):
|
||||
def fixture(self):
|
||||
parent=Path('/synthetic/parent');auth={'epoch_id':'one','command':{'fixture':True},
|
||||
'diagnostic_mode':'reference','checkpoint_manifest_sha256':'2'*64}
|
||||
roles=('state','spec','requests','overlay_before','overlay_manifest_before')
|
||||
paths={r:Path('/synthetic/'+r) for r in roles};pins={p:str(i+3)*64 for i,p in enumerate(paths.values())}
|
||||
hashes={name:format(i+8,'x')*64 for i,name in enumerate(V.FILES)}
|
||||
chain=dict(schema='phase4an-epoch-postprocess-chain-v1',complete=True,
|
||||
weights_installed=False,brain_executed=False,learning_pass_claimed=False,candidate_generated=False,
|
||||
coordinator_source_sha256=V.E_SHA,authority_sha256='1'*64,epoch_id='one',command=auth['command'],
|
||||
diagnostic_mode='reference',source_neural_checkpoint_dir=str(parent),
|
||||
source_neural_checkpoint_manifest_sha256='2'*64,input_files_sha256={str(p):v for p,v in pins.items()},
|
||||
output_files_sha256={n:s for n,s in hashes.items() if n!='chain-receipt.json'},
|
||||
after_overlay_file_sha256=hashes['delta-after.npz'],after_overlay_manifest_sha256=hashes['overlay-manifest.json'])
|
||||
for field,role in (('source_state_file_sha256','state'),('source_spec_sha256','spec'),
|
||||
('source_requests_sha256','requests'),('before_overlay_file_sha256','overlay_before'),
|
||||
('before_overlay_manifest_sha256','overlay_manifest_before')):chain[field]=pins[paths[role]]
|
||||
return chain,auth,'1'*64,pins,paths,parent,hashes
|
||||
|
||||
def test_exact_chain(self):V.chain_binding(*self.fixture())
|
||||
|
||||
def test_wrong_parent_command_or_payload_rejected(self):
|
||||
for field,value in (('source_neural_checkpoint_dir','elsewhere'),('source_neural_checkpoint_manifest_sha256','0'*64),
|
||||
('authority_sha256','0'*64),('command',{}),('before_overlay_file_sha256','0'*64),('source_state_file_sha256','0'*64),
|
||||
('after_overlay_file_sha256','0'*64),('output_files_sha256',{}),('input_files_sha256',{}),('complete',False),
|
||||
('weights_installed',True),('learning_pass_claimed',True),('coordinator_source_sha256','0'*64)):
|
||||
args=list(self.fixture());args[0]=copy.deepcopy(args[0]);args[0][field]=value
|
||||
with self.subTest(field=field),self.assertRaises(ValueError):V.chain_binding(*args)
|
||||
|
||||
def test_bit_identity_includes_signed_zero(self):
|
||||
self.assertTrue(V.same(np.zeros(2,np.float32),np.zeros(2,np.float32)))
|
||||
self.assertFalse(V.same(np.zeros(2,np.float32),np.zeros(2,np.float64)))
|
||||
self.assertFalse(V.same(np.array([0.],np.float32),np.array([-0.],np.float32)))
|
||||
|
||||
def test_source_substitution_rejected_before_exec(self):
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
p=Path(d)/'fake.py';p.write_text('raise RuntimeError("should not execute")')
|
||||
with self.assertRaisesRegex(ValueError,'Unverified source'):V.load('_fixture_not_loaded',p,'0'*64)
|
||||
self.assertNotIn('_fixture_not_loaded',sys.modules)
|
||||
|
||||
def test_actual_frozen_sources_load_without_torch_or_ordinary_R(self):
|
||||
code="""
|
||||
import sys
|
||||
sys.path.insert(0,sys.argv[1]);import validate_update_cpu as V
|
||||
e=V.load('_v_cpu_test_E',V.LAB/'conditioning_epoch.py',V.E_SHA)
|
||||
V.load('engineering_compare',V.LAB/'engineering_compare.py',V.CMP_SHA)
|
||||
q=V.load('_v_cpu_test_Q',V.LAB/'conditioning_preflight_compare.py',V.Q_SHA)
|
||||
assert 'torch' not in sys.modules and 'runtime_light' not in sys.modules
|
||||
assert callable(e._authority) and callable(q.audit_delta_binding)
|
||||
print('ACTUAL_SOURCE_IMPORT_OK')
|
||||
"""
|
||||
result=subprocess.run([sys.executable,'-B','-c',code,str(Path(V.__file__).parent)],text=True,capture_output=True)
|
||||
self.assertEqual(result.returncode,0,result.stderr);self.assertIn('ACTUAL_SOURCE_IMPORT_OK',result.stdout)
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,601 @@
|
||||
"""Externally authorized, single-update same-state continuation; not learning proof.
|
||||
|
||||
Only epoch_update from a sealed fresh AN checkpoint and its original E four-file
|
||||
postprocess is admitted. Later idle transitions retain the installed snapshot.
|
||||
The input policy is empty_idle or externally_pinned_CS_probe. Probe CS/seed/no-US
|
||||
semantics and branch lineage belong to the registered coordinator, not this module.
|
||||
E/U are NEVER imported/executed here. An external CPU validation receipt binds U's
|
||||
recomputation; its executor/process/registration authority belongs to the caller.
|
||||
No public small-graph mode. CPU synthetic tests exercise private pure helpers.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
SOURCE_PINS = {
|
||||
'runtime_continuation_source': '0b8e8e0a6a23a079dc62a88355ce355d53b3ae22f6665519a8f6aef2dcfc5aba',
|
||||
'runtime_light_source': '522b8c31ea938890fe15364fccd25ccc5bded54101754909f255532e7ad01aae',
|
||||
'conditioning_epoch_source': '757935a4815d9f625640df685184ed3fe44a8845323562796da7aa43cbb194e1',
|
||||
'conditioning_update_source': '96efff678cff910654eb08e86f1a17789e4e5589e340345f419c7027a7d547e2',
|
||||
'conditioning_preflight_compare_source': 'b88fd9a88d9f92d5c4d042b90f2129b015e8d4bd810c41351ee573241e2d4c2e',
|
||||
'engineering_compare_source': '5a2403f11bc08d65a9d242ac2cf9686b850e0c3680d65659f785e9b6b50c0238',
|
||||
'eligibility_bridge_source': '174fb8d14619189e74b095e77a6db18b14c93046dc431c0b55710a5aa2dd2e61',
|
||||
'phase4j_source': 'abb4574da85f00bd9ef61024c65993ef81d42651ff8d8d63c15dd69c6222471e',
|
||||
'am_overlay_source': '7f891d0ba79b393c96e75fd2dee2eddc51e57d8213eaac2779703bc2c18712b4',
|
||||
}
|
||||
SCHEMA = 'conditioning-updated-boundary-v1'
|
||||
CHECKPOINT_SCHEMA = 'conditioning-updated-checkpoint-v1'
|
||||
PROVENANCE_SCHEMA = 'conditioning-updated-runtime-v1'
|
||||
RECEIPT = 'updated-continuation-receipt.json'
|
||||
MANIFEST = 'checkpoint-manifest.json'
|
||||
GRAPH_FILES = ('nodes.npy', 'edge_id.npy', 'src.npy', 'dst.npy', 'signed_raw.npy', 'ptr.npy', 'weights.npy')
|
||||
APL_FILES = ('input_matrix.npy', 'output_matrix.npy', 'kc_globals.npy', 'apl_globals.npy')
|
||||
UPDATE_FILES = ('chain-receipt.json', 'update-receipt.json', 'delta-after.npz', 'overlay-manifest.json')
|
||||
E_SOURCE_ROLES = ('runtime_light_source', 'runtime_continuation_source', 'conditioning_update_source',
|
||||
'eligibility_bridge_source', 'phase4j_source', 'am_overlay_source')
|
||||
E_ROLES = frozenset(('spec', 'requests', 'overlay_before', 'overlay_manifest_before', 'state', 'kc',
|
||||
'canonical_kc', 'candidate_map', 'mask', 'base_candidate', *E_SOURCE_ROLES))
|
||||
|
||||
|
||||
def _require(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def _digest(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for block in iter(lambda: stream.read(8 << 20), b''):
|
||||
h.update(block)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _continuation():
|
||||
path = Path(__file__).resolve().parent.parent / 'olfactory-conditioning-lab-v1/runtime_continuation.py'
|
||||
raw = path.read_bytes()
|
||||
expected = SOURCE_PINS['runtime_continuation_source']
|
||||
_require(hashlib.sha256(raw).hexdigest() == expected, 'Frozen C source pin changed')
|
||||
name = 'conditioning_updated_pinned_C'
|
||||
existing = sys.modules.get(name)
|
||||
if existing is not None:
|
||||
_require(getattr(existing, '__updated_pin__', None) == expected and
|
||||
Path(existing.__file__).resolve() == path, 'C module identity collision')
|
||||
return existing
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[name] = module
|
||||
try:
|
||||
exec(compile(raw, str(path), 'exec'), module.__dict__)
|
||||
except BaseException:
|
||||
sys.modules.pop(name, None)
|
||||
raise
|
||||
module.__updated_pin__ = expected
|
||||
return module
|
||||
|
||||
|
||||
C = _continuation()
|
||||
R = C.R # The ONLY runtime/helper cache owner. Never import ordinary R or E.
|
||||
|
||||
|
||||
def _canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
||||
|
||||
|
||||
def _same(a, b):
|
||||
return a.dtype == b.dtype and a.shape == b.shape and a.tobytes() == b.tobytes()
|
||||
|
||||
|
||||
def _entry(entry, pins):
|
||||
R.require(type(entry) is dict and set(entry) == {'path', 'sha256'} and R._sha(entry['sha256']), 'Malformed file pin')
|
||||
raw = Path(entry['path'])
|
||||
R.require(raw.is_absolute() and raw.is_file() and not raw.is_symlink(), 'Expected absolute regular unlinked file')
|
||||
path = raw.resolve(strict=True)
|
||||
R.require(str(path) not in pins or pins[str(path)] == entry['sha256'], 'Conflicting file pins')
|
||||
pins[str(path)] = entry['sha256']
|
||||
return path
|
||||
|
||||
|
||||
def _check(pins):
|
||||
for path, sha in pins.items():
|
||||
R.require(R._sha(sha) and _digest(path) == sha, 'Source/input changed: ' + str(path))
|
||||
|
||||
|
||||
def _evidence(value):
|
||||
return dict(dtype=value.dtype.str, shape=list(value.shape), nbytes=int(value.nbytes),
|
||||
raw_c_order_sha256=R._raw(value))
|
||||
|
||||
|
||||
def _Q(sources):
|
||||
R._load('engineering_compare', sources['engineering_compare_source'], SOURCE_PINS['engineering_compare_source'])
|
||||
return R._load('conditioning_updated_pinned_Q', sources['conditioning_preflight_compare_source'],
|
||||
SOURCE_PINS['conditioning_preflight_compare_source'])
|
||||
|
||||
|
||||
def _requests(path, spec, policy):
|
||||
values = C._npz(path, ('tick', 'neuron_idx'))
|
||||
tick, node = values['tick'], values['neuron_idx']
|
||||
R.require(tick.dtype == node.dtype == np.int32 and tick.ndim == node.ndim == 1 and tick.shape == node.shape,
|
||||
'Invalid request dtype/shape')
|
||||
R.require(np.all((tick >= 0) & (tick < spec['steps'])) and np.all((node >= 0) & (node < C.N)), 'Request outside case')
|
||||
keys = tick.astype(np.int64) * C.N + node
|
||||
R.require(len(keys) < 2 or np.all(keys[1:] > keys[:-1]), 'Requests must be sorted unique')
|
||||
R.require(policy in ('empty_idle', 'externally_pinned_CS_probe'), 'Invalid input policy')
|
||||
R.require(policy != 'empty_idle' or len(tick) == 0, 'empty_idle contains requests')
|
||||
return values
|
||||
|
||||
|
||||
def _expected_effective(helper, plan, spec):
|
||||
maps = {}
|
||||
try:
|
||||
graph = Path(spec['graph_dir'])
|
||||
for name, dtype, size in (('nodes', 'int32', C.N), ('edge_id', 'int64', C.E),
|
||||
('src', 'int32', C.E), ('weights', 'float64', C.E)):
|
||||
a = np.load(graph / (name + '.npy'), mmap_mode='r', allow_pickle=False)
|
||||
maps[name] = a
|
||||
R.require(a.dtype == np.dtype(dtype) and a.shape == (size,), 'Full graph dtype/shape changed: ' + name)
|
||||
R.require(np.array_equal(maps['nodes'], np.arange(C.N, dtype=np.int32)), 'Noncanonical node order')
|
||||
apl = np.load(Path(spec['apl_bundle_dir']) / 'apl_globals.npy', allow_pickle=False)
|
||||
R.require(apl.dtype == np.int32 and apl.shape == (2,), 'Invalid APL IDs')
|
||||
apl_mask = np.isin(maps['src'], apl)
|
||||
R.require(int(apl_mask.sum()) == 5845, 'APL output mask changed')
|
||||
mapping = helper.map_installation(maps['weights'], maps['edge_id'], apl_mask, plan)
|
||||
R.require(mapping['missing_candidate_count'] == 0 and mapping['mapped_candidate_count'] == 14232, 'Full candidate mapping required')
|
||||
return helper.expected_hashes(maps['weights'], apl_mask, mapping)[1]
|
||||
finally:
|
||||
for a in maps.values():
|
||||
a._mmap.close()
|
||||
|
||||
|
||||
def _epoch_update(value, paths, sources, pins, parent, before, after, before_meta, after_meta):
|
||||
update = value['update']
|
||||
R.require(type(update) is dict and set(update) == {'epoch_authority', 'files'}, 'Missing epoch update authority')
|
||||
ep = _entry(update['epoch_authority'], pins)
|
||||
paths['epoch_authority'] = ep
|
||||
R.require(type(update['files']) is dict and set(update['files']) == set(UPDATE_FILES), 'All four original E outputs required')
|
||||
files = {name: _entry(update['files'][name], pins) for name in UPDATE_FILES}
|
||||
directory = files['chain-receipt.json'].parent
|
||||
R.require(all(path == directory / name for name, path in files.items()) and
|
||||
{p.name for p in directory.iterdir()} == set(UPDATE_FILES), 'E output must be exact four-file directory')
|
||||
R.require(files['delta-after.npz'] == paths['after_overlay'] and files['overlay-manifest.json'] == paths['after_manifest'],
|
||||
'Installed after snapshot is not the original E output')
|
||||
_check(pins)
|
||||
authority = R._read_json(ep)
|
||||
R.require(type(authority) is dict and set(authority) == {'schema', 'epoch_id', 'diagnostic_mode', 'command',
|
||||
'checkpoint_dir', 'checkpoint_manifest_sha256', 'files', 'frozen_inputs'} and
|
||||
authority['schema'] == 'phase4an-epoch-postprocess-authority-v1', 'Original E authority schema changed')
|
||||
R.require(parent['fresh'] is True and parent['global_tick_offset'] == 0 and
|
||||
Path(authority['checkpoint_dir']).resolve(strict=True) == parent['directory'] and
|
||||
authority['checkpoint_manifest_sha256'] == parent['manifest_sha256'] and
|
||||
authority['diagnostic_mode'] == parent['summary']['diagnostic_mode'], 'Wrong fresh E parent')
|
||||
R.require(type(authority['files']) is dict and set(authority['files']) == E_ROLES, 'Incomplete E file roles')
|
||||
epins = {str(ep): pins[str(ep)], str(parent['directory'] / MANIFEST): parent['manifest_sha256']}
|
||||
epaths = {role: _entry(entry, epins) for role, entry in authority['files'].items()}
|
||||
for role in E_SOURCE_ROLES:
|
||||
R.require(epins[str(epaths[role])] == SOURCE_PINS[role] and epaths[role] == sources[role], 'E source role mismatch: ' + role)
|
||||
R.require(type(authority['frozen_inputs']) is dict and authority['frozen_inputs'], 'Missing E frozen input pins')
|
||||
for path, sha in authority['frozen_inputs'].items():
|
||||
_entry(dict(path=path, sha256=sha), epins)
|
||||
R.require(epaths['state'] == parent['directory'] / 'state.npz' and
|
||||
parent['manifest']['files_sha256']['state.npz'] == epins[str(epaths['state'])], 'E state is not sealed parent')
|
||||
for role, actual in (('overlay_before', paths['before_overlay']), ('overlay_manifest_before', paths['before_manifest'])):
|
||||
R.require(epaths[role] == actual, 'E before overlay path differs')
|
||||
for role in ('spec', 'requests', 'overlay_before', 'overlay_manifest_before'):
|
||||
R.require(parent['provenance']['input_sha256'].get(str(epaths[role])) == epins[str(epaths[role])], 'E/runtime input differs: ' + role)
|
||||
for path, sha in epins.items():
|
||||
_entry(dict(path=path, sha256=sha), pins)
|
||||
_check(pins)
|
||||
chain = R._read_json(files['chain-receipt.json'])
|
||||
receipt = R._read_json(files['update-receipt.json'])
|
||||
command = authority['command']
|
||||
R.require(type(command) is dict and set(command) == {'steps', 'compartment', 'us_tick', 'd_command', 'frozen', 'trace_backend'}, 'E command schema')
|
||||
R.require(type(command['steps']) is int and command['steps'] == parent['steps'], 'E command clock mismatch')
|
||||
R.require(type(command['d_command']) in (int, float) and command['d_command'] in (0, 1) and
|
||||
type(command['frozen']) is bool and command['trace_backend'] in ('numpy', 'torch') and
|
||||
command['compartment'] in ("B2B'2a", 'a1', "y2a'1", "y5B'2a") and
|
||||
(command['us_tick'] is None or (type(command['us_tick']) is int and 0 <= command['us_tick'] < command['steps'])) and
|
||||
(command['us_tick'] is not None or command['d_command'] == 0), 'E command value/type mismatch')
|
||||
required_chain = dict(schema='phase4an-epoch-postprocess-chain-v1', complete=True,
|
||||
epoch_id=authority['epoch_id'], authority_file=str(ep), authority_sha256=pins[str(ep)],
|
||||
coordinator_source_sha256=SOURCE_PINS['conditioning_epoch_source'], command=command,
|
||||
diagnostic_mode=authority['diagnostic_mode'], source_neural_checkpoint_dir=str(parent['directory']),
|
||||
source_neural_checkpoint_manifest_sha256=parent['manifest_sha256'],
|
||||
before_overlay_file_sha256=pins[str(paths['before_overlay'])],
|
||||
before_overlay_manifest_sha256=pins[str(paths['before_manifest'])],
|
||||
after_overlay_file_sha256=pins[str(paths['after_overlay'])],
|
||||
after_overlay_manifest_sha256=pins[str(paths['after_manifest'])],
|
||||
source_state_file_sha256=epins[str(epaths['state'])], source_spec_sha256=epins[str(epaths['spec'])],
|
||||
source_requests_sha256=epins[str(epaths['requests'])], input_files_sha256=epins,
|
||||
output_files_sha256={name: pins[str(files[name])] for name in UPDATE_FILES if name != 'chain-receipt.json'},
|
||||
runtime_delta_before_raw_sha256=R._raw(before['plastic_delta_mv']),
|
||||
runtime_effective_weights_raw_sha256=parent['summary']['effective_weights_raw_sha256'],
|
||||
update_receipt_payload_sha256=receipt.get('payload_sha256'), runtime_learned_manifest_loader_verified=True,
|
||||
input_and_checkpoint_bytes_reverified=True, candidate_endpoints_equal_graph=True,
|
||||
KC_equals_supplied_canonical_membership=True, weights_installed=False, brain_executed=False,
|
||||
learning_pass_claimed=False, candidate_generated=False)
|
||||
R.require(all(_canonical(chain.get(k)) == _canonical(v) for k, v in required_chain.items()), 'Original E chain mismatch')
|
||||
for role, prefix in (('mask', 'mask'), ('base_candidate', 'base_candidate'), ('am_overlay_source', 'am_overlay')):
|
||||
R.require(Path(before_meta[prefix + '_path']).resolve() == epaths[role] and
|
||||
before_meta[prefix + '_sha256'] == epins[str(epaths[role])], 'E mapping/base authority mismatch')
|
||||
mapping = C._npz(epaths['candidate_map'], ('edge_id', 'source_neuron_idx', 'target_neuron_idx', 'target_compartment_verbatim'))
|
||||
kc = np.load(epaths['kc'], allow_pickle=False)
|
||||
canonical_kc = np.load(epaths['canonical_kc'], allow_pickle=False)
|
||||
base = np.load(epaths['base_candidate'], allow_pickle=False)
|
||||
R.require(epaths['canonical_kc'] == Path(C._parent_spec(parent)['apl_bundle_dir']).resolve() / 'kc_globals.npy' and
|
||||
kc.dtype == np.int32 and kc.shape == (4064,) and _same(kc, canonical_kc), 'Full canonical KC mismatch')
|
||||
R.require(_same(mapping['edge_id'], before['edge_id']) and _same(after['edge_id'], before['edge_id']) and
|
||||
_same(base, before['base_candidate_mv']) and _same(base, after['base_candidate_mv']), 'Full before/after mask/base mismatch')
|
||||
graph = Path(C._parent_spec(parent)['graph_dir'])
|
||||
parent_spec = C._parent_spec(parent)
|
||||
required_epins = [graph / name for name in GRAPH_FILES] + [Path(parent_spec['apl_bundle_dir']) / name for name in APL_FILES]
|
||||
required_epins.append(Path(parent_spec['coefficients_path']))
|
||||
required_epins.extend(Path(before_meta['aj_model_dir']).parent / name for name in R.PINS)
|
||||
R.require(all(str(path.resolve(strict=True)) in authority['frozen_inputs'] for path in required_epins),
|
||||
'Original E authority omitted frozen graph/APL/compiled sources')
|
||||
for role, filename in (('source_neuron_idx', 'src.npy'), ('target_neuron_idx', 'dst.npy')):
|
||||
a = np.load(graph / filename, mmap_mode='r', allow_pickle=False)
|
||||
try:
|
||||
R.require(mapping[role].dtype == np.int32 and mapping[role].shape == (14232,) and
|
||||
_same(mapping[role], a[before['edge_id']]), 'Actual candidate endpoint mismatch')
|
||||
finally:
|
||||
a._mmap.close()
|
||||
compartments = mapping['target_compartment_verbatim']
|
||||
R.require(compartments.dtype.kind == 'U' and compartments.shape == (14232,), 'Invalid full compartment metadata')
|
||||
arrays = dict(step=parent['state']['step'], neuron_idx=parent['state']['neuron_idx'], kc=kc,
|
||||
candidate_edge_id=before['edge_id'], candidate_sources=mapping['source_neuron_idx'],
|
||||
candidate_targets=mapping['target_neuron_idx'], candidate_compartments=compartments,
|
||||
delta_before=before['plastic_delta_mv'], base_candidate=base)
|
||||
R.require(_canonical(receipt.get('input_arrays')) == _canonical({k: _evidence(a) for k, a in arrays.items()}), 'U receipt actual array binding failed')
|
||||
expected_command = dict(steps=command['steps'], n_neurons=C.N, compartment=command['compartment'],
|
||||
us_tick=command['us_tick'], D_scheduled=float(command['d_command']), frozen=command['frozen'], trace_backend=command['trace_backend'])
|
||||
R.require(_canonical(receipt.get('command')) == _canonical(expected_command), 'U receipt command differs')
|
||||
binding = _Q(sources).audit_delta_binding(before['plastic_delta_mv'], after['plastic_delta_mv'], after['plastic_delta_mv'],
|
||||
update_receipt=receipt, parent_snapshot_sha256=pins[str(paths['before_overlay'])], child_manifest=after_meta)
|
||||
R.require(binding['pass_all'] is True, 'Q actual before/after delta binding failed')
|
||||
cp = _entry(value['cpu_validation'], pins)
|
||||
paths['cpu_validation'] = cp
|
||||
cpu = R._read_json(cp)
|
||||
expected_cpu = dict(schema='conditioning-update-cpu-validation-v1', complete=True,
|
||||
epoch_authority_sha256=pins[str(ep)], parent_checkpoint_manifest_sha256=parent['manifest_sha256'],
|
||||
update_files_sha256={name: pins[str(files[name])] for name in UPDATE_FILES},
|
||||
before_overlay_sha256=pins[str(paths['before_overlay'])], before_manifest_sha256=pins[str(paths['before_manifest'])],
|
||||
after_overlay_sha256=pins[str(paths['after_overlay'])], after_manifest_sha256=pins[str(paths['after_manifest'])],
|
||||
before_delta_raw_sha256=R._raw(before['plastic_delta_mv']), after_delta_raw_sha256=R._raw(after['plastic_delta_mv']),
|
||||
update_receipt_payload_sha256=receipt['payload_sha256'],
|
||||
validator_source=dict(path=str(sources['cpu_validator_source']), sha256=pins[str(sources['cpu_validator_source'])]),
|
||||
frozen_U_source_sha256=SOURCE_PINS['conditioning_update_source'], frozen_U_verify_receipt_recomputed=True,
|
||||
actual_sealed_events_used=True, full_candidate_mapping_verified=True, brain_executed=False, learning_pass_claimed=False)
|
||||
R.require(_canonical(cpu) == _canonical(expected_cpu), 'External CPU recomputation receipt mismatch')
|
||||
return binding
|
||||
|
||||
|
||||
def validate_authority(authority_json, authority_sha256, *, _seen=None):
|
||||
"""Read-only CPU admission. Does not recompute U, run E, import Torch or restore.
|
||||
|
||||
Returns value/authority/authority_sha256, paths, pins (absolute str -> SHA),
|
||||
sources, parent, case_dir/spec, helper, before_plan/after_plan/before_meta/
|
||||
after_meta; suitable for an independent monolithic oracle without restore.
|
||||
"""
|
||||
pins = {}
|
||||
authority_path = _entry(dict(path=str(authority_json), sha256=authority_sha256), pins)
|
||||
_check(pins)
|
||||
value = R._read_json(authority_path)
|
||||
fields = {'schema', 'boundary_id', 'registration_sha256', 'transition', 'diagnostic_mode', 'input_policy',
|
||||
'case', 'parent', 'global_tick_offset', 'overlay_before', 'overlay_after',
|
||||
'expected_effective_weight_before_sha256', 'expected_effective_weight_after_sha256', 'update',
|
||||
'cpu_validation', 'source_files', 'frozen_inputs'}
|
||||
R.require(type(value) is dict and set(value) == fields and value['schema'] == SCHEMA, 'Boundary authority schema mismatch')
|
||||
R.require(type(value['boundary_id']) is str and value['boundary_id'].strip() == value['boundary_id'] and value['boundary_id'], 'Invalid boundary ID')
|
||||
R.require(R._sha(value['registration_sha256']) and value['transition'] in ('epoch_update', 'idle') and
|
||||
value['diagnostic_mode'] in ('reference', 'light'), 'Invalid boundary scope')
|
||||
R.require(type(value['case']) is dict and set(value['case']) == {'spec', 'requests'}, 'Exact case pins required')
|
||||
paths = {key: _entry(value['case'][role], pins) for key, role in (('case_spec', 'spec'), ('requests', 'requests'))}
|
||||
for moment in ('before', 'after'):
|
||||
pair = value['overlay_' + moment]
|
||||
R.require(type(pair) is dict and set(pair) == {'file', 'manifest'}, 'Exact overlay pair required')
|
||||
paths[moment + '_overlay'] = _entry(pair['file'], pins)
|
||||
paths[moment + '_manifest'] = _entry(pair['manifest'], pins)
|
||||
source_values = value['source_files']
|
||||
R.require(type(source_values) is dict and set(source_values) == set(SOURCE_PINS) |
|
||||
{'updated_continuation_source', 'cpu_validator_source'}, 'Exact source roles required')
|
||||
sources = {name: _entry(entry, pins) for name, entry in source_values.items()}
|
||||
for name, sha in SOURCE_PINS.items():
|
||||
R.require(pins[str(sources[name])] == sha, 'Frozen source may not be replaced: ' + name)
|
||||
R.require(sources['updated_continuation_source'] == Path(__file__).resolve() and
|
||||
sources['runtime_continuation_source'] == Path(C.__file__).resolve() and
|
||||
sources['runtime_light_source'] == Path(R.__file__).resolve() and
|
||||
sources['cpu_validator_source'] == Path(__file__).resolve().parent / 'validate_update_cpu.py',
|
||||
'Loaded runtime/CPU validator source path differs')
|
||||
R.require(type(value['frozen_inputs']) is dict and value['frozen_inputs'], 'Full frozen inputs required')
|
||||
for path, sha in value['frozen_inputs'].items():
|
||||
_entry(dict(path=path, sha256=sha), pins)
|
||||
p = value['parent']
|
||||
R.require(type(p) is dict and set(p) == {'directory', 'checkpoint_manifest_sha256'} and Path(p['directory']).is_absolute(), 'Exact parent authority required')
|
||||
parentdir = Path(p['directory']).resolve(strict=True)
|
||||
_entry(dict(path=str(parentdir / MANIFEST), sha256=p['checkpoint_manifest_sha256']), pins)
|
||||
_check(pins)
|
||||
parent = load_checkpoint(parentdir, p['checkpoint_manifest_sha256'], _seen=_seen)
|
||||
R.require(type(value['global_tick_offset']) is int and value['global_tick_offset'] == parent['global_next_tick'], 'Wrong absolute continuation clock')
|
||||
case = paths['case_spec'].parent
|
||||
R.require(paths['case_spec'].name == 'spec.json' and paths['requests'] == case / 'requests.npz', 'Case filenames differ')
|
||||
spec = R._read_json(paths['case_spec'])
|
||||
R.require(spec.get('parent_checkpoint_manifest_sha256') == p['checkpoint_manifest_sha256'] and
|
||||
type(spec.get('global_tick_offset')) is int and spec['global_tick_offset'] == value['global_tick_offset'], 'Case parent/clock differs')
|
||||
fresh = dict(spec)
|
||||
fresh.pop('parent_checkpoint_manifest_sha256')
|
||||
R.validate_spec(fresh, case)
|
||||
R.require(parent['global_next_tick'] + spec['steps'] <= np.iinfo(np.int64).max, 'Global clock overflow')
|
||||
_requests(paths['requests'], spec, value['input_policy'])
|
||||
previous = C._parent_spec(parent)
|
||||
for key in ('dt_ms', 'model', 'apl', 'apl_delay_steps'):
|
||||
R.require(_canonical(spec[key]) == _canonical(previous[key]), 'Frozen dynamics differ: ' + key)
|
||||
for key in ('graph_dir', 'apl_bundle_dir'):
|
||||
R.require(Path(spec[key]).resolve(strict=True) == Path(previous[key]).resolve(strict=True), 'Frozen directory differs')
|
||||
R.require(_digest(spec['coefficients_path']) == parent['summary']['input_sha256']['coefficients.json'] and
|
||||
_digest(Path(spec['graph_dir']) / 'weights.npy') == parent['summary']['input_sha256']['base_weights.npy'], 'Base/coefficients differ')
|
||||
required = [Path(spec['graph_dir']).resolve() / n for n in GRAPH_FILES] + [Path(spec['apl_bundle_dir']).resolve() / n for n in APL_FILES]
|
||||
required.append(Path(spec['coefficients_path']).resolve(strict=True))
|
||||
R.require(all(str(path) in value['frozen_inputs'] for path in required), 'Full graph/APL/coeff pins missing')
|
||||
helper, before, bm, bpins = R.load_overlay(paths['before_overlay'], paths['before_manifest'])
|
||||
helper2, after, am, apins = R.load_overlay(paths['after_overlay'], paths['after_manifest'])
|
||||
R.require(helper2 is helper, 'Overlay cache owner differs')
|
||||
for path, sha in {**bpins, **apins}.items():
|
||||
_entry(dict(path=str(path), sha256=sha), pins)
|
||||
for relative, sha in R.PINS.items():
|
||||
path = (Path(am['aj_model_dir']).resolve().parent / relative).resolve(strict=True)
|
||||
R.require(value['frozen_inputs'].get(str(path)) == sha, 'Compiled/source dependency authority missing: ' + relative)
|
||||
for key in ('mask_path', 'mask_sha256', 'base_candidate_path', 'base_candidate_sha256', 'aj_model_dir', 'am_overlay_path', 'am_overlay_sha256'):
|
||||
R.require(bm[key] == am[key], 'Before/after anatomical/source authority differs: ' + key)
|
||||
R.require(_digest(parentdir / 'overlay-input.npz') == pins[str(paths['before_overlay'])] and
|
||||
_digest(parentdir / 'overlay-manifest.json') == pins[str(paths['before_manifest'])], 'Before snapshot differs from actual neural parent')
|
||||
R.require(parent['overlay']['delta_raw_sha256'] == R._raw(before['plastic_delta_mv']), 'Parent delta raw identity mismatch')
|
||||
for key in ('expected_effective_weight_before_sha256', 'expected_effective_weight_after_sha256'):
|
||||
R.require(R._sha(value[key]), 'Expected effective SHA required')
|
||||
before_effective = _expected_effective(helper, before, spec)
|
||||
after_effective = _expected_effective(helper, after, spec)
|
||||
R.require(before_effective == value['expected_effective_weight_before_sha256'] == parent['summary']['effective_weights_raw_sha256'], 'Before effective weights differ')
|
||||
R.require(after_effective == value['expected_effective_weight_after_sha256'], 'After effective weights differ')
|
||||
paths.update(epoch_authority=None, cpu_validation=None)
|
||||
binding = None
|
||||
if value['transition'] == 'epoch_update':
|
||||
R.require(parent['fresh'] is True, 'An update boundary is allowed only once, from fresh AN parent')
|
||||
binding = _epoch_update(value, paths, sources, pins, parent, before, after, bm, am)
|
||||
root = authority_sha256
|
||||
else:
|
||||
R.require(parent['manifest']['schema'] == CHECKPOINT_SCHEMA and value['update'] is None and value['cpu_validation'] is None,
|
||||
'Idle requires own updated parent and no new update authority')
|
||||
R.require(pins[str(paths['before_overlay'])] == pins[str(paths['after_overlay'])] and
|
||||
pins[str(paths['before_manifest'])] == pins[str(paths['after_manifest'])] and
|
||||
before_effective == after_effective, 'Idle changed the installed snapshot')
|
||||
R.require(parent['input_policy'] == 'empty_idle', 'A probe branch cannot feed back into a continuation lineage')
|
||||
root = parent['update_root_authority_sha256']
|
||||
_check(pins)
|
||||
return dict(value=value, authority=authority_path, authority_sha256=authority_sha256, paths=paths, pins=pins,
|
||||
sources=sources, parent=parent, case_dir=case, spec=spec, helper=helper, before_plan=before, after_plan=after,
|
||||
before_meta=bm, after_meta=am, delta_binding=binding, update_root_authority_sha256=root)
|
||||
|
||||
|
||||
class UpdatedRuntime(C.ContinuedRuntime):
|
||||
"""Only weight admission differs from C; restoration and kernels unchanged."""
|
||||
def __init__(self, *args, authority, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.authority = authority
|
||||
self.restore_audit = None
|
||||
|
||||
def install(self, *args, **kwargs):
|
||||
R.require(self.installations == 0 and self.restorations == 0, 'Double/belated weight installation')
|
||||
R._Runtime.install(self, *args, **kwargs) # Original base + full delta once; not old effective + delta.
|
||||
R.require(self.effective_sha == self.authority['value']['expected_effective_weight_after_sha256'], 'Installed weight differs from authorized after')
|
||||
|
||||
def restore(self, v, g, ref, counts, ring, apl_ring, apl, upload):
|
||||
super().restore(v, g, ref, counts, ring, apl_ring, apl, upload)
|
||||
expected = dict(v=self.parent['state']['v'], g=self.parent['state']['g'], ref=self.parent['state']['ref'],
|
||||
spike_ring=C.rotate_spike_ring(self.parent['terminal']['spike_ring'], int(self.parent['terminal']['next_tick'])),
|
||||
apl_pending=self.parent['terminal']['apl_pending'], apl_state=self.parent['terminal']['apl_state'])
|
||||
actual = dict(v=v, g=g, ref=ref, spike_ring=ring, apl_pending=apl_ring, apl_state=apl.state)
|
||||
for key, tensor in actual.items():
|
||||
R.require(_same(tensor.detach().cpu().numpy(), expected[key]), 'Restoration changed actual state bytes: ' + key)
|
||||
self.restore_audit = dict(restored_raw_sha256={key: R._raw(a) for key, a in expected.items()},
|
||||
all_state_and_queue_bytes_exact=True, existing_g_rescaled=False, retroactive_arrival_reweighting=False,
|
||||
pending_spike_arrivals_use_current_installed_weight=True, pending_APL_samples_preserved=True,
|
||||
boundary_installations=1, restorations=1, learning_pass_claimed=False)
|
||||
|
||||
def summary(self, value):
|
||||
result = super().summary(value)
|
||||
result.update(updated_boundary_schema=SCHEMA, boundary_authority_sha256=self.authority['authority_sha256'],
|
||||
update_root_authority_sha256=self.authority['update_root_authority_sha256'],
|
||||
boundary_transition=self.authority['value']['transition'], input_policy=self.authority['value']['input_policy'],
|
||||
weight_update_at_boundary_authorized=True, frozen_same_weight_retention_claimed=False)
|
||||
return result
|
||||
|
||||
|
||||
def compile_updated(aj, runtime, mode):
|
||||
tree, audit = C.derive_continued(Path(aj.__file__).read_bytes(), mode)
|
||||
namespace = dict(aj.__dict__)
|
||||
namespace.update(__name__=__name__ + '.derived_' + mode, __file__=str(Path(__file__).resolve()),
|
||||
_runtime=runtime, _continuation=runtime, write_json=runtime.write_json, audit_sequence=runtime.audit_sequence)
|
||||
exec(compile(tree, str(Path(__file__).resolve()) + '::updated-continuation-' + mode, 'exec'), namespace)
|
||||
return namespace['run_gpu'], audit
|
||||
|
||||
|
||||
def _record(directory, seen):
|
||||
provenance = R._read_json(directory / 'runtime-provenance.json')
|
||||
R.require(provenance.get('schema') == PROVENANCE_SCHEMA and provenance.get('complete') is True and
|
||||
provenance.get('source_sha256') == _digest(__file__) and
|
||||
Path(provenance['source_file']).resolve() == Path(__file__).resolve(), 'Not a genuine new continuation record')
|
||||
R.require(provenance.get('old_globals_patched') is False and provenance.get('weights_updated_during_run') is False and
|
||||
provenance.get('U_recomputed_here') is False and provenance.get('learning_pass_claimed') is False, 'Invalid continuation scope')
|
||||
C._verify_receipt_hashes(directory, provenance)
|
||||
R.require(provenance.get('state_sha256') == _digest(directory / 'state.npz'), 'Actual state is not bound')
|
||||
authority = validate_authority(provenance['authority_file'], provenance['authority_sha256'], _seen=seen)
|
||||
parent, spec, value = authority['parent'], authority['spec'], authority['value']
|
||||
steps, offset = spec['steps'], parent['global_next_tick']
|
||||
R.require(provenance['input_sha256'] == authority['pins'], 'Receipt input closure differs from authority')
|
||||
R.require(provenance.get('mode') == value['diagnostic_mode'] and
|
||||
provenance.get('parent_checkpoint_manifest_sha256') == parent['manifest_sha256'] and
|
||||
provenance.get('global_tick_offset') == offset and provenance.get('global_next_tick') == offset+steps and
|
||||
provenance.get('external_CPU_validation_receipt_bound') is (value['transition'] == 'epoch_update') and
|
||||
provenance.get('external_registration_process_and_probe_semantics_verified_here') is False,
|
||||
'Runtime provenance boundary/clock/scope differs')
|
||||
_, expected_ast = C.derive_continued((Path(authority['after_meta']['aj_model_dir']) / 'gpu_timing.py').read_bytes(), value['diagnostic_mode'])
|
||||
R.require(provenance.get('ast') == expected_ast, 'Derived source AST provenance differs')
|
||||
summary = R._read_json(directory / 'summary.json')
|
||||
finite = R._read_json(directory / 'finite-audit.json')
|
||||
for name, expected in dict(complete=True, pass_all=True, all_finite=True, steps=steps, completed_ticks=steps,
|
||||
nodes=C.N, edges=C.E, precision='float64', apl_precision='float32', within_trial_weight_updates=False,
|
||||
checkpoint_continuation_used=True, global_tick_offset=offset, global_next_tick=offset+steps,
|
||||
explicit_steps_executed=steps, max_steps=spec['max_steps'], hidden_early_stop=False,
|
||||
entire_neural_trial_executed=True, record_history=False, counts_scope='segment_only_not_lifetime',
|
||||
event_tick_scope='segment_local', weight_update_at_boundary_authorized=True, frozen_same_weight_retention_claimed=False,
|
||||
parent_checkpoint_manifest_sha256=parent['manifest_sha256'], diagnostic_mode=value['diagnostic_mode'],
|
||||
boundary_authority_sha256=authority['authority_sha256'], update_root_authority_sha256=authority['update_root_authority_sha256'],
|
||||
updated_boundary_schema=SCHEMA, boundary_transition=value['transition'], input_policy=value['input_policy'],
|
||||
effective_weights_raw_sha256=value['expected_effective_weight_after_sha256']).items():
|
||||
R.require(_canonical(summary.get(name)) == _canonical(expected), 'Summary binding mismatch: ' + name)
|
||||
R.require(finite.get('all_finite') is True and finite.get('first_failure_tick') == -1 and
|
||||
finite.get('finite_observed_ticks') == steps, 'Missing full finite coverage')
|
||||
expected_input = {'spec.json': authority['pins'][str(authority['paths']['case_spec'])],
|
||||
'requests.npz': authority['pins'][str(authority['paths']['requests'])],
|
||||
'base_weights.npy': _digest(Path(spec['graph_dir']) / 'weights.npy'), 'coefficients.json': _digest(spec['coefficients_path'])}
|
||||
R.require(summary.get('input_sha256') == expected_input, 'Summary case/base inputs differ')
|
||||
state = C._npz(directory / 'state.npz', ('step', 'neuron_idx', 'counts', 'v', 'g', 'ref'))
|
||||
terminal = C._npz(directory / 'terminal-queues.npz', ('spike_ring', 'apl_state', 'apl_pending', 'next_tick'))
|
||||
C.validate_state(state, terminal, steps, fresh=False)
|
||||
if steps < 19:
|
||||
restored = C.rotate_spike_ring(parent['terminal']['spike_ring'], int(parent['terminal']['next_tick']))
|
||||
R.require(_same(terminal['spike_ring'][steps:], restored[steps:]), 'Unwritten carried spike slots differ')
|
||||
if steps < 18:
|
||||
R.require(_same(terminal['apl_pending'][:18-steps], parent['terminal']['apl_pending'][steps:]), 'Carried APL tail differs')
|
||||
pending = np.load(directory / 'apl-pending-tail.float32.npy', allow_pickle=False)
|
||||
timing = R._read_json(directory / 'apl-timing-audit.json')
|
||||
R.require(_same(pending, terminal['apl_pending']) and timing.get('pending_raw_sha256') == R._raw(pending) and
|
||||
timing.get('apl_delay_steps') == 18 and timing.get('brain_tail_advanced') is False and
|
||||
timing.get('final_apl_state_u32_bits') == terminal['apl_state'].view(np.uint32).tolist() and
|
||||
timing.get('global_tick_offset') == offset and timing.get('global_next_tick') == offset+steps and
|
||||
timing.get('initial_queue_raw_sha256') == R._raw(parent['terminal']['apl_pending']), 'APL metadata/terminal mismatch')
|
||||
overlay = R._read_json(directory / 'overlay-audit.json')
|
||||
R.require(overlay.get('complete') is True and overlay.get('weights_updated_during_run') is False and
|
||||
overlay.get('effective_weights_raw_sha256') == value['expected_effective_weight_after_sha256'] and
|
||||
overlay.get('delta_raw_sha256') == R._raw(authority['after_plan']['plastic_delta_mv']) and
|
||||
overlay.get('mask_sha256') == R.MASK_SHA and overlay.get('am_helper_sha256') == R.AM_OVERLAY_SHA, 'Installed snapshot receipt mismatch')
|
||||
for dest, source in (('overlay-input.npz', 'after_overlay'), ('overlay-manifest.json', 'after_manifest')):
|
||||
R.require(_digest(directory / dest) == authority['pins'][str(authority['paths'][source])], 'Copied after snapshot differs')
|
||||
receipt = R._read_json(directory / RECEIPT)
|
||||
payload = C._tree_hashes(directory)
|
||||
payload.pop(RECEIPT, None)
|
||||
expected_receipt = dict(schema='conditioning-updated-receipt-v1', complete=True,
|
||||
authority_file=str(authority['authority']), authority_sha256=authority['authority_sha256'],
|
||||
parent_checkpoint_dir=str(parent['directory']), parent_checkpoint_manifest_sha256=parent['manifest_sha256'],
|
||||
global_tick_offset=offset, global_next_tick=offset+steps, segment_steps=steps,
|
||||
update_root_authority_sha256=authority['update_root_authority_sha256'], input_policy=value['input_policy'],
|
||||
payload_sha256=payload, weights_updated_during_run=False, counts_scope='segment_only_not_lifetime',
|
||||
checkpoint_continuation_verified_by_GPU_comparison=False, learning_pass_claimed=False)
|
||||
R.require(_canonical(receipt) == _canonical(expected_receipt), 'New receipt payload/ancestry mismatch')
|
||||
restored = dict(v=parent['state']['v'], g=parent['state']['g'], ref=parent['state']['ref'],
|
||||
spike_ring=C.rotate_spike_ring(parent['terminal']['spike_ring'], int(parent['terminal']['next_tick'])),
|
||||
apl_pending=parent['terminal']['apl_pending'], apl_state=parent['terminal']['apl_state'])
|
||||
boundary = R._read_json(directory / 'boundary-restore-audit.json')
|
||||
R.require(boundary == dict(restored_raw_sha256={k:R._raw(a) for k,a in restored.items()},
|
||||
all_state_and_queue_bytes_exact=True, existing_g_rescaled=False, retroactive_arrival_reweighting=False,
|
||||
pending_spike_arrivals_use_current_installed_weight=True, pending_APL_samples_preserved=True,
|
||||
boundary_installations=1, restorations=1, learning_pass_claimed=False), 'Boundary restore audit differs from real parent')
|
||||
return dict(directory=directory, summary=summary, provenance=provenance, overlay=overlay, state=state, terminal=terminal,
|
||||
steps=steps, global_tick_offset=offset, global_next_tick=offset+steps, fresh=False,
|
||||
ancestry_directories=[directory, *parent['ancestry_directories']], input_policy=value['input_policy'],
|
||||
update_root_authority_sha256=authority['update_root_authority_sha256'])
|
||||
|
||||
|
||||
def load_checkpoint(checkpoint_dir, expected_sha, *, _seen=None):
|
||||
directory = Path(checkpoint_dir).resolve(strict=True)
|
||||
R.require(R._sha(expected_sha) and _digest(directory / MANIFEST) == expected_sha, 'External checkpoint pin differs')
|
||||
manifest = R._read_json(directory / MANIFEST)
|
||||
if manifest.get('schema') == 'phase4an-checkpoint-v1':
|
||||
return C.load_checkpoint(directory, expected_sha, _seen=_seen)
|
||||
seen = set() if _seen is None else set(_seen)
|
||||
R.require(directory not in seen, 'Updated checkpoint ancestry cycle')
|
||||
seen.add(directory)
|
||||
R.require(set(manifest) == {'schema', 'complete', 'files_sha256', 'segment_steps', 'global_tick_offset', 'global_next_tick',
|
||||
'counts_scope', 'update_root_authority_sha256', 'input_policy', 'learning_pass_claimed',
|
||||
'checkpoint_continuation_verified_by_GPU_comparison'} and
|
||||
manifest.get('schema') == CHECKPOINT_SCHEMA and manifest.get('complete') is True and
|
||||
manifest.get('learning_pass_claimed') is False and manifest.get('checkpoint_continuation_verified_by_GPU_comparison') is False and
|
||||
manifest.get('counts_scope') == 'segment_only' and manifest.get('files_sha256') == C._tree_hashes(directory), 'New checkpoint exact inventory differs')
|
||||
record = _record(directory, seen)
|
||||
for key in ('global_tick_offset', 'global_next_tick', 'update_root_authority_sha256', 'input_policy'):
|
||||
R.require(manifest.get(key) == record[key], 'Checkpoint metadata mismatch: ' + key)
|
||||
R.require(manifest.get('segment_steps') == record['steps'] and manifest['files_sha256'] == C._tree_hashes(directory) and
|
||||
_digest(directory / MANIFEST) == expected_sha, 'Checkpoint changed while loading')
|
||||
record.update(manifest=manifest, manifest_sha256=expected_sha)
|
||||
return record
|
||||
|
||||
|
||||
def seal_checkpoint(checkpoint_dir):
|
||||
directory = Path(checkpoint_dir).resolve(strict=True)
|
||||
R.require(not (directory / MANIFEST).exists(), 'Checkpoint is already sealed')
|
||||
before = C._tree_hashes(directory)
|
||||
record = _record(directory, {directory})
|
||||
R.require(before == C._tree_hashes(directory), 'Checkpoint changed while sealing')
|
||||
value = dict(schema=CHECKPOINT_SCHEMA, complete=True, files_sha256=before, segment_steps=record['steps'],
|
||||
global_tick_offset=record['global_tick_offset'], global_next_tick=record['global_next_tick'],
|
||||
counts_scope='segment_only', update_root_authority_sha256=record['update_root_authority_sha256'],
|
||||
input_policy=record['input_policy'], learning_pass_claimed=False,
|
||||
checkpoint_continuation_verified_by_GPU_comparison=False)
|
||||
R._save(directory / MANIFEST, value)
|
||||
return dict(path=str(directory / MANIFEST), sha256=_digest(directory / MANIFEST), **value)
|
||||
|
||||
|
||||
def run(authority_json, authority_sha256, out_dir, build_root, *, mode='light'):
|
||||
R.require(sys.dont_write_bytecode, 'Use python -B')
|
||||
admitted = validate_authority(authority_json, authority_sha256)
|
||||
value, parent, spec = admitted['value'], admitted['parent'], admitted['spec']
|
||||
R.require(mode == value['diagnostic_mode'], 'Mode differs from authority')
|
||||
protected = [*parent['ancestry_directories'], *(Path(path).parent for path in admitted['pins'])]
|
||||
case, out, build = R.execution_paths(admitted['case_dir'], out_dir, build_root, protected)
|
||||
ajdir = Path(admitted['after_meta']['aj_model_dir'])
|
||||
R._load('timing_queue', ajdir / 'timing_queue.py', R.PINS['apl-timing-lab-v1/timing_queue.py'])
|
||||
aj = R._load('conditioning_updated_sealed_AJ', ajdir / 'gpu_timing.py', R.AJ_SHA)
|
||||
runtime = UpdatedRuntime(mode, spec, admitted['helper'], admitted['after_plan'], admitted['after_meta'],
|
||||
admitted['pins'], aj.torch, admitted['paths']['after_overlay'], admitted['paths']['after_manifest'],
|
||||
parent=parent, authority=admitted)
|
||||
function, ast_audit = compile_updated(aj, runtime, mode)
|
||||
try:
|
||||
inherited = function(case, out, build)
|
||||
R.require(runtime.finished and runtime.restorations == runtime.installations == 1 and inherited['complete'], 'Incomplete new continuation')
|
||||
R.require(inherited['effective_weights_raw_sha256'] == value['expected_effective_weight_after_sha256'], 'Runtime effective identity differs')
|
||||
_check(admitted['pins'])
|
||||
load_checkpoint(parent['directory'], parent['manifest_sha256'])
|
||||
summary = R._read_json(out / 'summary.json')
|
||||
R.require(summary == runtime.summary(inherited), 'Stored updated summary differs')
|
||||
R._save(out / 'boundary-restore-audit.json', runtime.restore_audit)
|
||||
provenance = dict(schema=PROVENANCE_SCHEMA, complete=True, mode=mode,
|
||||
source_file=str(Path(__file__).resolve()), source_sha256=_digest(__file__),
|
||||
authority_file=str(admitted['authority']), authority_sha256=authority_sha256,
|
||||
ast=ast_audit, input_sha256=admitted['pins'], old_globals_patched=False, weights_updated_during_run=False,
|
||||
global_tick_offset=parent['global_next_tick'], global_next_tick=parent['global_next_tick']+spec['steps'],
|
||||
parent_checkpoint_manifest_sha256=parent['manifest_sha256'], U_recomputed_here=False,
|
||||
external_CPU_validation_receipt_bound=value['transition'] == 'epoch_update',
|
||||
external_registration_process_and_probe_semantics_verified_here=False, learning_pass_claimed=False)
|
||||
for key, name in (('summary_sha256','summary.json'), ('finite_audit_sha256','finite-audit.json'),
|
||||
('terminal_queues_sha256','terminal-queues.npz'), ('overlay_audit_sha256','overlay-audit.json'), ('state_sha256','state.npz')):
|
||||
provenance[key] = _digest(out / name)
|
||||
R._save(out / 'runtime-provenance.json', provenance)
|
||||
receipt = dict(schema='conditioning-updated-receipt-v1', complete=True,
|
||||
authority_file=str(admitted['authority']), authority_sha256=authority_sha256,
|
||||
parent_checkpoint_dir=str(parent['directory']), parent_checkpoint_manifest_sha256=parent['manifest_sha256'],
|
||||
global_tick_offset=parent['global_next_tick'], global_next_tick=parent['global_next_tick']+spec['steps'],
|
||||
segment_steps=spec['steps'], update_root_authority_sha256=admitted['update_root_authority_sha256'],
|
||||
input_policy=value['input_policy'], payload_sha256=C._tree_hashes(out), weights_updated_during_run=False,
|
||||
counts_scope='segment_only_not_lifetime', checkpoint_continuation_verified_by_GPU_comparison=False, learning_pass_claimed=False)
|
||||
R._save(out / RECEIPT, receipt)
|
||||
sealed = seal_checkpoint(out)
|
||||
return dict(summary, checkpoint_manifest_sha256=sealed['sha256'])
|
||||
except Exception as error:
|
||||
if out.is_dir() and not (out / 'updated-error.json').exists():
|
||||
R._save(out / 'updated-error.json', dict(complete=False, type=type(error).__name__, message=str(error), retry_forbidden=True))
|
||||
raise
|
||||
@@ -0,0 +1,174 @@
|
||||
"""Fresh CPU-process revalidation of a sealed epoch's actual update.
|
||||
|
||||
This does not run a brain or E.postprocess_epoch and writes only one exclusive
|
||||
receipt. The caller must pin the source, authority and successful process to its
|
||||
registration. A supplied SHA is not independent scientific authorization.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
LAB = Path(__file__).resolve().parent.parent/'olfactory-conditioning-lab-v1'
|
||||
E_SHA = '757935a4815d9f625640df685184ed3fe44a8845323562796da7aa43cbb194e1'
|
||||
Q_SHA = 'b88fd9a88d9f92d5c4d042b90f2129b015e8d4bd810c41351ee573241e2d4c2e'
|
||||
U_SHA = '96efff678cff910654eb08e86f1a17789e4e5589e340345f419c7027a7d547e2'
|
||||
CMP_SHA = '5a2403f11bc08d65a9d242ac2cf9686b850e0c3680d65659f785e9b6b50c0238'
|
||||
FILES = ('chain-receipt.json','update-receipt.json','delta-after.npz','overlay-manifest.json')
|
||||
|
||||
|
||||
def require(ok,message):
|
||||
if not ok: raise ValueError(message)
|
||||
|
||||
|
||||
def digest(path):
|
||||
h=hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for b in iter(lambda:stream.read(8<<20),b''):h.update(b)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def same(a,b): return a.dtype==b.dtype and a.shape==b.shape and a.tobytes()==b.tobytes()
|
||||
|
||||
|
||||
def unlinked(path):
|
||||
path=Path(path).absolute()
|
||||
require(not any(p.is_symlink() or (hasattr(p,'is_junction') and p.is_junction())
|
||||
for p in (path,*path.parents)), 'Linked receipt/update path forbidden')
|
||||
return path
|
||||
|
||||
|
||||
def load(name,path,expected):
|
||||
raw=Path(path).read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest()==expected and name not in sys.modules,'Unverified source/module binding')
|
||||
spec=importlib.util.spec_from_file_location(name,path);module=importlib.util.module_from_spec(spec)
|
||||
sys.modules[name]=module
|
||||
exec(compile(raw,str(path),'exec'),module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def chain_binding(chain,authority,authority_sha,pins,paths,checkpoint,hashes):
|
||||
require(chain.get('schema')=='phase4an-epoch-postprocess-chain-v1' and chain.get('complete') is True,
|
||||
'Incomplete epoch update chain')
|
||||
for flag in ('weights_installed','brain_executed','learning_pass_claimed','candidate_generated'):
|
||||
require(chain.get(flag) is False,'Wrong chain scope: '+flag)
|
||||
require(chain['coordinator_source_sha256']==E_SHA and chain['authority_sha256']==authority_sha and
|
||||
chain['epoch_id']==authority['epoch_id'] and chain['command']==authority['command'] and
|
||||
chain['diagnostic_mode']==authority['diagnostic_mode'],'Epoch authority/command differs')
|
||||
require(chain['source_neural_checkpoint_dir']==str(checkpoint) and
|
||||
chain['source_neural_checkpoint_manifest_sha256']==authority['checkpoint_manifest_sha256'] and
|
||||
chain['input_files_sha256']=={str(p):v for p,v in pins.items()},'Actual checkpoint/input binding differs')
|
||||
for field,role in (('source_state_file_sha256','state'),('source_spec_sha256','spec'),
|
||||
('source_requests_sha256','requests'),('before_overlay_file_sha256','overlay_before'),
|
||||
('before_overlay_manifest_sha256','overlay_manifest_before')):
|
||||
require(chain[field]==pins[paths[role]],'Chain input differs: '+role)
|
||||
expected={name:hashes[name] for name in FILES if name!='chain-receipt.json'}
|
||||
require(chain['output_files_sha256']==expected and chain['after_overlay_file_sha256']==hashes['delta-after.npz'] and
|
||||
chain['after_overlay_manifest_sha256']==hashes['overlay-manifest.json'],'Chain output differs')
|
||||
|
||||
|
||||
def validate(epoch_authority,authority_sha,update_dir,chain_sha,receipt_file):
|
||||
require(sys.dont_write_bytecode and 'torch' not in sys.modules and 'runtime_light' not in sys.modules,
|
||||
'Run in a fresh Python -B CPU process')
|
||||
os.environ['CUDA_VISIBLE_DEVICES']=''
|
||||
e=load('_conditioning_execution_E_validator',LAB/'conditioning_epoch.py',E_SHA)
|
||||
load('engineering_compare',LAB/'engineering_compare.py',CMP_SHA)
|
||||
q=load('_conditioning_execution_Q_validator',LAB/'conditioning_preflight_compare.py',Q_SHA)
|
||||
value,paths,pins,checkpoint,authority_path=e._authority(epoch_authority,authority_sha)
|
||||
c,r,u=e._production_dependencies(paths,pins) # The only R is C.R; no ordinary runtime loader.
|
||||
directory=unlinked(update_dir).resolve(strict=True);out=unlinked(receipt_file)
|
||||
protected={checkpoint,directory,*[p.parent for p in pins]}
|
||||
require(out.parent.is_dir() and not out.exists() and not any(out.resolve().is_relative_to(p) for p in protected),
|
||||
'Receipt must be new and outside every frozen input/output directory')
|
||||
require(set(p.name for p in directory.iterdir())==set(FILES) and
|
||||
all((directory/n).is_file() and not (directory/n).is_symlink() for n in FILES),'Expected exact four update files')
|
||||
hashes={n:digest(directory/n) for n in FILES}
|
||||
require(e._sha(chain_sha) and hashes['chain-receipt.json']==chain_sha,'Chain differs from external SHA')
|
||||
own=digest(__file__);chain=e._read(directory/'chain-receipt.json')
|
||||
chain_binding(chain,value,authority_sha,pins,paths,checkpoint,hashes)
|
||||
parent=c.load_checkpoint(checkpoint,value['checkpoint_manifest_sha256'])
|
||||
command=value['command'];spec=e._read(paths['spec'])
|
||||
r.validate_spec(spec,paths['spec'].parent)
|
||||
require(parent['fresh'] is True and parent['global_tick_offset']==0 and parent['steps']==command['steps']==spec['steps'] and
|
||||
parent['summary']['diagnostic_mode']==value['diagnostic_mode'],'Wrong actual epoch/state scope')
|
||||
for role in ('spec','requests','overlay_before','overlay_manifest_before'):
|
||||
require(parent['provenance']['input_sha256'].get(str(paths[role]))==pins[paths[role]],'Runtime input differs: '+role)
|
||||
require(parent['manifest']['files_sha256']['state.npz']==pins[paths['state']],'State not sealed by this checkpoint')
|
||||
_,before,before_meta,_=r.load_overlay(paths['overlay_before'],paths['overlay_manifest_before'])
|
||||
_,after,after_meta,_=r.load_overlay(directory/'delta-after.npz',directory/'overlay-manifest.json')
|
||||
graph=Path(spec['graph_dir']).resolve();apl=Path(spec['apl_bundle_dir']).resolve()
|
||||
for location in [graph/n for n in e.GRAPH_FILES]+[apl/n for n in e.APL_FILES]+[Path(spec['coefficients_path']).resolve()]:
|
||||
require(location in pins,'Missing complete graph/APL/coefficient pin')
|
||||
require(paths['canonical_kc']==apl/'kc_globals.npy','Canonical KC path differs')
|
||||
for role,prefix in (('mask','mask'),('base_candidate','base_candidate'),('am_overlay_source','am_overlay')):
|
||||
require(Path(before_meta[prefix+'_path']).resolve()==paths[role] and before_meta[prefix+'_sha256']==pins[paths[role]],'Overlay input differs')
|
||||
aj=Path(before_meta['aj_model_dir']).resolve()
|
||||
for relative,sha in r.PINS.items():require(pins.get((aj.parent/relative).resolve())==sha,'Missing original dependency pin')
|
||||
mapping=e._npz(paths['candidate_map'],('edge_id','source_neuron_idx','target_neuron_idx','target_compartment_verbatim'))
|
||||
mask=np.load(paths['mask'],allow_pickle=False);kc=np.load(paths['kc'],allow_pickle=False)
|
||||
canonical=np.load(paths['canonical_kc'],allow_pickle=False);base=np.load(paths['base_candidate'],allow_pickle=False)
|
||||
e._vector(mask,'int64',14232,'mask');e._vector(kc,'int32',4064,'KC');e._vector(canonical,'int32',4064,'canonical KC')
|
||||
e._vector(base,'float32',14232,'base')
|
||||
require(np.all((mask>=0)&(mask<25582938)) and np.all(mask[1:]>mask[:-1]) and
|
||||
np.all((kc>=0)&(kc<166700)) and len(np.unique(kc))==len(kc),
|
||||
'Candidate/KC range or uniqueness differs')
|
||||
require(same(kc,canonical) and same(mask,mapping['edge_id']) and same(mask,before['edge_id']) and same(mask,after['edge_id']),
|
||||
'KC/candidate membership differs')
|
||||
require(same(base,before['base_candidate_mv']) and same(base,after['base_candidate_mv']),'Original base changed')
|
||||
maps={}
|
||||
try:
|
||||
for n,dtype,count in (('nodes','int32',166700),('edge_id','int64',25582938),('src','int32',25582938),('dst','int32',25582938)):
|
||||
maps[n]=np.load(graph/(n+'.npy'),allow_pickle=False,mmap_mode='r');e._vector(maps[n],dtype,count,n)
|
||||
require(np.array_equal(maps['nodes'],np.arange(166700,dtype=np.int32)) and same(maps['edge_id'][mask],mask),'Not canonical full graph')
|
||||
require(same(mapping['source_neuron_idx'],maps['src'][mask]) and same(mapping['target_neuron_idx'],maps['dst'][mask]),
|
||||
'Candidate endpoints differ from actual connectome')
|
||||
finally:
|
||||
for a in maps.values():a._mmap.close()
|
||||
state=e._npz(paths['state'],('step','neuron_idx','counts','v','g','ref'))
|
||||
require(all(same(state[n],parent['state'][n]) for n in state),'Actual sealed event/state mismatch')
|
||||
require(parent['overlay']['delta_raw_sha256']==r._raw(before['plastic_delta_mv']) and
|
||||
chain['runtime_delta_before_raw_sha256']==r._raw(before['plastic_delta_mv']) and
|
||||
chain['runtime_effective_weights_raw_sha256']==parent['summary']['effective_weights_raw_sha256'], 'Actual before installation differs')
|
||||
update=e._read(directory/'update-receipt.json')
|
||||
require(update['payload_sha256']==chain['update_receipt_payload_sha256'],'Update receipt chain differs')
|
||||
u.verify_receipt(update,step=state['step'],neuron_idx=state['neuron_idx'],kc=kc,candidate_edge_id=mask,
|
||||
candidate_sources=mapping['source_neuron_idx'],candidate_targets=mapping['target_neuron_idx'],
|
||||
candidate_compartments=mapping['target_compartment_verbatim'],delta_before=before['plastic_delta_mv'],base_candidate=base,
|
||||
steps=command['steps'],n_neurons=166700,compartment=command['compartment'],us_tick=command['us_tick'],
|
||||
d_command=command['d_command'],frozen=command['frozen'],trace_backend=command['trace_backend'],
|
||||
bridge_source=paths['eligibility_bridge_source'],phase4j_source=paths['phase4j_source'])
|
||||
binding=q.audit_delta_binding(before['plastic_delta_mv'],after['plastic_delta_mv'],after['plastic_delta_mv'],
|
||||
update_receipt=update,parent_snapshot_sha256=pins[paths['overlay_before']],child_manifest=after_meta)
|
||||
require(binding['pass_all'],'Actual after array differs from recomputed receipt')
|
||||
import torch
|
||||
require(os.environ['CUDA_VISIBLE_DEVICES']=='' and not torch.cuda.is_initialized(),'CPU verifier initialized CUDA')
|
||||
e._check_files(pins);c.load_checkpoint(checkpoint,value['checkpoint_manifest_sha256'])
|
||||
for file,sha in (('conditioning_epoch.py',E_SHA),('conditioning_preflight_compare.py',Q_SHA),('engineering_compare.py',CMP_SHA)):
|
||||
require(digest(LAB/file)==sha,'Verifier dependency changed')
|
||||
require(hashes=={n:digest(directory/n) for n in FILES} and own==digest(__file__),'Source/update changed during validation')
|
||||
receipt=dict(schema='conditioning-update-cpu-validation-v1',complete=True,epoch_authority_sha256=authority_sha,
|
||||
parent_checkpoint_manifest_sha256=value['checkpoint_manifest_sha256'],update_files_sha256=hashes,
|
||||
before_overlay_sha256=pins[paths['overlay_before']],before_manifest_sha256=pins[paths['overlay_manifest_before']],
|
||||
after_overlay_sha256=hashes['delta-after.npz'],after_manifest_sha256=hashes['overlay-manifest.json'],
|
||||
before_delta_raw_sha256=r._raw(before['plastic_delta_mv']),after_delta_raw_sha256=r._raw(after['plastic_delta_mv']),
|
||||
update_receipt_payload_sha256=update['payload_sha256'],validator_source=dict(path=str(Path(__file__).resolve()),sha256=own),
|
||||
frozen_U_source_sha256=U_SHA,frozen_U_verify_receipt_recomputed=True,actual_sealed_events_used=True,
|
||||
full_candidate_mapping_verified=True,brain_executed=False,learning_pass_claimed=False)
|
||||
e._save(out,receipt)
|
||||
return receipt
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--authority',required=True);parser.add_argument('--authority-sha256',required=True)
|
||||
parser.add_argument('--update-dir',required=True);parser.add_argument('--chain-sha256',required=True)
|
||||
parser.add_argument('--receipt',required=True);args=parser.parse_args()
|
||||
validate(args.authority,args.authority_sha256,args.update_dir,args.chain_sha256,args.receipt)
|
||||
print(json.dumps(dict(complete=True,receipt=args.receipt,sha256=digest(args.receipt))),flush=True)
|
||||
@@ -0,0 +1,41 @@
|
||||
# Persistent-process engineering replay — 2026-10-01
|
||||
|
||||
User authorized continuing performance optimization after the exact V100 eligibility prototype. This is a NEW bounded engineering experiment, not a resumption, retry, or extension of the stopped scientific Phase4AR run. No future assay, learning run, game or decoder is authorized here.
|
||||
|
||||
## Immutable inputs and selection
|
||||
|
||||
- Original registration SHA256: `b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740`.
|
||||
- Original scientific source commit: `80aeb2093db655329774eff7b32fb6e417b8b40b`.
|
||||
- Prior exact-GPU replay code commit: `221e1f13f758ebe8d9f188bab976c361f7cacf45`.
|
||||
- Fixed real fixture manifest: `/home/qishizhe/phase4ar-v100-acceleration-20261001/fixtures/manifest.json`.
|
||||
- Fixture manifest SHA256: `481df128d39bf28e5984a6f2e5757f83d45cb7a6136f8d2843ecc0a67eca437b`.
|
||||
- Use all14 fixtures in their existing order: first and last committed task by task-ID within7arms, chosen in the prior experiment without reading outcomes. Coverage is only the available committed prefix, not the complete scientific design.
|
||||
- All anatomical data, sources, saved requests, before-overlay, historical checkpoint and original update references remain read-only. No new update is installed. No request/RNG regeneration, learning-rate, sign, threshold, timestep or eligibility change.
|
||||
|
||||
## CPU lanes
|
||||
|
||||
Measure original U in fresh processes and separate resident producer/verifier processes. The verifier owns independently loaded inputs and invokes unchanged original U recomputation. This measures update-interface overhead, NOT full AQ authority/checkpoint verification. Use3 fixed passes; all outputs/receipts must match the original CPU oracle.
|
||||
|
||||
Also measure unchanged original E.postprocess_epoch in a resident CPU process,2 fixed passes, new output per call. Preserve all checks inside E. Original full AQ validation remains a fresh CPU subprocess; never bypass its fresh-interpreter guards. Profile function costs separately; profiler-instrumented timings are not speed benchmarks.
|
||||
|
||||
## Brain lanes
|
||||
|
||||
Use only the original scientific environment and admitted RTX4090 for this pass. Original Torch lacks V100 support for its frozen whole-brain runtime; V100 eligibility compatibility does not establish whole-brain compatibility.
|
||||
|
||||
Run unchanged R.run_light and original checkpoint seal/read functions. Baseline:14 fresh child processes. Candidate: one resident child executes14 forward then14 reverse. Every call creates a fresh neuronal/APL state through the unmodified function. No use of checkpoint continuation, old BrainRuntime, custom state reset, or previous effective-weight accumulation. This first pass reuses interpreter, verified module caches, CUDA context, and the runtime's existing caches only; it does not cache GPU graph tensors or rewrite the numerical loop.
|
||||
|
||||
Compare every event, counts, final v/g/ref, spike ring, APL state/pending/phase, effective-weight hash and request acceptance against the historical sealed trial. Check exact dtypes, shapes and bytes. Verify source/input pins before and after trials. Failures stop the affected lane and retain evidence; no selection of passing trials.
|
||||
|
||||
## Audit, timing and bounds
|
||||
|
||||
Each resident job has a completion record but NOT a fictitious OS exit code. Its session receives an independently observed actual process exit only when the whole child exits. No old AR ledger is modified.
|
||||
|
||||
Report initialization/compilation, immutable-input authentication, execution, checkpoint seal/read, comparison, output I/O and complete child wall times separately. Report data transfer, recording and checks that remain. Independent stage measurements cannot be added and advertised as a measured end-to-end training speedup; no new full-run ETA from isolated kernels.
|
||||
|
||||
Run CPU and GPU timing lanes serially to avoid artificial contention. Check all3 ComfyUI queues before each GPU trial; no service eviction. Maximum engineering workflow30minutes, each child15minutes, new artifacts capped at2GiB and100GiB minimum free disk reserve. If an infrastructure or candidate bug occurs, preserve the attempt and correct only new source/attempt paths; never retry scientific AR tasks.
|
||||
|
||||
Outputs: `/home/qishizhe/phase4ar-pipeline-acceleration-20261001/`. Source: new `conditioning-pipeline-acceleration-v1` directory in independent worktree `/home/qishizhe/digital-drosophila-v100-acceleration`.
|
||||
|
||||
Pre/post checks: original saved64,034-file Phase4AR inventory,16 registered sources, previous acceleration artifact manifest and previous acceleration source hashes. This is NOT a new Phase1–4AQ numerical regression.
|
||||
|
||||
Possible gate: `PASS-PERSISTENT-REPLAY-EQUIVALENCE` for tested lanes only. It is not a learned-model candidate, formal production-runtime promotion, full scientific-gate pass, or permission to resume30,000epochs.
|
||||
@@ -0,0 +1,566 @@
|
||||
"""Bounded unchanged-runtime replay: 14 fresh execs versus one resident exec.
|
||||
|
||||
Only the original R.run_light is executed, in the original 4090 environment.
|
||||
Every call allocates fresh neural/APL state. No GPU graph residency, numerical
|
||||
optimization, conditioning coordinator, generated overlay, or AR resume is used.
|
||||
All output is new, outside the scientific tree. Original checkpoints are read.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
|
||||
ROOT = Path('/data/digital-drosophila')
|
||||
MODEL = ROOT / 'models/male-cns-lif'
|
||||
EXP = ROOT / 'experiments/phase4ar-normal-conditioning'
|
||||
ORIGINAL_ENV = MODEL / '.venv'
|
||||
ORIGINAL_PYTHON = ORIGINAL_ENV / 'bin/python'
|
||||
REG_PATH = EXP / 'protocol/preregistered.json'
|
||||
REG_SHA = 'b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740'
|
||||
SOURCE_COMMIT = '80aeb2093db655329774eff7b32fb6e417b8b40b'
|
||||
GPU = 'GPU-79f3a85d-adce-7833-7003-6488140ca596'
|
||||
R_PATH = MODEL / 'olfactory-conditioning-lab-v1/runtime_light.py'
|
||||
C_PATH = MODEL / 'olfactory-conditioning-lab-v1/runtime_continuation.py'
|
||||
AP_PATH = MODEL / 'conditioning-interface-v2/isolated_workers.py'
|
||||
R_SHA = '522b8c31ea938890fe15364fccd25ccc5bded54101754909f255532e7ad01aae'
|
||||
C_SHA = '0b8e8e0a6a23a079dc62a88355ce355d53b3ae22f6665519a8f6aef2dcfc5aba'
|
||||
AP_SHA = 'e47651a8ea99d7c44115107ff6b5dc71312183609ae11c891db65bb21ed61e30'
|
||||
STATE_KEYS = ('step', 'neuron_idx', 'counts', 'v', 'g', 'ref')
|
||||
TERMINAL_KEYS = ('spike_ring', 'apl_state', 'apl_pending', 'next_tick')
|
||||
ARMS = ('cs_only', 'd_zero', 'dan_only', 'frozen', 'paired', 'random_reward', 'unpaired')
|
||||
SUMMARY_KEYS = ('completed_ticks', 'nodes', 'edges', 'precision', 'apl_precision', 'state_units',
|
||||
'total_spikes', 'requested', 'accepted_requests', 'rejected_requests', 'arriving_edges',
|
||||
'accepted_arriving_edges', 'counts_match_sparse_events', 'all_finite', 'record_history',
|
||||
'apl_fast_edges_zeroed', 'kc_targets_present', 'effective_weights_raw_sha256', 'apl_schedule',
|
||||
'apl_si_conversion', 'apl_delay_steps', 'pending_generated_count', 'pending_initial_zero_prefix',
|
||||
'pending_tail_shape', 'future_generated_decay_tail_included', 'diagnostic_mode',
|
||||
'within_trial_weight_updates', 'checkpoint_continuation_used', 'explicit_steps_executed',
|
||||
'first_failure_tick')
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
if not condition:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def path_checked(path):
|
||||
path = Path(path)
|
||||
require(path.is_absolute() and '..' not in path.parts, 'Absolute nonescaping path required')
|
||||
require(not any(p.is_symlink() or (hasattr(p, 'is_junction') and p.is_junction())
|
||||
for p in (path, *path.parents)), 'Linked path forbidden: ' + str(path))
|
||||
return path
|
||||
|
||||
|
||||
def sha(path):
|
||||
digest = hashlib.sha256()
|
||||
with path_checked(path).open('rb') as stream:
|
||||
for block in iter(lambda: stream.read(8 << 20), b''):
|
||||
digest.update(block)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def read(path):
|
||||
def pairs(items):
|
||||
result = {}
|
||||
for key, value in items:
|
||||
require(key not in result, 'Duplicate JSON key')
|
||||
result[key] = value
|
||||
return result
|
||||
return json.loads(path_checked(path).read_text(encoding='utf-8'), object_pairs_hook=pairs,
|
||||
parse_constant=lambda _: (_ for _ in ()).throw(ValueError('Nonfinite JSON')))
|
||||
|
||||
|
||||
def save(path, value):
|
||||
with path_checked(path).open('x', encoding='utf-8', newline='\n') as stream:
|
||||
json.dump(value, stream, indent=2, sort_keys=True, allow_nan=False)
|
||||
stream.write('\n')
|
||||
|
||||
|
||||
def pin_add(pins, path, expected):
|
||||
path = str(path_checked(path))
|
||||
expected = expected if isinstance(expected, str) else expected['sha256']
|
||||
require(isinstance(expected, str) and len(expected) == 64
|
||||
and all(c in '0123456789abcdef' for c in expected), 'Invalid SHA256')
|
||||
require(path not in pins or pins[path] == expected, 'Conflicting authority pin: ' + path)
|
||||
pins[path] = expected
|
||||
|
||||
|
||||
def verify(pins):
|
||||
for path, expected in pins.items():
|
||||
require(sha(path) == expected, 'Pinned input changed: ' + path)
|
||||
|
||||
|
||||
def contained(root, relative):
|
||||
path = path_checked(root / relative)
|
||||
require(path.is_relative_to(root), 'Fixture path leaves exported root')
|
||||
return path
|
||||
|
||||
|
||||
def load_source(name, path, expected):
|
||||
raw = path_checked(path).read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest() == expected and name not in sys.modules,
|
||||
'Unverified or repeated module binding: ' + name)
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[name] = module
|
||||
exec(compile(raw, str(path), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def fixture_order(count):
|
||||
require(count == 14, 'The fixed manifest must contain exactly 14 real fixtures')
|
||||
return [('forward', index) for index in range(count)] + [('reverse', index) for index in range(count - 1, -1, -1)]
|
||||
|
||||
|
||||
def build_selection(fixtures, manifest_sha):
|
||||
"""Bind saved case/overlay and old checkpoint to the authenticated export."""
|
||||
fixtures = path_checked(fixtures)
|
||||
manifest_path = fixtures / 'manifest.json'
|
||||
require(sha(manifest_path) == manifest_sha, 'Export manifest differs from external pin')
|
||||
manifest = read(manifest_path)
|
||||
require(manifest.get('complete') is True and manifest.get('schema') == 'conditioning-acceleration-fixtures-v1'
|
||||
and manifest.get('registration_sha256') == REG_SHA and manifest.get('source_code_commit') == SOURCE_COMMIT,
|
||||
'Unexpected completed real export authority')
|
||||
records = manifest['fixtures']
|
||||
fixture_order(len(records))
|
||||
require(len({record['fixture_id'] for record in records}) == 14, 'Duplicate fixture identity')
|
||||
require({arm: sum(row['task']['arm'] == arm for row in records) for arm in ARMS}
|
||||
== {arm: 2 for arm in ARMS}, 'Expected the declared two fixtures per available arm')
|
||||
require(sha(REG_PATH) == REG_SHA, 'Original AR registration changed')
|
||||
registration = read(REG_PATH)
|
||||
require(registration['source_code_commit'] == SOURCE_COMMIT
|
||||
and registration['scientific_scope'] == 'normal-acquisition-only', 'Original registration role differs')
|
||||
global_pins = {str(manifest_path): manifest_sha, str(REG_PATH): REG_SHA,
|
||||
str(R_PATH): R_SHA, str(C_PATH): C_SHA, str(AP_PATH): AP_SHA}
|
||||
for relative, info in manifest['files'].items():
|
||||
pin_add(global_pins, contained(fixtures, relative), info)
|
||||
verify(global_pins)
|
||||
rows = []
|
||||
for record in records:
|
||||
name = record['fixture_id']
|
||||
directory = contained(fixtures, name)
|
||||
require(read(directory / 'fixture.json') == record
|
||||
and record['exact_stored_delta_and_trace_verified'] is True
|
||||
and record['original_validator_verified_full_graph_mapping'] is True
|
||||
and record['full_canonical_KC_count'] == 4064 and record['full_candidate_edge_count'] == 14232,
|
||||
'Fixture lacks original full mapping/reference evidence')
|
||||
pins = dict(global_pins)
|
||||
for path, info in read(directory / 'source-file-pins.json').items():
|
||||
pin_add(pins, path, info)
|
||||
task = record['task']
|
||||
key = 'task-' + hashlib.sha256(task['task_id'].encode()).hexdigest()
|
||||
brain_name = key + '--brain'
|
||||
job_path = EXP / 'jobs' / (brain_name + '.json')
|
||||
process_path = EXP / 'receipts' / brain_name / 'process.json'
|
||||
authority_path = EXP / 'jobs' / (key + '.authority.json')
|
||||
require(all(str(p) in pins for p in (job_path, process_path, authority_path)),
|
||||
'Original brain job/process/authority not bound by exported source pins')
|
||||
verify({str(p): pins[str(p)] for p in (job_path, process_path, authority_path)})
|
||||
job, process, authority = read(job_path), read(process_path), read(authority_path)
|
||||
require(authority == read(directory / 'authority.json')
|
||||
and sha(authority_path) == record['authority_sha256'], 'Export authority differs from sealed original')
|
||||
require(job['kind'] == 'brain' and job['job_id'] == brain_name
|
||||
and job['schema'] == 'phase4ap-isolated-worker-job-v1'
|
||||
and job['registration_sha256'] == REG_SHA and job['worker_sha256'] == AP_SHA
|
||||
and job['diagnostic_mode'] == 'light', 'Original brain job differs')
|
||||
require(process['complete'] is True and type(process['exit_code']) is int and process['exit_code'] == 0
|
||||
and process['timed_out'] is False and process['exit_observed_by_parent'] is True
|
||||
and process.get('launch_error') is None and process['job_sha256'] == pins[str(job_path)]
|
||||
and process['entry_id'] == brain_name and process['registration_sha256'] == REG_SHA
|
||||
and process['argv'][0] == str(ORIGINAL_PYTHON) and '-B' in process['argv'],
|
||||
'Original brain has no authenticated successful fresh exec')
|
||||
require(job['sources'] == {'runtime_light': {'path': str(R_PATH), 'sha256': R_SHA},
|
||||
'runtime_continuation': {'path': str(C_PATH), 'sha256': C_SHA}},
|
||||
'Original brain sources differ')
|
||||
for path, expected in job['input_sha256'].items():
|
||||
pin_add(pins, path, expected)
|
||||
for path, expected in authority['frozen_inputs'].items():
|
||||
pin_add(pins, path, expected)
|
||||
for info in authority['files'].values():
|
||||
pin_add(pins, info['path'], info['sha256'])
|
||||
case = path_checked(job['case_dir'])
|
||||
old = path_checked(job['output_dir'])
|
||||
require(case == EXP / 'cases' / key and old == EXP / 'runs' / key
|
||||
and authority['checkpoint_dir'] == str(old) and authority['epoch_id'] == task['task_id'],
|
||||
'Old brain case/checkpoint/task binding differs')
|
||||
for role, path in (('spec', case / 'spec.json'), ('requests', case / 'requests.npz'),
|
||||
('overlay_before', Path(job['overlay_file'])),
|
||||
('overlay_manifest_before', Path(job['overlay_manifest']))):
|
||||
require(authority['files'][role] == {'path': str(path), 'sha256': pins[str(path)]},
|
||||
'Original brain input role differs: ' + role)
|
||||
spec = read(case / 'spec.json')
|
||||
require(spec['steps'] == spec['max_steps'] == 1200 and spec['record_history'] is False
|
||||
and spec['apl_delay_steps'] == 18 and spec['dt_ms'] == .1
|
||||
and spec['within_trial_weight_updates'] is False, 'Replay is not the exact bounded fresh trial')
|
||||
require(not (case / 'arrays.npz').exists(), 'Unexpected neural initial-state override')
|
||||
old_manifest = old / 'checkpoint-manifest.json'
|
||||
pin_add(pins, old_manifest, authority['checkpoint_manifest_sha256'])
|
||||
require(sha(old_manifest) == authority['checkpoint_manifest_sha256'], 'Old checkpoint manifest changed')
|
||||
checkpoint = read(old_manifest)
|
||||
require(checkpoint['schema'] == 'phase4an-checkpoint-v1' and checkpoint['complete'] is True
|
||||
and checkpoint['segment_steps'] == 1200 and checkpoint['global_tick_offset'] == 0
|
||||
and checkpoint['global_next_tick'] == 1200, 'Expected sealed fresh reference checkpoint')
|
||||
for relative, expected in checkpoint['files_sha256'].items():
|
||||
pin_add(pins, contained(old, relative), expected)
|
||||
require(checkpoint['files_sha256']['state.npz'] == authority['files']['state']['sha256'],
|
||||
'Authority state differs from complete checkpoint inventory')
|
||||
rows.append(dict(fixture_id=name, task_id=task['task_id'], case_dir=str(case),
|
||||
overlay_file=job['overlay_file'], overlay_manifest=job['overlay_manifest'],
|
||||
original_checkpoint=str(old), original_checkpoint_manifest_sha256=authority['checkpoint_manifest_sha256'],
|
||||
original_brain_job=str(job_path), original_process_wall_seconds=process['end_to_end_seconds'],
|
||||
pins=pins))
|
||||
# All original and exported bytes are verified before any new GPU work.
|
||||
all_pins = dict(global_pins)
|
||||
for row in rows:
|
||||
for path, expected in row['pins'].items():
|
||||
pin_add(all_pins, path, expected)
|
||||
verify(all_pins)
|
||||
return dict(schema='conditioning-persistent-process-selection-v1', registration_sha256=REG_SHA,
|
||||
fixture_manifest=str(manifest_path), fixture_manifest_sha256=manifest_sha,
|
||||
fixed_count=14, fresh_order=list(range(14)), resident_order=fixture_order(14),
|
||||
selected_before_candidate_execution=True, fixtures=rows, all_pins=all_pins,
|
||||
numerical_implementation='unchanged frozen runtime_light.run_light',
|
||||
neural_reset='original function allocates fresh neuron/APL/queues for every call',
|
||||
request_rng='none during runtime; exact saved requests.npz reused',
|
||||
no_GPU_graph_residency=True, no_generated_overlay_installed=True)
|
||||
|
||||
|
||||
def array_evidence(array):
|
||||
return dict(dtype=array.dtype.str, shape=list(array.shape),
|
||||
sha256=hashlib.sha256(array.tobytes(order='C')).hexdigest())
|
||||
|
||||
|
||||
def compare_arrays(actual, expected, required):
|
||||
require(set(actual) == set(expected) == set(required), 'Checkpoint array schema differs')
|
||||
result = {}
|
||||
for name in required:
|
||||
left, right = array_evidence(actual[name]), array_evidence(expected[name])
|
||||
result[name] = dict(bitwise_exact=left == right, actual=left, expected=right)
|
||||
return result
|
||||
|
||||
|
||||
def compare_checkpoints(current, original, current_dir, original_dir):
|
||||
arrays = dict(state=compare_arrays(current['state'], original['state'], STATE_KEYS),
|
||||
terminal=compare_arrays(current['terminal'], original['terminal'], TERMINAL_KEYS))
|
||||
summaries = {key: dict(actual=current['summary'].get(key), expected=original['summary'].get(key),
|
||||
exact=key in current['summary'] and key in original['summary']
|
||||
and current['summary'][key] == original['summary'][key]) for key in SUMMARY_KEYS}
|
||||
files = {name: dict(actual=sha(current_dir / name), expected=sha(original_dir / name))
|
||||
for name in ('requests.csv', 'finite-audit.json', 'apl-pending-tail.float32.npy')}
|
||||
for item in files.values():
|
||||
item['exact'] = item['actual'] == item['expected']
|
||||
environment_equal = current['summary']['apl_component']['environment'] == original['summary']['apl_component']['environment']
|
||||
exact = (all(item['bitwise_exact'] for group in arrays.values() for item in group.values())
|
||||
and all(item['exact'] for item in summaries.values())
|
||||
and all(item['exact'] for item in files.values()) and environment_equal
|
||||
and current['fresh'] is original['fresh'] is True
|
||||
and current['global_tick_offset'] == original['global_tick_offset'] == 0)
|
||||
return dict(exact=exact, arrays=arrays, summaries=summaries, files=files,
|
||||
original_APL_environment_exact=environment_equal,
|
||||
comparison_scope='all six state arrays, four terminal arrays, requests, finite coverage, APL pending, effective weights and selected summaries')
|
||||
|
||||
|
||||
def check_environment():
|
||||
require(sys.dont_write_bytecode and Path(sys.prefix) == ORIGINAL_ENV,
|
||||
'Use the original registered environment Python -B')
|
||||
require(os.environ.get('CUDA_VISIBLE_DEVICES') == GPU
|
||||
and os.environ.get('CUDA_HOME') == '/usr/local/cuda'
|
||||
and os.environ.get('TORCH_CUDA_ARCH_LIST') == '8.9', 'Explicit original 4090 build environment required')
|
||||
|
||||
|
||||
def run_worker(job_path, job_sha):
|
||||
"""One exec; resident lane shares only original modules/caches, never state."""
|
||||
started = time.perf_counter()
|
||||
check_environment()
|
||||
require('torch' not in sys.modules and 'runtime_light' not in sys.modules, 'Worker must begin as a fresh exec')
|
||||
require(sha(job_path) == job_sha, 'Replay worker job changed')
|
||||
job = read(job_path)
|
||||
require(sha(Path(__file__).absolute()) == job['candidate_source_sha256'], 'Candidate source changed')
|
||||
require(sha(job['selection_file']) == job['selection_sha256'], 'Pinned selection changed')
|
||||
selection = read(job['selection_file'])
|
||||
require(selection['registration_sha256'] == REG_SHA and selection['fixed_count'] == 14, 'Worker selection authority differs')
|
||||
count = 1 if job['lane'] == 'fresh' else 28
|
||||
require(job['lane'] in ('fresh', 'resident') and len(job['runs']) == count, 'Worker lane count differs')
|
||||
if job['lane'] == 'resident':
|
||||
require(job['runs'] == [[direction, index] for direction, index in fixture_order(14)], 'Resident order differs')
|
||||
output = path_checked(job['output_root'])
|
||||
require(output.is_dir() and output.parent == path_checked(job['experiment_root']), 'Worker output root differs')
|
||||
load_started = time.perf_counter()
|
||||
ap = load_source('_pipeline_original_AP', AP_PATH, AP_SHA)
|
||||
runtime = load_source('runtime_light', R_PATH, R_SHA)
|
||||
checkpoint = None
|
||||
initial_module_seconds = time.perf_counter() - load_started
|
||||
records = []
|
||||
for sequence, (direction, index) in enumerate(job['runs']):
|
||||
require(time.time() < job['deadline_unix'], 'Bounded replay wall deadline reached')
|
||||
require(type(index) is int and 0 <= index < 14, 'Invalid fixed fixture index')
|
||||
row = selection['fixtures'][index]
|
||||
trial_started = time.perf_counter()
|
||||
authority_started = time.perf_counter()
|
||||
verify(row['pins'])
|
||||
require(sha(job_path) == job_sha and sha(job['selection_file']) == job['selection_sha256'], 'Worker authority changed')
|
||||
admission = ap._admit_brain()
|
||||
authority_before_seconds = time.perf_counter() - authority_started
|
||||
name = (f'{index:02d}-' if job['lane'] == 'fresh' else f'{sequence:02d}-{direction}-') + row['fixture_id']
|
||||
trial_root = output / name
|
||||
trial_root.mkdir(exist_ok=False)
|
||||
trial_dir = trial_root / 'trial'
|
||||
runtime_started = time.perf_counter()
|
||||
summary = runtime.run_light(Path(row['case_dir']), trial_dir, Path(job['build_root']),
|
||||
Path(row['overlay_file']), Path(row['overlay_manifest']))
|
||||
runtime_seconds = time.perf_counter() - runtime_started
|
||||
checkpoint_started = time.perf_counter()
|
||||
if checkpoint is None:
|
||||
checkpoint = load_source('_pipeline_original_checkpoint', C_PATH, C_SHA)
|
||||
seal = checkpoint.seal_checkpoint(trial_dir)
|
||||
current = checkpoint.load_checkpoint(trial_dir, seal['sha256'])
|
||||
original = checkpoint.load_checkpoint(row['original_checkpoint'], row['original_checkpoint_manifest_sha256'])
|
||||
fresh_reference = None
|
||||
if job['lane'] == 'resident':
|
||||
fresh_pin = job['fresh_references'][row['fixture_id']]
|
||||
require(sha(fresh_pin['report']) == fresh_pin['report_sha256'], 'Fresh reference report changed')
|
||||
fresh_reference = checkpoint.load_checkpoint(fresh_pin['checkpoint'], fresh_pin['checkpoint_manifest_sha256'])
|
||||
require(current['summary'] == summary, 'Current sealed summary differs from actual returned summary')
|
||||
checkpoint_seconds = time.perf_counter() - checkpoint_started
|
||||
compare_started = time.perf_counter()
|
||||
environment = ap._environment('brain')
|
||||
ap._verify_precision(environment, summary['apl_component']['environment'])
|
||||
comparison = compare_checkpoints(current, original, trial_dir, Path(row['original_checkpoint']))
|
||||
if fresh_reference is not None:
|
||||
comparison['fresh_reference'] = compare_checkpoints(current, fresh_reference, trial_dir, Path(fresh_pin['checkpoint']))
|
||||
comparison['exact'] = comparison['exact'] and comparison['fresh_reference']['exact']
|
||||
compare_seconds = time.perf_counter() - compare_started
|
||||
io_started = time.perf_counter()
|
||||
save(trial_root / 'comparison.json', comparison)
|
||||
comparison_io_seconds = time.perf_counter() - io_started
|
||||
require(comparison['exact'], 'Brain replay differs from original sealed checkpoint: ' + row['fixture_id'])
|
||||
after_started = time.perf_counter()
|
||||
verify(row['pins'])
|
||||
require(sha(Path(__file__).absolute()) == job['candidate_source_sha256'], 'Candidate source changed during trial')
|
||||
require(sha(job_path) == job_sha and sha(job['selection_file']) == job['selection_sha256'], 'Worker authority changed after trial')
|
||||
authority_after_seconds = time.perf_counter() - after_started
|
||||
report = dict(fixture_id=row['fixture_id'], direction=direction, sequence=sequence,
|
||||
fixed_index=index, lane=job['lane'], exact=True, original_checkpoint=row['original_checkpoint'],
|
||||
original_checkpoint_manifest_sha256=row['original_checkpoint_manifest_sha256'],
|
||||
current_checkpoint=str(trial_dir), current_checkpoint_manifest_sha256=seal['sha256'],
|
||||
original_brain_job=row['original_brain_job'], input_pins_verified_before_and_after=True,
|
||||
compared_array_count=len(STATE_KEYS) + len(TERMINAL_KEYS), comparison_sha256=sha(trial_root / 'comparison.json'),
|
||||
admission=admission, environment=environment,
|
||||
timings=dict(authority_before_seconds=authority_before_seconds, runtime_and_builtin_output_seconds=runtime_seconds,
|
||||
checkpoint_seal_and_load_seconds=checkpoint_seconds, comparison_seconds=compare_seconds,
|
||||
comparison_record_io_seconds=comparison_io_seconds, authority_after_seconds=authority_after_seconds,
|
||||
original_build_or_cache_seconds=summary['build_or_cache_seconds'],
|
||||
original_diagnostic_simulation_seconds=summary['diagnostic_simulation_seconds'],
|
||||
trial_wall_before_report_seconds=time.perf_counter() - trial_started),
|
||||
timing_limit='Original runtime includes its own I/O; it is not instrumented or subtracted. Build/import costs remain in recorded wall time.',
|
||||
process_pid=os.getpid(), process_exit_claimed=False,
|
||||
neural_state_fresh_each_call=True, within_trial_weight_updates=False,
|
||||
only_saved_before_overlay_used=True, generated_delta_installed=False, original_experiment_resumed=False,
|
||||
learning_success_claimed=False, GPU_graph_residency=False)
|
||||
report_started = time.perf_counter()
|
||||
save(trial_root / 'replay-report.json', report)
|
||||
records.append(dict(report=str(trial_root / 'replay-report.json'), sha256=sha(trial_root / 'replay-report.json'),
|
||||
report_io_seconds=time.perf_counter() - report_started,
|
||||
trial_wall_seconds=time.perf_counter() - trial_started, **report))
|
||||
print(json.dumps(dict(lane=job['lane'], fixture=row['fixture_id'], direction=direction, exact=True)), flush=True)
|
||||
# Checkpoints hold owned CPU arrays only; no state is fed to the next run.
|
||||
del current, original, fresh_reference
|
||||
verify(selection['all_pins'])
|
||||
result = dict(complete=True, lane=job['lane'], count=len(records), records=records,
|
||||
process_pid=os.getpid(), initial_module_load_seconds=initial_module_seconds,
|
||||
worker_wall_seconds=time.perf_counter() - started, all_bitwise_exact=True,
|
||||
original_runtime_unchanged=True, fresh_neural_state_every_trial=True,
|
||||
process_exit_independently_observed=False, original_experiment_resumed=False,
|
||||
original_files_modified=False, scientific_learning_pass_claimed=False)
|
||||
save(Path(job['result_file']), result)
|
||||
return result
|
||||
|
||||
|
||||
def launch(job, job_path, process_dir, deadline):
|
||||
save(job_path, job)
|
||||
job_sha = sha(job_path)
|
||||
argv = [str(ORIGINAL_PYTHON), '-B', str(Path(__file__).absolute()),
|
||||
'--worker-job', str(job_path), '--worker-job-sha256', job_sha]
|
||||
environment = dict(os.environ, CUDA_VISIBLE_DEVICES=GPU, CUDA_HOME='/usr/local/cuda',
|
||||
MAX_JOBS='2', TORCH_CUDA_ARCH_LIST='8.9', PYTHONDONTWRITEBYTECODE='1',
|
||||
PATH=str(ORIGINAL_ENV / 'bin') + os.pathsep + '/usr/local/cuda/bin' + os.pathsep + os.environ.get('PATH', ''))
|
||||
label = job_path.stem
|
||||
stdout_path, stderr_path = process_dir / (label + '.stdout.log'), process_dir / (label + '.stderr.log')
|
||||
started = time.perf_counter()
|
||||
timeout = deadline - time.time()
|
||||
require(timeout > 0, 'Replay wall budget exhausted before spawn')
|
||||
returncode, timed_out, launch_error = None, False, None
|
||||
process = None
|
||||
terminated_child = False
|
||||
|
||||
def stop_child():
|
||||
nonlocal terminated_child
|
||||
if process is None:
|
||||
return
|
||||
terminated_child = True
|
||||
if process.poll() is None:
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait()
|
||||
|
||||
def interrupted(signum, _frame):
|
||||
stop_child()
|
||||
raise KeyboardInterrupt('Replay interrupted by signal ' + str(signum))
|
||||
|
||||
previous_handlers = {signum: signal.getsignal(signum) for signum in (signal.SIGTERM, signal.SIGINT)}
|
||||
try:
|
||||
for signum in previous_handlers:
|
||||
signal.signal(signum, interrupted)
|
||||
with stdout_path.open('xb') as stdout, stderr_path.open('xb') as stderr:
|
||||
process = subprocess.Popen(argv, cwd=Path(__file__).absolute().parent, env=environment,
|
||||
stdout=stdout, stderr=stderr)
|
||||
returncode = process.wait(timeout=timeout)
|
||||
except subprocess.TimeoutExpired:
|
||||
timed_out = True
|
||||
stop_child()
|
||||
returncode = process.returncode
|
||||
except OSError as exc:
|
||||
launch_error = f'{type(exc).__name__}: {exc}'
|
||||
stop_child()
|
||||
except BaseException:
|
||||
stop_child()
|
||||
raise
|
||||
finally:
|
||||
for signum, handler in previous_handlers.items():
|
||||
signal.signal(signum, handler)
|
||||
receipt = dict(argv=argv, job_sha256=job_sha, actual_returncode=returncode,
|
||||
timed_out=timed_out, launch_error=launch_error, child_whole_wall_seconds=time.perf_counter() - started,
|
||||
exit_independently_observed=returncode is not None, parent_pid=os.getpid(),
|
||||
child_pid=None if process is None else process.pid,
|
||||
child_terminated_on_failure=terminated_child,
|
||||
process_group_policy='inherits outer run_job owned process group; no nested session',
|
||||
stdout_sha256=sha(stdout_path) if stdout_path.exists() else None,
|
||||
stderr_sha256=sha(stderr_path) if stderr_path.exists() else None,
|
||||
receipt_scope='actual exec process; resident trial reports never claim individual process exits')
|
||||
save(process_dir / (label + '.json'), receipt)
|
||||
require(returncode == 0 and not timed_out and launch_error is None, 'Replay child failed; evidence retained: ' + label)
|
||||
result = read(job['result_file'])
|
||||
require(result['complete'] is True and result['all_bitwise_exact'] is True
|
||||
and result['lane'] == job['lane'] and result['count'] == len(job['runs']), 'Child result incomplete')
|
||||
for row in result['records']:
|
||||
require(sha(row['report']) == row['sha256'], 'Child trial report changed after exit')
|
||||
receipt['result_file'] = job['result_file']
|
||||
receipt['result_sha256'] = sha(job['result_file'])
|
||||
return receipt, result
|
||||
|
||||
|
||||
def run(fixtures, manifest_sha, output):
|
||||
started = time.perf_counter()
|
||||
deadline = time.time() + 900
|
||||
require(sys.dont_write_bytecode and Path(sys.prefix) == ORIGINAL_ENV,
|
||||
'Parent must use the original registered environment Python -B')
|
||||
output = path_checked(output)
|
||||
require(not output.exists() and output.parent.is_dir() and not output.is_relative_to(ROOT)
|
||||
and not output.is_relative_to(path_checked(fixtures))
|
||||
and not output.is_relative_to(Path(__file__).absolute().parent), 'Use a fresh output root outside all protected trees')
|
||||
output.mkdir()
|
||||
for name in ('fresh', 'resident', 'jobs', 'processes', 'build', 'sessions'):
|
||||
(output / name).mkdir()
|
||||
try:
|
||||
preparation_started = time.perf_counter()
|
||||
selection = build_selection(fixtures, manifest_sha)
|
||||
selection_path = output / 'selection.json'
|
||||
save(selection_path, selection)
|
||||
candidate_sha = sha(Path(__file__).absolute())
|
||||
save(output / 'authority.json', dict(registration_sha256=REG_SHA, fixture_manifest_sha256=manifest_sha,
|
||||
candidate_source_sha256=candidate_sha, selection_sha256=sha(selection_path),
|
||||
original_interpreter=str(ORIGINAL_PYTHON), gpu_uuid=GPU,
|
||||
fixed_trials=dict(fresh=14, resident_forward=14, resident_reverse=14),
|
||||
wall_budget_seconds=900, deadline_unix=deadline,
|
||||
preparation_seconds=time.perf_counter() - preparation_started,
|
||||
source_pins={str(R_PATH): R_SHA, str(C_PATH): C_SHA, str(AP_PATH): AP_SHA},
|
||||
cold_build_policy='one new shared candidate build directory; first fresh call includes cold build, no warm-up trials',
|
||||
existing_AR_not_resumed=True, numerical_implementation_unchanged=True,
|
||||
created_utc=datetime.now(timezone.utc).isoformat()))
|
||||
common = dict(selection_file=str(selection_path), selection_sha256=sha(selection_path),
|
||||
candidate_source_sha256=candidate_sha, build_root=str(output / 'build'),
|
||||
experiment_root=str(output), deadline_unix=deadline)
|
||||
children, fresh_records = [], []
|
||||
for index in range(14):
|
||||
label = f'fresh-{index:02d}'
|
||||
job = dict(common, lane='fresh', runs=[['fresh', index]], output_root=str(output / 'fresh'),
|
||||
result_file=str(output / 'sessions' / (label + '.json')))
|
||||
process, result = launch(job, output / 'jobs' / (label + '.json'), output / 'processes', deadline)
|
||||
children.append(process)
|
||||
fresh_records.extend(result['records'])
|
||||
fresh_references = {row['fixture_id']: dict(checkpoint=row['current_checkpoint'],
|
||||
checkpoint_manifest_sha256=row['current_checkpoint_manifest_sha256'],
|
||||
report=row['report'], report_sha256=row['sha256']) for row in fresh_records}
|
||||
job = dict(common, lane='resident', runs=fixture_order(14), output_root=str(output / 'resident'),
|
||||
fresh_references=fresh_references,
|
||||
result_file=str(output / 'sessions/resident.json'))
|
||||
process, resident = launch(job, output / 'jobs/resident.json', output / 'processes', deadline)
|
||||
children.append(process)
|
||||
require(time.time() < deadline, 'Replay exceeded bounded wall budget')
|
||||
verify(selection['all_pins'])
|
||||
require(sha(Path(__file__).absolute()) == candidate_sha, 'Candidate source changed')
|
||||
by_fresh = {row['fixture_id']: row for row in fresh_records}
|
||||
paired = []
|
||||
for row in resident['records']:
|
||||
reference = by_fresh[row['fixture_id']]
|
||||
paired.append(dict(fixture_id=row['fixture_id'], direction=row['direction'],
|
||||
fresh_trial_wall_seconds=reference['trial_wall_seconds'],
|
||||
resident_trial_wall_seconds=row['trial_wall_seconds'],
|
||||
fresh_runtime_and_output_seconds=reference['timings']['runtime_and_builtin_output_seconds'],
|
||||
resident_runtime_and_output_seconds=row['timings']['runtime_and_builtin_output_seconds'],
|
||||
both_exact_to_same_original_checkpoint=True))
|
||||
result = dict(status='PASS-UNCHANGED-R-PERSISTENT-PROCESS-REPLAY', complete=True,
|
||||
fixture_count=14, fresh_trial_count=14, resident_trial_count=28, actual_child_processes=len(children),
|
||||
all_bitwise_exact=True, children=children, matched_pairs=paired,
|
||||
fresh_children_whole_wall_seconds=sum(c['child_whole_wall_seconds'] for c in children[:-1]),
|
||||
resident_child_whole_wall_seconds=children[-1]['child_whole_wall_seconds'],
|
||||
wall_seconds=time.perf_counter() - started, original_files_verified_unchanged=True,
|
||||
source_runtime_unchanged=True, neural_state_fresh_every_call=True, GPU_graph_residency=False,
|
||||
original_experiment_resumed=False, generated_overlay_installed=False,
|
||||
scientific_learning_pass_claimed=False,
|
||||
timing_limit='Different lane counts (14 vs 28); use per-fixture pairs. First fresh includes cold extension build. No pure kernel speedup is claimed.',
|
||||
files={str(p.relative_to(output)): sha(p) for p in sorted(output.rglob('*')) if p.is_file()})
|
||||
save(output / 'summary.json', result)
|
||||
return result
|
||||
except BaseException:
|
||||
save(output / 'failure.json', dict(complete=False, traceback=traceback.format_exc(),
|
||||
wall_seconds=time.perf_counter() - started, original_experiment_resumed=False,
|
||||
automatic_retry=False, partial_outputs_retained=True))
|
||||
raise
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--fixtures', type=Path)
|
||||
parser.add_argument('--fixture-manifest-sha256')
|
||||
parser.add_argument('--output', type=Path)
|
||||
parser.add_argument('--worker-job', type=Path, help=argparse.SUPPRESS)
|
||||
parser.add_argument('--worker-job-sha256', help=argparse.SUPPRESS)
|
||||
args = parser.parse_args()
|
||||
if args.worker_job:
|
||||
require(args.worker_job_sha256 and not any((args.fixtures, args.fixture_manifest_sha256, args.output)),
|
||||
'Worker and parent arguments cannot be combined')
|
||||
result = run_worker(args.worker_job, args.worker_job_sha256)
|
||||
else:
|
||||
require(args.fixtures and args.fixture_manifest_sha256 and args.output
|
||||
and not args.worker_job_sha256, 'Require --fixtures --fixture-manifest-sha256 --output')
|
||||
result = run(args.fixtures, args.fixture_manifest_sha256, args.output)
|
||||
print(json.dumps(dict(complete=True, status=result.get('status', 'worker-returned'))), flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,194 @@
|
||||
"""Seal bounded engineering replay evidence; never resume scientific work."""
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import statistics
|
||||
import subprocess
|
||||
|
||||
ROOT = Path('/home/qishizhe/phase4ar-pipeline-acceleration-20261001')
|
||||
SOURCE = Path(__file__).absolute().parent
|
||||
WORKTREE = SOURCE.parents[2]
|
||||
|
||||
|
||||
def require(value, message):
|
||||
if not value:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def read(path):
|
||||
return json.loads(path.read_text())
|
||||
|
||||
|
||||
def sha(path):
|
||||
h = hashlib.sha256()
|
||||
with path.open('rb') as stream:
|
||||
for block in iter(lambda: stream.read(8 << 20), b''):
|
||||
h.update(block)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def save(path, value):
|
||||
with path.open('x') as stream:
|
||||
json.dump(value, stream, indent=2, sort_keys=True, allow_nan=False)
|
||||
stream.write('\n')
|
||||
|
||||
|
||||
def stats(values):
|
||||
return dict(count=len(values), median=statistics.median(values), mean=statistics.mean(values),
|
||||
minimum=min(values), maximum=max(values), total=sum(values))
|
||||
|
||||
|
||||
def successful_job(label):
|
||||
record = read(ROOT / 'jobs' / (label + '.exit.json'))
|
||||
require(record['observed_exit'] is True and record['exit_code'] == 0
|
||||
and not record.get('stop_reason') and not record['timed_out'], 'Job did not exit successfully: ' + label)
|
||||
return record
|
||||
|
||||
|
||||
def check_inventory(root, inventory):
|
||||
for rel, item in inventory.items():
|
||||
path = root / rel
|
||||
require(path.resolve().is_relative_to(root) and not path.is_symlink(), 'Unsafe artifact path')
|
||||
expected = item if isinstance(item, str) else item['sha256']
|
||||
require(sha(path) == expected, 'Artifact changed: ' + str(path))
|
||||
if isinstance(item, dict) and 'bytes' in item:
|
||||
require(path.stat().st_size == item['bytes'], 'Artifact size changed')
|
||||
|
||||
|
||||
def main():
|
||||
require(ROOT.is_dir() and not ROOT.is_symlink(), 'New experiment root required')
|
||||
require(not (ROOT / 'final-summary.json').exists(), 'Finalization must not overwrite prior results')
|
||||
jobs = {name: successful_job(name) for name in
|
||||
('cpu-unit-tests', 'brain-unit-tests', 'cpu-profile-01', 'brain-replay-01')}
|
||||
before, after = [read(ROOT / ('integrity-' + stage + '.json')) for stage in ('before', 'after')]
|
||||
require(before['status'] == after['status'] == 'PASS', 'Pre/post integrity failed')
|
||||
require(after['original']['status'] == 'PASS' and after['original']['files_checked'] == 64034
|
||||
and not after['original']['file_mismatches'] and not after['original']['source_mismatches'], 'Science integrity failed')
|
||||
cpu = read(ROOT / 'cpu-profile/report.json')
|
||||
brain = read(ROOT / 'brain-replay/summary.json')
|
||||
require(cpu['complete'] and cpu['fixtures'] == 14 and cpu['all_child_exits_observed_zero']
|
||||
and cpu['all_full_array_reference_comparisons_passed'] and cpu['all_original_receipts_exact']
|
||||
and cpu['full_AQ_validates_actual_second_pass_E_outputs'], 'CPU regression incomplete')
|
||||
require(brain['complete'] and brain['all_bitwise_exact'] and brain['fresh_trial_count'] == 14
|
||||
and brain['resident_trial_count'] == 28 and brain['actual_child_processes'] == 15, 'Brain regression incomplete')
|
||||
check_inventory(ROOT / 'cpu-profile', cpu['files'])
|
||||
check_inventory(ROOT / 'brain-replay', brain['files'])
|
||||
fresh = [read(ROOT / ('brain-replay/sessions/fresh-%02d.json' % i))['records'][0] for i in range(14)]
|
||||
resident = read(ROOT / 'brain-replay/sessions/resident.json')['records']
|
||||
for record in fresh + resident:
|
||||
require(record['exact'] and record['input_pins_verified_before_and_after']
|
||||
and record['neural_state_fresh_each_call'] and not record['generated_delta_installed'], 'Invalid replay trial')
|
||||
paired = []
|
||||
for first in fresh:
|
||||
others = [r for r in resident if r['fixture_id'] == first['fixture_id']]
|
||||
require(len(others) == 2 and {r['direction'] for r in others} == {'forward', 'reverse'}, 'Incomplete fixed ordering')
|
||||
fresh_runtime = first['timings']['runtime_and_builtin_output_seconds']
|
||||
warm_runtime = statistics.median(r['timings']['runtime_and_builtin_output_seconds'] for r in others)
|
||||
warm_wall = statistics.median(r['trial_wall_seconds'] for r in others)
|
||||
paired.append(dict(fixture_id=first['fixture_id'], fixed_index=first['fixed_index'],
|
||||
first_fixture_cold_build_and_context=first['fixed_index'] == 0,
|
||||
fresh_runtime_seconds=fresh_runtime, resident_runtime_seconds=warm_runtime,
|
||||
runtime_ratio=fresh_runtime / warm_runtime,
|
||||
fresh_trial_wall_seconds=first['trial_wall_seconds'], resident_trial_wall_seconds=warm_wall,
|
||||
trial_wall_ratio=first['trial_wall_seconds'] / warm_wall,
|
||||
fresh_simulation_seconds=first['timings']['original_diagnostic_simulation_seconds'],
|
||||
resident_simulation_seconds=statistics.median(r['timings']['original_diagnostic_simulation_seconds'] for r in others)))
|
||||
# Exclusion is by fixed initialization position, never by observed outcome.
|
||||
# All 42 trials remain in correctness evidence and the full paired table.
|
||||
steady = paired[1:]
|
||||
brain_timing = {name: stats([p[name] for p in steady]) for name in (
|
||||
'fresh_runtime_seconds', 'resident_runtime_seconds', 'runtime_ratio',
|
||||
'fresh_trial_wall_seconds', 'resident_trial_wall_seconds', 'trial_wall_ratio',
|
||||
'fresh_simulation_seconds', 'resident_simulation_seconds')}
|
||||
cold_E = cpu['full_E']['cold_fixed_first']
|
||||
warm_E = [r for r in cpu['full_E']['resident']
|
||||
if r['round_index'] == 1 and r['fixture_id'] == cold_E['fixture_id']]
|
||||
require(len(warm_E) == 1, 'Missing same-fixture E timing')
|
||||
e_pair = dict(fixture_id=cold_E['fixture_id'],
|
||||
cold_API_seconds=cold_E['original_api_seconds'], warm_API_seconds=warm_E[0]['original_api_seconds'],
|
||||
API_ratio=cold_E['original_api_seconds'] / warm_E[0]['original_api_seconds'],
|
||||
sample_warning='One fixed-first cold sample; not a 14-fixture matched cold E study')
|
||||
commit = subprocess.check_output(['git', '-C', str(WORKTREE), 'rev-parse', 'HEAD'], text=True).strip()
|
||||
git_status = subprocess.check_output(['git', '-C', str(WORKTREE), 'status', '--porcelain'], text=True)
|
||||
require(not git_status, 'Candidate worktree must be committed before finalization')
|
||||
result = dict(status='PASS-PERSISTENT-REPLAY-EQUIVALENCE', created_utc=datetime.now(timezone.utc).isoformat(),
|
||||
source_commit=commit, registration_sha256=cpu['registration_sha256'],
|
||||
original_source_commit=cpu['original_source_commit'], fixture_manifest_sha256=cpu['fixture_manifest_sha256'],
|
||||
jobs=jobs, cpu_summary=cpu['summary'], full_E_same_fixture_API_comparison=e_pair,
|
||||
brain_matched_pairs=paired, brain_steady_13_fixture_summary=brain_timing,
|
||||
first_brain_fixture=paired[0],
|
||||
full_brain_regression=dict(fresh=14, resident_forward=14, resident_reverse=14,
|
||||
arrays_per_trial=10, all_bitwise_exact=True, actual_child_exits_observed_zero=15),
|
||||
cpu_regression=dict(cold_U=14, resident_update_plus_independent_verification=42,
|
||||
full_E_cold=1, full_E_resident=28, full_AQ_on_new_E_outputs=14, host_tests=17),
|
||||
integrity=after, scientific_AR_resumed=False, training_epochs_added=0, probes_added=0,
|
||||
production_runtime_promoted=False, scientific_learning_success_claimed=False,
|
||||
limitations=[
|
||||
'Fixed 14 real committed-prefix fixtures only; not the full scientific design.',
|
||||
'Fresh means fresh interpreter, not flushed filesystem caches.',
|
||||
'Brain uses unchanged original 4090 runtime; whole-brain V100 compatibility remains unestablished.',
|
||||
'Original GPU tensors/graph are still allocated and uploaded each trial; no numerical loop rewrite.',
|
||||
'Brain runtime timings include its original output I/O. Trial wall also includes extra audit checks.',
|
||||
'Resident trial audit additionally checks the current fresh reference, making trial-wall boundaries unequal.',
|
||||
'Paired steady timing excludes fixed fixture 0 cold initialization in both lanes; correctness excludes none.',
|
||||
'Independent measured stages are not a combined training pipeline; no end-to-end speedup or revised full-run ETA.',
|
||||
'Full independent AQ still uses a fresh subprocess and all original checks.',
|
||||
'The original stopped scientific run remains at 1033 CPU-verified epochs and 138 probes.',
|
||||
'Integrity covers saved Phase4AR files/sources and previous acceleration files; not a new Phase1-4AQ numerical regression.',
|
||||
'Expected timeout self-test intentionally exits nonzero; it is not a scientific-run failure.'
|
||||
])
|
||||
save(ROOT / 'final-summary.json', result)
|
||||
s = cpu['summary']
|
||||
b = brain_timing
|
||||
report = f'''# 常驻进程工程回放结果
|
||||
|
||||
状态:`PASS-PERSISTENT-REPLAY-EQUIVALENCE`。仅限这次固定回放,不代表学习成功或正式运行时升级。
|
||||
|
||||
## 实测
|
||||
|
||||
| 测量范围 | 新进程 | 常驻进程 | 说明 |
|
||||
|---|---:|---:|---|
|
||||
| 原始 CPU 更新 API | {s['cold_U_API_seconds']['median']:.4f} s | {s['resident_warm_U_API_seconds']['median']:.4f} s | 新进程首次 API 包含导入等开销 |
|
||||
| 完整更新 API,同一固定案例 | {e_pair['cold_API_seconds']:.4f} s | {e_pair['warm_API_seconds']:.4f} s | 仅一组冷启动对照 |
|
||||
| 全脑原始运行函数,13 组配对中位数 | {b['fresh_runtime_seconds']['median']:.4f} s | {b['resident_runtime_seconds']['median']:.4f} s | 含原有输出;排除固定首例的初始化 |
|
||||
|
||||
完整更新常驻 14 组中位耗时:{s['original_full_E_warm_roundtrip_seconds']['median']:.4f} s。
|
||||
完整独立验证仍需:{s['original_full_AQ_subprocess_wall_seconds']['median']:.4f} s(14 组中位数)。
|
||||
全脑运行函数同案例配对倍率中位数:{b['runtime_ratio']['median']:.3f}×,不是整轮训练加速倍率。
|
||||
|
||||
## 一致性与保护
|
||||
|
||||
- 17 项主机测试通过。
|
||||
- CPU:14 次冷启动更新、42 次独立双进程更新/重算、29 次完整更新、14 次完整独立验证通过。
|
||||
- 全脑:14 次新进程、正序 14 次与逆序 14 次常驻回放;所有脉冲、状态、延迟队列和请求等一致,10 个数组逐位相同。
|
||||
- 64,034 个原实验文件与 16 个注册源码重新校验通过;之前 659 个加速产物和 13 个源码保持不变。
|
||||
- 原 Phase4AR 仍停止于 1,033 轮 CPU 校验训练与 138 次 probe,没有新增训练或安装新权重。
|
||||
|
||||
## 边界与下一步
|
||||
|
||||
本次全脑测试使用原 RTX 4090 环境,没有证明全脑已能迁移到 V100。此前 V100 约 3.4 ms 的成绩仅属于 eligibility/update 模块。
|
||||
常驻进程复用的是解释器、模块和 CUDA 上下文;每轮神经状态仍由原始函数重新分配。
|
||||
当前仍保留完整验证、图和权重上传、记录写盘。下一步应在新的可审计流水线中验证整轮开销,不能把本报告的独立阶段相加当作实测训练速度。
|
||||
|
||||
源码提交:`{commit}`。完整逐例耗时、实际进程退出、来源校验见 `final-summary.json` 和各 lane 报告。
|
||||
'''
|
||||
with (ROOT / 'RESULTS.md').open('x') as stream:
|
||||
stream.write(report)
|
||||
files = {str(path.relative_to(ROOT)): dict(bytes=path.stat().st_size, sha256=sha(path))
|
||||
for path in sorted(ROOT.rglob('*')) if path.is_file()}
|
||||
source_files = {path.name: sha(path) for path in sorted(SOURCE.iterdir()) if path.is_file()}
|
||||
manifest = dict(schema='conditioning-persistent-replay-artifacts-v1', source_commit=commit,
|
||||
root=str(ROOT), files=files, source_files=source_files,
|
||||
self_hash_policy='This manifest excludes itself and SHA256SUMS; SHA256SUMS includes the manifest.')
|
||||
save(ROOT / 'artifact-manifest.json', manifest)
|
||||
with (ROOT / 'SHA256SUMS').open('x') as stream:
|
||||
for rel, item in files.items():
|
||||
stream.write(item['sha256'] + ' ' + rel + '\n')
|
||||
stream.write(sha(ROOT / 'artifact-manifest.json') + ' artifact-manifest.json\n')
|
||||
print(json.dumps(dict(status=result['status'], files=len(files), source_commit=commit,
|
||||
total_bytes=sum(v['bytes'] for v in files.values()), brain=brain_timing, CPU=cpu['summary']), indent=2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Verify previous independent engineering artifacts and original saved science."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
BASE = Path('/home/qishizhe/phase4ar-pipeline-acceleration-20261001')
|
||||
OLD = Path('/home/qishizhe/phase4ar-v100-acceleration-20261001')
|
||||
OLD_SOURCE = Path(__file__).resolve().parent.parent / 'conditioning-acceleration-v1'
|
||||
OLD_MANIFEST_SHA = '6efdec34c96cdc79f786b91bd7a99b0e8ef64d0c4dcfa525646c82659a77d44f'
|
||||
FIXTURE_SHA = '481df128d39bf28e5984a6f2e5757f83d45cb7a6136f8d2843ecc0a67eca437b'
|
||||
|
||||
def sha(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as f:
|
||||
for b in iter(lambda:f.read(8 << 20), b''): h.update(b)
|
||||
return h.hexdigest()
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('--stage', choices=('before','after'), required=True)
|
||||
a = p.parse_args()
|
||||
BASE.mkdir(exist_ok=True)
|
||||
assert not BASE.is_symlink()
|
||||
report_path = BASE / ('integrity-' + a.stage + '.json')
|
||||
assert not report_path.exists()
|
||||
start = time.perf_counter()
|
||||
assert sha(OLD / 'artifact-manifest.json') == OLD_MANIFEST_SHA
|
||||
assert sha(OLD / 'fixtures/manifest.json') == FIXTURE_SHA
|
||||
manifest = json.loads((OLD / 'artifact-manifest.json').read_text())
|
||||
bad = []
|
||||
for rel, item in manifest['files'].items():
|
||||
path = OLD / rel
|
||||
assert path.resolve().is_relative_to(OLD) and not path.is_symlink()
|
||||
if not path.is_file() or path.stat().st_size != item['bytes'] or sha(path) != item['sha256']: bad.append(rel)
|
||||
for name, expected in manifest['source_files'].items():
|
||||
if sha(OLD_SOURCE / name) != expected: bad.append('source:' + name)
|
||||
assert not bad, bad
|
||||
science = BASE / ('original-integrity-' + a.stage + '.json')
|
||||
result = subprocess.run([sys.executable, '-B', str(OLD_SOURCE / 'audit_integrity.py'), '--output', str(science)],
|
||||
capture_output=True, text=True, timeout=120)
|
||||
assert result.returncode == 0, result.stdout + result.stderr
|
||||
records = json.loads(science.read_text())
|
||||
report = dict(status='PASS', previous_engineering_files_checked=len(manifest['files']),
|
||||
previous_engineering_sources_checked=len(manifest['source_files']), original=records,
|
||||
previous_manifest_sha256=OLD_MANIFEST_SHA, fixture_manifest_sha256=FIXTURE_SHA,
|
||||
old_artifacts_modified=False, original_AR_resumed=False, wall_seconds=time.perf_counter()-start)
|
||||
with report_path.open('x') as f: json.dump(report, f, indent=2)
|
||||
print(json.dumps(report), flush=True)
|
||||
@@ -0,0 +1,770 @@
|
||||
"""Read-only profiling of the fixed 14 Phase 4AR update fixtures.
|
||||
|
||||
The original Python -B environment and unchanged original U/AM/J sources are
|
||||
mandatory. No brain is run, training is resumed, or computed weight installed.
|
||||
Outputs are exclusive files under one fresh directory outside frozen inputs.
|
||||
|
||||
Unprofiled lanes measure fresh U processes, two separate resident CPU
|
||||
processes (U producer and original U.verify_receipt verifier), and fresh full AQ
|
||||
validators. A further lane calls unchanged full E in fresh and resident CPU
|
||||
processes, retaining all its original checks. The resident verifier does NOT replace AQ checkpoint/graph/source
|
||||
validation. Production checks must not be removed on the basis of this replay.
|
||||
Separate cProfile runs are diagnostic and excluded from timing comparisons.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import cProfile
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path, PurePosixPath
|
||||
import pstats
|
||||
import queue
|
||||
import statistics
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
ROOT = Path('/data/digital-drosophila')
|
||||
MODEL = ROOT / 'models/male-cns-lif'
|
||||
ENV = MODEL / '.venv'
|
||||
EXP = ROOT / 'experiments/phase4ar-normal-conditioning'
|
||||
REG_SHA = 'b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740'
|
||||
COMMIT = '80aeb2093db655329774eff7b32fb6e417b8b40b'
|
||||
SOURCE_SHA = dict(
|
||||
conditioning_update_source='96efff678cff910654eb08e86f1a17789e4e5589e340345f419c7027a7d547e2',
|
||||
eligibility_bridge_source='174fb8d14619189e74b095e77a6db18b14c93046dc431c0b55710a5aa2dd2e61',
|
||||
phase4j_source='abb4574da85f00bd9ef61024c65993ef81d42651ff8d8d63c15dd69c6222471e')
|
||||
E_PATH = MODEL / 'olfactory-conditioning-lab-v1/conditioning_epoch.py'
|
||||
E_SHA = '757935a4815d9f625640df685184ed3fe44a8845323562796da7aa43cbb194e1'
|
||||
INPUTS = ('step', 'neuron_idx', 'kc', 'candidate_edge_id', 'candidate_sources',
|
||||
'candidate_targets', 'candidate_compartments', 'delta_before', 'base_candidate')
|
||||
OUTPUTS = ('delta_after', 'sampled_trace', 'final_trace')
|
||||
REPEATS = 3
|
||||
SCHEMA = 'conditioning-pipeline-original-profile-v1'
|
||||
CHILDREN = []
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
if not condition:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
||||
|
||||
|
||||
def payload_sha(value):
|
||||
return hashlib.sha256(canonical(value).encode()).hexdigest()
|
||||
|
||||
|
||||
def unlinked(value):
|
||||
path = Path(value)
|
||||
require(path.is_absolute() and '..' not in path.parts, 'Explicit absolute path required')
|
||||
require(not any(p.is_symlink() or (hasattr(p, 'is_junction') and p.is_junction())
|
||||
for p in (path, *path.parents)), 'Linked path forbidden: ' + str(path))
|
||||
return path
|
||||
|
||||
|
||||
def digest(path):
|
||||
result = hashlib.sha256()
|
||||
with unlinked(path).open('rb') as stream:
|
||||
for data in iter(lambda: stream.read(8 << 20), b''):
|
||||
result.update(data)
|
||||
return result.hexdigest()
|
||||
|
||||
|
||||
def identity(path):
|
||||
path = unlinked(path)
|
||||
require(path.is_file(), 'Missing regular file: ' + str(path))
|
||||
size = path.stat().st_size
|
||||
result = dict(sha256=digest(path), bytes=size)
|
||||
require(size == path.stat().st_size, 'File size changed during read')
|
||||
return result
|
||||
|
||||
|
||||
def check(path, pin):
|
||||
observed = identity(path)
|
||||
sha = pin if isinstance(pin, str) else pin['sha256']
|
||||
require(observed['sha256'] == sha, 'File SHA differs: ' + str(path))
|
||||
if isinstance(pin, dict) and 'bytes' in pin:
|
||||
require(observed['bytes'] == pin['bytes'], 'File size differs: ' + str(path))
|
||||
return observed
|
||||
|
||||
|
||||
def read(path):
|
||||
def pairs(items):
|
||||
result = {}
|
||||
for key, value in items:
|
||||
require(key not in result, 'Duplicate JSON key')
|
||||
result[key] = value
|
||||
return result
|
||||
return json.loads(unlinked(path).read_text(encoding='utf-8'), object_pairs_hook=pairs,
|
||||
parse_constant=lambda _: (_ for _ in ()).throw(ValueError('Nonfinite JSON')))
|
||||
|
||||
|
||||
def save(path, value):
|
||||
with unlinked(path).open('x', encoding='utf-8', newline='\n') as stream:
|
||||
json.dump(value, stream, sort_keys=True, indent=2, ensure_ascii=False, allow_nan=False)
|
||||
stream.write('\n')
|
||||
|
||||
|
||||
def contained(root, name):
|
||||
require(type(name) is str and '\\' not in name, 'Invalid relative fixture path')
|
||||
relative = PurePosixPath(name)
|
||||
require(not relative.is_absolute() and str(relative) == name and '..' not in relative.parts
|
||||
and all(':' not in part for part in relative.parts), 'Escaping fixture path')
|
||||
result = unlinked(root / name)
|
||||
require(result.is_relative_to(root), 'Fixture path escaped root')
|
||||
return result
|
||||
|
||||
|
||||
def evidence(array):
|
||||
return dict(dtype=array.dtype.str, shape=list(array.shape), nbytes=int(array.nbytes),
|
||||
raw_c_order_sha256=hashlib.sha256(array.tobytes(order='C')).hexdigest())
|
||||
|
||||
|
||||
def same(left, right):
|
||||
return left.dtype == right.dtype and left.shape == right.shape and left.tobytes() == right.tobytes()
|
||||
|
||||
|
||||
def cpu_start():
|
||||
require(sys.dont_write_bytecode and 'torch' not in sys.modules and 'runtime_light' not in sys.modules,
|
||||
'Fresh Python -B CPU process required')
|
||||
require(Path(sys.prefix) == ENV, 'Use the unchanged original registered .venv')
|
||||
os.environ['CUDA_VISIBLE_DEVICES'] = ''
|
||||
os.environ['PYTHONDONTWRITEBYTECODE'] = '1'
|
||||
|
||||
|
||||
def load_source(name, path, sha):
|
||||
raw = unlinked(path).read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest() == sha and name not in sys.modules, 'Source/module identity differs')
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[name] = module
|
||||
exec(compile(raw, str(path), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def read_manifest(fixtures, expected):
|
||||
path = fixtures / 'manifest.json'
|
||||
check(path, expected)
|
||||
manifest = read(path)
|
||||
require(manifest['schema'] == 'conditioning-acceleration-fixtures-v1' and manifest['complete'] is True
|
||||
and manifest['registration_sha256'] == REG_SHA and manifest['source_code_commit'] == COMMIT
|
||||
and manifest['fixture_count'] == len(manifest['fixtures']) == 14,
|
||||
'Exact sealed fourteen-fixture authority required')
|
||||
require(len({f['fixture_id'] for f in manifest['fixtures']}) == 14, 'Duplicate fixture identity')
|
||||
require(manifest['selection_sha256'] == manifest['files']['selection.json']['sha256'], 'Selection authority differs')
|
||||
return manifest
|
||||
|
||||
|
||||
def verify_suite(fixtures, expected):
|
||||
manifest = read_manifest(fixtures, expected)
|
||||
for relative, pin in manifest['files'].items():
|
||||
check(contained(fixtures, relative), pin)
|
||||
registration = EXP / 'protocol/preregistered.json'
|
||||
check(registration, REG_SHA)
|
||||
reg = read(registration)
|
||||
require(reg['source_code_commit'] == COMMIT, 'Registered scientific source commit differs')
|
||||
original_pins = {str(registration): REG_SHA, **reg['source_sha256']}
|
||||
for entry in manifest['fixtures']:
|
||||
directory = contained(fixtures, entry['fixture_id'])
|
||||
for path, pin in read(directory / 'source-file-pins.json').items():
|
||||
prior = original_pins.get(path)
|
||||
require(prior is None or (prior if isinstance(prior, str) else prior['sha256']) == pin['sha256'],
|
||||
'Conflicting immutable input pin')
|
||||
original_pins[path] = pin
|
||||
require(entry['exact_stored_delta_and_trace_verified'] is True
|
||||
and entry['full_canonical_KC_count'] == 4064 and entry['full_candidate_edge_count'] == 14232
|
||||
and entry['original_validator_verified_full_graph_mapping'] is True, 'Unvalidated fixture identity')
|
||||
for path, pin in original_pins.items():
|
||||
check(path, pin)
|
||||
validator = MODEL / 'conditioning-execution-v1/validate_update_cpu.py'
|
||||
original_pins[str(validator)] = check(validator, reg['input_sha256'][str(validator)])
|
||||
require(reg['input_sha256'][str(E_PATH)] == E_SHA, 'Registered E source pin differs')
|
||||
original_pins[str(E_PATH)] = check(E_PATH, E_SHA)
|
||||
return manifest, original_pins
|
||||
|
||||
|
||||
def fixture_inputs(fixtures, manifest, entry):
|
||||
"""Each child independently reads/checks/owns its input and reference arrays."""
|
||||
import numpy as np
|
||||
directory = contained(fixtures, entry['fixture_id'])
|
||||
required = (entry['npz'], entry['command'], entry['fixture_id'] + '/reference-sources.json',
|
||||
entry['fixture_id'] + '/stored-update-receipt.json')
|
||||
for relative in required:
|
||||
check(contained(fixtures, relative), manifest['files'][relative])
|
||||
require(manifest['files'][entry['npz']]['sha256'] == entry['npz_sha256']
|
||||
and manifest['files'][entry['command']]['sha256'] == entry['command_sha256'], 'Fixture entry/file pins differ')
|
||||
with np.load(contained(fixtures, entry['npz']), allow_pickle=False) as archive:
|
||||
arrays = {name: archive[name].copy() for name in archive.files}
|
||||
inputs = {name: arrays[name] for name in INPUTS}
|
||||
require({name: evidence(array) for name, array in inputs.items()} == entry['input_arrays'],
|
||||
'Loaded fixture full input bytes differ')
|
||||
for name, pin in entry['output_arrays'].items():
|
||||
require(evidence(arrays[name]) == pin, 'Loaded fixture reference bytes differ: ' + name)
|
||||
require(len(inputs['kc']) == 4064 and len(inputs['candidate_edge_id']) == 14232,
|
||||
'Incomplete original canonical array identity')
|
||||
command = read(contained(fixtures, entry['command']))
|
||||
require(command['trace_backend'] == 'torch', 'Original Torch CPU backend required')
|
||||
sources = read(directory / 'reference-sources.json')
|
||||
require(set(sources) == set(SOURCE_SHA), 'Unexpected original source roles')
|
||||
for role, pin in sources.items():
|
||||
require(pin['sha256'] == SOURCE_SHA[role], 'Frozen source SHA differs')
|
||||
check(pin['path'], pin['sha256'])
|
||||
kwargs = dict(inputs, **command, bridge_source=sources['eligibility_bridge_source']['path'],
|
||||
phase4j_source=sources['phase4j_source']['path'])
|
||||
receipt = read(directory / 'stored-update-receipt.json')
|
||||
require(receipt['payload_sha256'] == entry['original_update_payload_sha256'], 'Stored receipt identity differs')
|
||||
for name in OUTPUTS:
|
||||
require(evidence(arrays['reference_' + name]) == receipt['outputs'][name], 'Receipt/reference byte evidence differs')
|
||||
require(same(arrays['reference_delta_after'], arrays['stored_delta_after']), 'Stored delta differs from CPU reference')
|
||||
for array in arrays.values():
|
||||
array.setflags(write=False)
|
||||
return dict(inputs=inputs, arrays=arrays, kwargs=kwargs, sources=sources, receipt=receipt, command=command)
|
||||
|
||||
|
||||
def original_locations(fixtures, entry):
|
||||
directory = contained(fixtures, entry['fixture_id'])
|
||||
authority = read(directory / 'authority.json')
|
||||
pins = read(directory / 'source-file-pins.json')
|
||||
authority_paths = [path for path, pin in pins.items()
|
||||
if path.endswith('.authority.json') and pin['sha256'] == entry['authority_sha256']]
|
||||
require(len(authority_paths) == 1, 'Original authority location is ambiguous')
|
||||
authority_path = authority_paths[0]
|
||||
check(authority_path, entry['authority_sha256'])
|
||||
require(read(authority_path) == authority, 'Copied/original authority differs')
|
||||
task_key = Path(authority_path).name[:-len('.authority.json')]
|
||||
update_dir = EXP / 'updates' / task_key
|
||||
chain_path = update_dir / 'chain-receipt.json'
|
||||
chain_sha = pins[str(chain_path)]['sha256']
|
||||
return authority_path, authority, update_dir, chain_sha
|
||||
|
||||
|
||||
def assert_epoch_output(directory, chain, fixture, entry):
|
||||
import numpy as np
|
||||
require(chain['complete'] is True and chain['coordinator_source_sha256'] == E_SHA
|
||||
and chain['authority_sha256'] == entry['authority_sha256']
|
||||
and chain['weights_installed'] is False and chain['brain_executed'] is False
|
||||
and chain['input_and_checkpoint_bytes_reverified'] is True
|
||||
and chain['candidate_endpoints_equal_graph'] is True
|
||||
and chain['KC_equals_supplied_canonical_membership'] is True,
|
||||
'Original full E validation chain incomplete')
|
||||
receipt = read(directory / 'update-receipt.json')
|
||||
require(canonical(receipt) == canonical(fixture['receipt']), 'Full original E receipt differs from sealed CPU reference')
|
||||
with np.load(directory / 'delta-after.npz', allow_pickle=False) as archive:
|
||||
require(set(archive.files) == {'edge_id', 'plastic_delta_mv'}, 'Full E overlay NPZ schema differs')
|
||||
require(same(archive['edge_id'], fixture['inputs']['candidate_edge_id'])
|
||||
and same(archive['plastic_delta_mv'], fixture['arrays']['reference_delta_after']),
|
||||
'Full original E candidate/delta bytes differ')
|
||||
for name in OUTPUTS:
|
||||
require(receipt['outputs'][name] == evidence(fixture['arrays']['reference_' + name]),
|
||||
'Full E trace/delta receipt does not bind full reference bytes')
|
||||
for filename, sha in chain['output_files_sha256'].items():
|
||||
check(directory / filename, sha)
|
||||
return receipt
|
||||
|
||||
|
||||
def assert_update(result, fixture):
|
||||
for name in OUTPUTS:
|
||||
require(same(getattr(result, name), fixture['arrays']['reference_' + name]), 'Full array mismatch: ' + name)
|
||||
require(canonical(result.receipt) == canonical(fixture['receipt']), 'Original complete receipt mismatch')
|
||||
require({name: evidence(value) for name, value in fixture['inputs'].items()} == result.receipt['input_arrays'],
|
||||
'Resident input bytes changed')
|
||||
snapshots = fixture['arrays']['reference_snapshots']
|
||||
if fixture['command']['us_tick'] is None:
|
||||
require(snapshots.shape == (0, 4064) and not result.sampled_trace.view('uint32').any(),
|
||||
'No-US snapshot/+0 rule differs')
|
||||
else:
|
||||
require(snapshots.shape == (1, 4064) and same(snapshots[0], result.sampled_trace),
|
||||
'After-current-tick sampled snapshot differs')
|
||||
|
||||
|
||||
def pack_array(array):
|
||||
return dict(dtype=array.dtype.str, shape=list(array.shape),
|
||||
data_base64=base64.b64encode(array.tobytes(order='C')).decode('ascii'))
|
||||
|
||||
|
||||
def compare_packet(packet, reference):
|
||||
require(packet['dtype'] == reference.dtype.str and packet['shape'] == list(reference.shape),
|
||||
'Producer packet array identity differs')
|
||||
raw = base64.b64decode(packet['data_base64'], validate=True)
|
||||
require(raw == reference.tobytes(order='C'), 'Producer full array bytes differ from independent reference')
|
||||
|
||||
|
||||
def verify_response(value, previous, sequence, role):
|
||||
require(value['role'] == role and value['sequence'] == sequence
|
||||
and value['previous_response_sha256'] == previous and value['complete'] is True,
|
||||
'Worker response chain/role differs')
|
||||
expected = payload_sha({key: item for key, item in value.items() if key != 'response_sha256'})
|
||||
require(expected == value['response_sha256'], 'Worker response payload hash differs')
|
||||
return expected
|
||||
|
||||
|
||||
def profile_category(filename, name):
|
||||
"""Exclusive SELF-time categories; cumulative function rows stay separate."""
|
||||
if 'importlib' in filename or name in ('_imp.create_dynamic', '_imp.exec_dynamic'):
|
||||
return 'module_import'
|
||||
if '::trace-expression-only' in filename or any("'" + op + "'" in name for op in ('mul_', 'add_', 'clamp_max_', 'zero_')):
|
||||
return 'trace_expression_and_tensor_ops'
|
||||
if filename.endswith('/ast.py') or filename.endswith('\\ast.py') or name in ('_load_original', '_load_bridge') or 'builtins.compile' in name:
|
||||
return 'source_parse_compile_load'
|
||||
if name in ('trace_from_events', 'apply_eligibility', 'apply_v2'):
|
||||
return 'trace_apply_python_self'
|
||||
if any(token in name for token in ('read_bytes', 'readinto', 'readall', 'HASH', 'openssl_sha256', '_pinned_bytes', '_evidence')):
|
||||
return 'file_reads_and_hashing'
|
||||
return 'other_validation_arrays_and_runtime'
|
||||
|
||||
|
||||
def profile_rows(profiler):
|
||||
rows, categories = [], {}
|
||||
for (filename, line, name), (primitive, calls, own, cumulative, _) in pstats.Stats(profiler).stats.items():
|
||||
category = profile_category(filename, name)
|
||||
categories[category] = categories.get(category, 0.) + own
|
||||
rows.append(dict(file=filename, line=line, function=name, primitive_calls=primitive, calls=calls,
|
||||
self_seconds=own, cumulative_seconds=cumulative, category=category))
|
||||
return dict(self_time_categories_seconds=categories,
|
||||
functions=sorted(rows, key=lambda row: row['cumulative_seconds'], reverse=True),
|
||||
interpretation='diagnostic Python cProfile overhead included; self categories are exclusive, cumulative rows overlap; not standalone pure-math latency')
|
||||
|
||||
|
||||
def worker(fixtures, expected, role, worker_output_root=None):
|
||||
cpu_start()
|
||||
started = time.perf_counter()
|
||||
manifest = read_manifest(fixtures, expected)
|
||||
entries = {entry['fixture_id']: entry for entry in manifest['fixtures']}
|
||||
t = time.perf_counter()
|
||||
import numpy as np
|
||||
numpy_seconds = time.perf_counter() - t
|
||||
first = contained(fixtures, manifest['fixtures'][0]['fixture_id'])
|
||||
check(first / 'reference-sources.json', manifest['files'][manifest['fixtures'][0]['fixture_id'] + '/reference-sources.json'])
|
||||
sources = read(first / 'reference-sources.json')
|
||||
source = sources['conditioning_update_source']
|
||||
require(source['sha256'] == SOURCE_SHA['conditioning_update_source'], 'Original U source differs')
|
||||
t = time.perf_counter()
|
||||
update = load_source('_pipeline_original_U_' + role, source['path'], source['sha256'])
|
||||
source_seconds = time.perf_counter() - t
|
||||
epoch = None
|
||||
epoch_import_seconds = 0.
|
||||
if role == 'epoch':
|
||||
require(worker_output_root is not None and unlinked(worker_output_root).is_dir(), 'Explicit existing full E output root required')
|
||||
t = time.perf_counter()
|
||||
epoch = load_source('_pipeline_original_E', E_PATH, E_SHA)
|
||||
epoch_import_seconds = time.perf_counter() - t
|
||||
print(canonical(dict(event='ready', role=role, pid=os.getpid(), fixture_manifest_sha256=expected,
|
||||
setup_seconds=time.perf_counter() - started, numpy_import_seconds=numpy_seconds,
|
||||
original_U_source_import_seconds=source_seconds, torch_loaded='torch' in sys.modules,
|
||||
original_E_source_import_seconds=epoch_import_seconds,
|
||||
CUDA_VISIBLE_DEVICES='', source_pins=sources)), flush=True)
|
||||
cache, previous, sequence = {}, None, 0
|
||||
producer_previous, producer_sequence, producer_pid = None, 0, None
|
||||
for line in sys.stdin:
|
||||
request = json.loads(line)
|
||||
if request.get('action') == 'stop':
|
||||
break
|
||||
require(request.get('action') in ('run', 'profile'), 'Unknown request action')
|
||||
require(role != 'verifier' or request['action'] == 'run', 'Verifier profiling is not an authorized lane')
|
||||
request_started = time.perf_counter()
|
||||
entry = entries[request['fixture_id']]
|
||||
t = time.perf_counter()
|
||||
cached = request['fixture_id'] in cache
|
||||
if not cached:
|
||||
cache[request['fixture_id']] = fixture_inputs(fixtures, manifest, entry)
|
||||
fixture = cache[request['fixture_id']]
|
||||
load_seconds = time.perf_counter() - t
|
||||
require(fixture['sources'] == sources, 'Fixture source closure differs from resident original module')
|
||||
verify_seconds = 0.
|
||||
packets = None
|
||||
receipt = fixture['receipt']
|
||||
diagnostic = None
|
||||
epoch_output = None
|
||||
if role == 'epoch':
|
||||
require(request['action'] == 'run', 'Full E profiling uses unprofiled original API only')
|
||||
epoch_output = unlinked(request['epoch_output'])
|
||||
require(epoch_output.parent == worker_output_root and not epoch_output.exists(), 'Full E output must be a fresh direct child')
|
||||
authority_path, _, _, _ = original_locations(fixtures, entry)
|
||||
t = time.perf_counter()
|
||||
chain = epoch.postprocess_epoch(authority_path, entry['authority_sha256'], epoch_output)
|
||||
api_seconds = time.perf_counter() - t
|
||||
t = time.perf_counter()
|
||||
receipt = assert_epoch_output(epoch_output, chain, fixture, entry)
|
||||
verify_seconds = time.perf_counter() - t
|
||||
elif role == 'verifier':
|
||||
produced = request['producer_response']
|
||||
producer_sequence += 1
|
||||
producer_previous = verify_response(produced, producer_previous, producer_sequence, 'producer')
|
||||
require(produced['fixture_id'] == request['fixture_id'] and produced['request_id'] == request['request_id'],
|
||||
'Producer/verifier task pairing differs')
|
||||
if producer_pid is None:
|
||||
producer_pid = produced['pid']
|
||||
require(produced['pid'] == producer_pid and producer_pid != os.getpid(), 'Verifier must be a distinct stable OS process')
|
||||
t = time.perf_counter()
|
||||
require(canonical(produced['receipt']) == canonical(receipt), 'Producer receipt differs from sealed CPU reference')
|
||||
for name in OUTPUTS:
|
||||
compare_packet(produced['arrays'][name], fixture['arrays']['reference_' + name])
|
||||
packet_seconds = time.perf_counter() - t
|
||||
t = time.perf_counter()
|
||||
require(update.verify_receipt(produced['receipt'], **fixture['kwargs']) is True, 'Original U receipt verification failed')
|
||||
api_seconds = time.perf_counter() - t
|
||||
verify_seconds = packet_seconds
|
||||
else:
|
||||
profiler = cProfile.Profile() if request['action'] == 'profile' else None
|
||||
t = time.perf_counter()
|
||||
if profiler:
|
||||
profiler.enable()
|
||||
try:
|
||||
result = update.update_epoch(**fixture['kwargs'])
|
||||
finally:
|
||||
if profiler:
|
||||
profiler.disable()
|
||||
api_seconds = time.perf_counter() - t
|
||||
t = time.perf_counter()
|
||||
assert_update(result, fixture)
|
||||
packets = {name: pack_array(getattr(result, name)) for name in OUTPUTS}
|
||||
verify_seconds = time.perf_counter() - t
|
||||
receipt = result.receipt
|
||||
if profiler:
|
||||
diagnostic = profile_rows(profiler)
|
||||
import torch
|
||||
require(not torch.cuda.is_initialized() and os.environ['CUDA_VISIBLE_DEVICES'] == '', 'CPU worker initialized CUDA')
|
||||
require({name: evidence(array) for name, array in fixture['inputs'].items()} == entry['input_arrays'],
|
||||
'Resident inputs differ after call')
|
||||
sequence += 1
|
||||
response = dict(schema=SCHEMA + '-response', complete=True, role=role, pid=os.getpid(), sequence=sequence,
|
||||
previous_response_sha256=previous, request_id=request['request_id'], fixture_id=request['fixture_id'],
|
||||
cached_inputs=cached, input_load_verify_seconds=load_seconds, original_api_seconds=api_seconds,
|
||||
reference_checks_and_packet_seconds=verify_seconds, worker_request_seconds=time.perf_counter() - request_started,
|
||||
full_array_reference_exact=True, original_receipt_exact=True, input_bytes_unchanged=True,
|
||||
cuda_initialized=False, receipt=receipt, arrays=packets, cprofile=diagnostic,
|
||||
epoch_output=None if epoch_output is None else str(epoch_output),
|
||||
independently_verified_producer_response_sha256=producer_previous if role == 'verifier' else None,
|
||||
versions=dict(python=sys.version, numpy=np.__version__, torch=torch.__version__),
|
||||
verification_scope=('unchanged full E.postprocess_epoch including all original source/graph/checkpoint checks; exact delta bytes and full receipt trace hashes'
|
||||
if role == 'epoch' else 'independent original U.verify_receipt recomputation plus exact full producer-array/reference comparison; NOT full AQ graph/checkpoint validation'
|
||||
if role == 'verifier' else 'unchanged original U.update_epoch; all output array bytes equal sealed CPU reference'))
|
||||
response['response_sha256'] = payload_sha(response)
|
||||
previous = response['response_sha256']
|
||||
print(canonical(response), flush=True)
|
||||
for fixture in cache.values():
|
||||
for source in fixture['sources'].values():
|
||||
check(source['path'], source['sha256'])
|
||||
check(fixtures / 'manifest.json', expected)
|
||||
|
||||
|
||||
class Child:
|
||||
def __init__(self, output, name, fixtures, expected, role, worker_output_root=None):
|
||||
self.name, self.output, self.role = name, output, role
|
||||
self.previous, self.sequence, self.closed = None, 0, False
|
||||
self.started = time.perf_counter()
|
||||
self.stderr = (output / (name + '.stderr.log')).open('xb')
|
||||
self.responses = (output / (name + '.responses.jsonl')).open('x', encoding='utf-8', newline='\n')
|
||||
self.argv = [sys.executable, '-B', str(Path(__file__).absolute()), '--fixtures', str(fixtures),
|
||||
'--fixture-manifest-sha256', expected, '--worker', role]
|
||||
if worker_output_root is not None:
|
||||
self.argv += ['--worker-output-root', str(worker_output_root)]
|
||||
self.process = subprocess.Popen(self.argv, cwd=output, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
stderr=self.stderr, text=True, encoding='utf-8', bufsize=1,
|
||||
env=dict(os.environ, CUDA_VISIBLE_DEVICES='', PYTHONDONTWRITEBYTECODE='1'))
|
||||
CHILDREN.append(self)
|
||||
self.lines = queue.Queue()
|
||||
def pump():
|
||||
try:
|
||||
for line in self.process.stdout:
|
||||
self.lines.put(line)
|
||||
finally:
|
||||
self.lines.put(None)
|
||||
self.reader = threading.Thread(target=pump, daemon=True)
|
||||
self.reader.start()
|
||||
self.ready = self._read()
|
||||
require(self.ready['event'] == 'ready' and self.ready['role'] == role
|
||||
and self.ready['pid'] == self.process.pid and self.ready['fixture_manifest_sha256'] == expected
|
||||
and self.ready['torch_loaded'] is False, 'Fresh CPU worker startup differs')
|
||||
self.startup_wall = time.perf_counter() - self.started
|
||||
|
||||
def _read(self):
|
||||
try:
|
||||
line = self.lines.get(timeout=120)
|
||||
except queue.Empty as error:
|
||||
raise TimeoutError(self.name + ' response exceeded 120 seconds') from error
|
||||
require(bool(line), self.name + ' exited without a complete response; inspect stderr')
|
||||
self.responses.write(line)
|
||||
self.responses.flush()
|
||||
return json.loads(line)
|
||||
|
||||
def request(self, value):
|
||||
started = time.perf_counter()
|
||||
self.process.stdin.write(canonical(value) + '\n')
|
||||
self.process.stdin.flush()
|
||||
response = self._read()
|
||||
wall = time.perf_counter() - started
|
||||
self.sequence += 1
|
||||
self.previous = verify_response(response, self.previous, self.sequence, self.role)
|
||||
require(response['pid'] == self.process.pid and response['fixture_id'] == value['fixture_id']
|
||||
and response['request_id'] == value['request_id'], 'Worker response pairing differs')
|
||||
return response, wall
|
||||
|
||||
def close(self):
|
||||
if self.closed:
|
||||
return self.receipt
|
||||
self.process.stdin.write(canonical(dict(action='stop')) + '\n')
|
||||
self.process.stdin.flush()
|
||||
self.process.stdin.close()
|
||||
code = self.process.wait(timeout=30)
|
||||
self.reader.join(timeout=2)
|
||||
self.process.stdout.close()
|
||||
self.stderr.close()
|
||||
self.responses.close()
|
||||
self.receipt = dict(argv=self.argv, pid=self.process.pid, exit_code=code,
|
||||
actual_exit_observed=True, startup_wall_seconds=self.startup_wall,
|
||||
process_wall_seconds=time.perf_counter() - self.started, ready=self.ready,
|
||||
responses=self.sequence, final_response_sha256=self.previous,
|
||||
stdout_sha256=digest(self.output / (self.name + '.responses.jsonl')),
|
||||
stderr_sha256=digest(self.output / (self.name + '.stderr.log')))
|
||||
save(self.output / (self.name + '-process.json'), self.receipt)
|
||||
self.closed = True
|
||||
require(code == 0, self.name + ' failed; output retained')
|
||||
return self.receipt
|
||||
|
||||
def abort(self):
|
||||
"""Only this exact spawned child is stopped; partial evidence is retained."""
|
||||
if self.closed:
|
||||
return
|
||||
terminate_sent = False
|
||||
kill_sent = False
|
||||
if self.process.poll() is None:
|
||||
self.process.terminate()
|
||||
terminate_sent = True
|
||||
try:
|
||||
code = self.process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
self.process.kill()
|
||||
kill_sent = True
|
||||
code = self.process.wait(timeout=30)
|
||||
self.reader.join(timeout=2)
|
||||
for stream in (self.process.stdin, self.process.stdout, self.stderr, self.responses):
|
||||
if stream is not None and not stream.closed:
|
||||
stream.close()
|
||||
save(self.output / (self.name + '-abort-process.json'), dict(argv=self.argv, pid=self.process.pid,
|
||||
actual_exit_observed=True, exit_code=code, terminate_sent=terminate_sent, kill_sent=kill_sent,
|
||||
partial_evidence_retained=True, automatic_retry=False))
|
||||
self.closed = True
|
||||
|
||||
|
||||
def cleanup_children():
|
||||
errors = []
|
||||
for child in reversed(CHILDREN):
|
||||
try:
|
||||
child.abort()
|
||||
except Exception as error:
|
||||
errors.append(type(error).__name__ + ': ' + str(error))
|
||||
require(not errors, 'Child cleanup errors: ' + '; '.join(errors))
|
||||
|
||||
|
||||
def compact_response(response, wall):
|
||||
return {**{key: value for key, value in response.items() if key not in ('arrays', 'receipt', 'cprofile')},
|
||||
'original_receipt_payload_sha256': response['receipt']['payload_sha256'],
|
||||
'parent_roundtrip_seconds': wall}
|
||||
|
||||
|
||||
def distribution(values):
|
||||
require(bool(values), 'Empty timing distribution')
|
||||
return dict(count=len(values), minimum=min(values), median=statistics.median(values),
|
||||
maximum=max(values), sum=sum(values), mean=statistics.mean(values))
|
||||
|
||||
|
||||
def full_validation(fixtures, entry, output, reg, produced_update_dir):
|
||||
directory = contained(fixtures, entry['fixture_id'])
|
||||
authority_path, _, historical_update_dir, _ = original_locations(fixtures, entry)
|
||||
update_dir = unlinked(produced_update_dir)
|
||||
require(update_dir.is_dir() and update_dir != historical_update_dir
|
||||
and not update_dir.is_relative_to(EXP), 'Full AQ must validate newly produced E artifacts outside AR')
|
||||
filenames = ('chain-receipt.json', 'update-receipt.json', 'delta-after.npz', 'overlay-manifest.json')
|
||||
require(set(path.name for path in update_dir.iterdir()) == set(filenames), 'New E output inventory differs')
|
||||
update_hashes = {name: digest(update_dir / name) for name in filenames}
|
||||
chain_sha = update_hashes['chain-receipt.json']
|
||||
validator = MODEL / 'conditioning-execution-v1/validate_update_cpu.py'
|
||||
check(validator, reg['input_sha256'][str(validator)])
|
||||
receipt_path = output / (entry['fixture_id'] + '.validation.json')
|
||||
argv = [sys.executable, '-B', str(validator), '--authority', authority_path,
|
||||
'--authority-sha256', entry['authority_sha256'], '--update-dir', str(update_dir),
|
||||
'--chain-sha256', chain_sha, '--receipt', str(receipt_path)]
|
||||
started = time.perf_counter()
|
||||
with (output / (entry['fixture_id'] + '.stdout.log')).open('xb') as stdout, \
|
||||
(output / (entry['fixture_id'] + '.stderr.log')).open('xb') as stderr:
|
||||
process = subprocess.run(argv, cwd=output, stdout=stdout, stderr=stderr,
|
||||
env=dict(os.environ, CUDA_VISIBLE_DEVICES='', PYTHONDONTWRITEBYTECODE='1'), timeout=120, check=False)
|
||||
wall = time.perf_counter() - started
|
||||
record = dict(fixture_id=entry['fixture_id'], argv=argv, exit_code=process.returncode,
|
||||
actual_exit_observed=True, subprocess_wall_seconds=wall,
|
||||
validated_update_dir=str(update_dir), validated_new_E_artifact=True,
|
||||
update_files_sha256=update_hashes)
|
||||
save(output / (entry['fixture_id'] + '.process.json'), record)
|
||||
require(process.returncode == 0, 'Original AQ validation failed; outputs retained')
|
||||
expected = read(directory / 'fresh-cpu-validation.json')
|
||||
# E's new NPZ/container hashes may differ while its scientific array bytes
|
||||
# match. Only these independently observed output-file bindings may vary.
|
||||
expected.update(update_files_sha256=update_hashes,
|
||||
after_overlay_sha256=update_hashes['delta-after.npz'],
|
||||
after_manifest_sha256=update_hashes['overlay-manifest.json'])
|
||||
require(read(receipt_path) == expected,
|
||||
'Fresh full AQ receipt differs from original scientific/source fields and new E file bindings')
|
||||
require(update_hashes == {name: digest(update_dir / name) for name in filenames}, 'New E artifacts changed during full AQ validation')
|
||||
record['full_original_AQ_receipt_exact_to_expected_binding'] = True
|
||||
record['receipt_sha256'] = digest(receipt_path)
|
||||
return record
|
||||
|
||||
|
||||
def profile(fixtures, expected, output, repeats):
|
||||
cpu_start()
|
||||
require(repeats == REPEATS, 'This fixed engineering experiment requires exactly three resident passes')
|
||||
started = time.perf_counter()
|
||||
fixtures, output = unlinked(fixtures), unlinked(output)
|
||||
own = identity(Path(__file__).absolute())
|
||||
manifest, original_pins = verify_suite(fixtures, expected)
|
||||
protected = {fixtures, EXP, MODEL, *[Path(path).parent for path in original_pins]}
|
||||
require(not output.exists() and output.parent.is_dir()
|
||||
and not any(output.is_relative_to(parent) for parent in protected),
|
||||
'Output must be a fresh independent directory with an existing parent')
|
||||
output.mkdir()
|
||||
save(output / 'experiment.json', dict(schema=SCHEMA, fixture_manifest_sha256=expected,
|
||||
fixture_order=[entry['fixture_id'] for entry in manifest['fixtures']], repeats=repeats,
|
||||
selection='all previously sealed 14 fixtures, fixed existing manifest order, no outcome selection',
|
||||
original_source_commit=COMMIT, registration_sha256=REG_SHA,
|
||||
source_pins=original_pins, implementation_source=dict(path=str(Path(__file__).absolute()), **own),
|
||||
scope='read-only fixed-input engineering replay; no installation, brain, training or learning claim',
|
||||
resident_verifier_scope='original U.verify_receipt only; cannot substitute for original AQ full graph/checkpoint validator'))
|
||||
cold_dir, resident_dir, aq_dir, diagnostic_dir, epoch_dir = [output / name for name in ('cold', 'resident', 'full-aq', 'diagnostic', 'full-E')]
|
||||
for directory in (cold_dir, resident_dir, aq_dir, diagnostic_dir, epoch_dir):
|
||||
directory.mkdir()
|
||||
cold = []
|
||||
for entry in manifest['fixtures']:
|
||||
child = Child(cold_dir, entry['fixture_id'], fixtures, expected, 'producer')
|
||||
response, wall = child.request(dict(action='run', request_id='cold/' + entry['fixture_id'], fixture_id=entry['fixture_id']))
|
||||
exit_receipt = child.close()
|
||||
cold.append(dict(compact_response(response, wall), process=exit_receipt))
|
||||
print(canonical(dict(lane='cold-original-U', fixture_id=entry['fixture_id'], complete=True)), flush=True)
|
||||
producer = Child(resident_dir, 'producer', fixtures, expected, 'producer')
|
||||
verifier = Child(resident_dir, 'verifier', fixtures, expected, 'verifier')
|
||||
require(producer.process.pid != verifier.process.pid, 'Independent verifier process required')
|
||||
resident = []
|
||||
for round_index in range(repeats):
|
||||
for entry in manifest['fixtures']:
|
||||
request = dict(action='run', request_id=f'round-{round_index:02d}/' + entry['fixture_id'], fixture_id=entry['fixture_id'])
|
||||
pair_started = time.perf_counter()
|
||||
produced, producer_wall = producer.request(request)
|
||||
verified, verifier_wall = verifier.request(dict(request, producer_response=produced))
|
||||
require(verified['independently_verified_producer_response_sha256'] == produced['response_sha256'],
|
||||
'Independent verifier receipt chain mismatch')
|
||||
resident.append(dict(round_index=round_index, fixture_id=entry['fixture_id'],
|
||||
producer=compact_response(produced, producer_wall), verifier=compact_response(verified, verifier_wall),
|
||||
pair_parent_wall_seconds=time.perf_counter() - pair_started))
|
||||
print(canonical(dict(lane='resident-separate-original-U-and-verifier', round_index=round_index, complete=True)), flush=True)
|
||||
producer_exit, verifier_exit = producer.close(), verifier.close()
|
||||
epoch_artifacts = epoch_dir / 'new-updates'
|
||||
epoch_artifacts.mkdir()
|
||||
first = manifest['fixtures'][0]
|
||||
epoch_cold_worker = Child(epoch_dir, 'cold-first', fixtures, expected, 'epoch', epoch_artifacts)
|
||||
epoch_cold_response, epoch_cold_wall = epoch_cold_worker.request(dict(action='run', request_id='full-E-cold/' + first['fixture_id'],
|
||||
fixture_id=first['fixture_id'], epoch_output=str(epoch_artifacts / ('cold-' + first['fixture_id']))))
|
||||
epoch_cold_exit = epoch_cold_worker.close()
|
||||
epoch_cold = dict(compact_response(epoch_cold_response, epoch_cold_wall), process=epoch_cold_exit)
|
||||
print(canonical(dict(lane='fresh-full-original-E', fixture_id=first['fixture_id'], complete=True)), flush=True)
|
||||
epoch_worker = Child(epoch_dir, 'resident', fixtures, expected, 'epoch', epoch_artifacts)
|
||||
epoch_resident = []
|
||||
for round_index in range(2):
|
||||
for entry in manifest['fixtures']:
|
||||
response, wall = epoch_worker.request(dict(action='run', request_id=f'full-E-{round_index:02d}/' + entry['fixture_id'],
|
||||
fixture_id=entry['fixture_id'], epoch_output=str(epoch_artifacts / f'round-{round_index:02d}-{entry["fixture_id"]}')))
|
||||
epoch_resident.append(dict(round_index=round_index, **compact_response(response, wall)))
|
||||
print(canonical(dict(lane='resident-full-original-E', round_index=round_index,
|
||||
fixture_id=entry['fixture_id'], complete=True)), flush=True)
|
||||
epoch_exit = epoch_worker.close()
|
||||
full = []
|
||||
reg = read(EXP / 'protocol/preregistered.json')
|
||||
for entry in manifest['fixtures']:
|
||||
full.append(full_validation(fixtures, entry, aq_dir, reg,
|
||||
epoch_artifacts / f'round-01-{entry["fixture_id"]}'))
|
||||
print(canonical(dict(lane='full-original-AQ', fixture_id=entry['fixture_id'], complete=True)), flush=True)
|
||||
# Independent diagnostics: first call includes cold Torch import; another
|
||||
# full fixed pass has warm imports. These calls never enter speed medians.
|
||||
diagnostic = Child(diagnostic_dir, 'profiler', fixtures, expected, 'producer')
|
||||
diagnostics = []
|
||||
first = manifest['fixtures'][0]
|
||||
schedule = [('cold-fixed-first', first), *[('warm-fixed-all', entry) for entry in manifest['fixtures']]]
|
||||
for index, (temperature, entry) in enumerate(schedule):
|
||||
response, wall = diagnostic.request(dict(action='profile', request_id=f'profile-{index:02d}/' + entry['fixture_id'],
|
||||
fixture_id=entry['fixture_id']))
|
||||
record = dict(temperature=temperature, **compact_response(response, wall), cprofile=response['cprofile'])
|
||||
save(diagnostic_dir / f'{index:02d}-{entry["fixture_id"]}.json', record)
|
||||
diagnostics.append(dict(temperature=temperature, fixture_id=entry['fixture_id'],
|
||||
profile_file=f'diagnostic/{index:02d}-{entry["fixture_id"]}.json',
|
||||
self_time_categories_seconds=response['cprofile']['self_time_categories_seconds']))
|
||||
diagnostic_exit = diagnostic.close()
|
||||
warm = [row for row in resident if row['round_index'] > 0]
|
||||
summary = dict(
|
||||
cold_U_subprocess_wall_seconds=distribution([row['process']['process_wall_seconds'] for row in cold]),
|
||||
cold_U_API_seconds=distribution([row['original_api_seconds'] for row in cold]),
|
||||
cold_worker_startup_wall_seconds=distribution([row['process']['startup_wall_seconds'] for row in cold]),
|
||||
cold_input_load_verify_seconds=distribution([row['input_load_verify_seconds'] for row in cold]),
|
||||
resident_warm_U_API_seconds=distribution([row['producer']['original_api_seconds'] for row in warm]),
|
||||
resident_warm_verify_API_seconds=distribution([row['verifier']['original_api_seconds'] for row in warm]),
|
||||
resident_warm_pair_roundtrip_seconds=distribution([row['pair_parent_wall_seconds'] for row in warm]),
|
||||
original_full_E_warm_API_seconds=distribution([row['original_api_seconds'] for row in epoch_resident if row['round_index'] == 1]),
|
||||
original_full_E_warm_roundtrip_seconds=distribution([row['parent_roundtrip_seconds'] for row in epoch_resident if row['round_index'] == 1]),
|
||||
original_full_E_cold_first_API_seconds=epoch_cold['original_api_seconds'],
|
||||
original_full_E_cold_first_process_wall_seconds=epoch_cold['process']['process_wall_seconds'],
|
||||
original_full_AQ_subprocess_wall_seconds=distribution([row['subprocess_wall_seconds'] for row in full]))
|
||||
for path, pin in original_pins.items():
|
||||
check(path, pin)
|
||||
verify_suite(fixtures, expected)
|
||||
check(Path(__file__).absolute(), own)
|
||||
report = dict(schema=SCHEMA, complete=True, created_utc=datetime.now(timezone.utc).isoformat(),
|
||||
registration_sha256=REG_SHA, original_source_commit=COMMIT, fixture_manifest_sha256=expected,
|
||||
fixtures=14, resident_passes=repeats, warm_passes_in_summary=[1, 2], cold=cold, resident=resident,
|
||||
full_E=dict(cold_fixed_first=epoch_cold, resident=epoch_resident, resident_passes=2,
|
||||
historical_process_seconds={entry['fixture_id']: entry['historical_process_seconds']['update'] for entry in manifest['fixtures']}),
|
||||
full_AQ=full, diagnostic=diagnostics, process_exits=dict(producer=producer_exit, verifier=verifier_exit,
|
||||
profiler=diagnostic_exit, full_E_resident=epoch_exit, full_E_cold_first=epoch_cold_exit),
|
||||
summary=summary, total_wall_seconds=time.perf_counter() - started,
|
||||
limitations=['Fixed inputs replayed; no dependency is advanced and no produced weight is installed.',
|
||||
'Resident original U verification omits full AQ checkpoint/graph hashing and cannot replace that validation in production.',
|
||||
'cProfile is diagnostic only, with overhead; its cumulative function times overlap.',
|
||||
'Full E resident retains every original validation check; stage times are not a measured complete brain/E/AQ pipeline.',
|
||||
'Cold denotes a fresh Python process, not a flushed operating-system page cache.',
|
||||
'CPU workload conditions are observed by the caller; these lanes execute serially.'],
|
||||
original_files_modified=False, brain_executed=False, training_executed=False, weights_installed=False,
|
||||
all_full_array_reference_comparisons_passed=True, all_original_receipts_exact=True,
|
||||
independent_resident_verifier_process=True, all_child_exits_observed_zero=True,
|
||||
full_AQ_validates_actual_second_pass_E_outputs=True,
|
||||
files={str(path.relative_to(output)): identity(path) for path in sorted(output.rglob('*')) if path.is_file()})
|
||||
save(output / 'report.json', report)
|
||||
print(canonical(dict(complete=True, report=str(output / 'report.json'), summary=summary)), flush=True)
|
||||
return report
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--fixtures', type=Path, required=True)
|
||||
parser.add_argument('--fixture-manifest-sha256', required=True)
|
||||
parser.add_argument('--output', type=Path)
|
||||
parser.add_argument('--repeats', type=int, choices=(REPEATS,), default=REPEATS)
|
||||
parser.add_argument('--worker', choices=('producer', 'verifier', 'epoch'), help=argparse.SUPPRESS)
|
||||
parser.add_argument('--worker-output-root', type=Path, help=argparse.SUPPRESS)
|
||||
args = parser.parse_args()
|
||||
if args.worker:
|
||||
require(args.output is None, 'Worker writes only its parent-controlled protocol streams')
|
||||
worker(unlinked(args.fixtures), args.fixture_manifest_sha256, args.worker,
|
||||
None if args.worker_output_root is None else unlinked(args.worker_output_root))
|
||||
else:
|
||||
require(args.output is not None, '--output is required')
|
||||
try:
|
||||
profile(args.fixtures, args.fixture_manifest_sha256, args.output, args.repeats)
|
||||
finally:
|
||||
cleanup_children()
|
||||
@@ -0,0 +1,80 @@
|
||||
"""New pipeline experiment process receipts, with exclusive output and no retries."""
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
ROOT = Path('/home/qishizhe/phase4ar-pipeline-acceleration-20261001')
|
||||
|
||||
def output_bytes():
|
||||
total = 0
|
||||
for f in ROOT.rglob('*'):
|
||||
try:
|
||||
if f.is_file() and not f.is_symlink(): total += f.stat().st_size
|
||||
except FileNotFoundError:
|
||||
pass # Concurrent compiler temporary file removal, not a payload.
|
||||
return total
|
||||
|
||||
def stop_group(proc):
|
||||
try: os.killpg(proc.pid, signal.SIGTERM)
|
||||
except ProcessLookupError: pass
|
||||
try: proc.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired: pass
|
||||
try: os.killpg(proc.pid, signal.SIGKILL)
|
||||
except ProcessLookupError: pass
|
||||
return proc.wait()
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('--label', required=True)
|
||||
p.add_argument('--timeout', type=int, default=900)
|
||||
p.add_argument('command', nargs=argparse.REMAINDER)
|
||||
a = p.parse_args()
|
||||
assert re.fullmatch(r'[a-z0-9-]+', a.label) and a.command and 0 < a.timeout <= 900
|
||||
assert ROOT.is_dir() and not ROOT.is_symlink()
|
||||
assert shutil.disk_usage(ROOT).free >= 100 * (1 << 30)
|
||||
out = ROOT / 'jobs'
|
||||
out.mkdir(exist_ok=True)
|
||||
start = time.perf_counter()
|
||||
record = dict(label=a.label, command=a.command, scope='independent engineering replay only',
|
||||
started_utc=datetime.now(timezone.utc).isoformat(), scientific_AR_resumed=False)
|
||||
with (out / (a.label + '.start.json')).open('x') as f: json.dump(record, f, indent=2)
|
||||
with (out / (a.label + '.stdout.log')).open('x') as stdout, (out / (a.label + '.stderr.log')).open('x') as stderr:
|
||||
proc = None
|
||||
try:
|
||||
# All children belong to a dedicated group created by THIS invocation.
|
||||
# On stop, terminate this group only, never unrelated services/science.
|
||||
proc = subprocess.Popen(a.command, stdout=stdout, stderr=stderr, start_new_session=True,
|
||||
env={**os.environ, 'PYTHONDONTWRITEBYTECODE':'1'})
|
||||
record.update(pid=proc.pid, process_group=proc.pid)
|
||||
stop_reason = None
|
||||
while True:
|
||||
try:
|
||||
proc.wait(timeout=5)
|
||||
break
|
||||
except subprocess.TimeoutExpired:
|
||||
if time.perf_counter() - start > a.timeout: stop_reason = 'wall_timeout'
|
||||
elif shutil.disk_usage(ROOT).free < 100 * (1 << 30): stop_reason = 'minimum_disk_reserve'
|
||||
elif output_bytes() > 2 * (1 << 30):
|
||||
stop_reason = 'output_cap'
|
||||
if stop_reason:
|
||||
break
|
||||
if not stop_reason and output_bytes() > 2 * (1 << 30): stop_reason = 'output_cap'
|
||||
if stop_reason or proc.returncode != 0: stop_group(proc)
|
||||
record.update(exit_code=proc.returncode, observed_exit=True,
|
||||
timed_out=stop_reason == 'wall_timeout', stop_reason=stop_reason)
|
||||
except OSError as error:
|
||||
rc = None if proc is None else stop_group(proc)
|
||||
record.update(exit_code=rc, observed_exit=proc is not None, timed_out=False, launch_error=str(error))
|
||||
except BaseException:
|
||||
if proc is not None: stop_group(proc)
|
||||
raise
|
||||
record.update(wall_seconds=time.perf_counter()-start, finished_utc=datetime.now(timezone.utc).isoformat())
|
||||
with (out / (a.label + '.exit.json')).open('x') as f: json.dump(record, f, indent=2)
|
||||
print(json.dumps(record), flush=True)
|
||||
raise SystemExit(record['exit_code'] if record['observed_exit'] and not record.get('stop_reason') else 124)
|
||||
@@ -0,0 +1,161 @@
|
||||
"""Host-only authority, exact-comparison, ordering and process receipt tests."""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import numpy as np
|
||||
|
||||
import brain_replay as replay
|
||||
|
||||
|
||||
class ReplayTests(unittest.TestCase):
|
||||
def test_fixed_forward_reverse_order(self):
|
||||
result = replay.fixture_order(14)
|
||||
self.assertEqual(len(result), 28)
|
||||
self.assertEqual(result[:14], [('forward', i) for i in range(14)])
|
||||
self.assertEqual(result[14:], [('reverse', i) for i in range(13, -1, -1)])
|
||||
for count in (0, 13, 15):
|
||||
with self.assertRaises(ValueError):
|
||||
replay.fixture_order(count)
|
||||
|
||||
def test_exact_comparison_detects_signed_zero_dtype_shape_and_bit_changes(self):
|
||||
expected = {'v': np.array([0., 1.], np.float64)}
|
||||
self.assertTrue(replay.compare_arrays(expected, expected, ('v',))['v']['bitwise_exact'])
|
||||
for array in (np.array([-0., 1.], np.float64), np.array([0., 1.], np.float32),
|
||||
np.array([[0., 1.]], np.float64),
|
||||
np.array([0., np.nextafter(1., 2.)], np.float64)):
|
||||
self.assertFalse(replay.compare_arrays({'v': array}, expected, ('v',))['v']['bitwise_exact'])
|
||||
with self.assertRaisesRegex(ValueError, 'schema'):
|
||||
replay.compare_arrays({}, expected, ('v',))
|
||||
|
||||
def test_checkpoint_comparison_includes_all_arrays_requests_and_environment(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
actual_dir, old_dir = root / 'actual', root / 'old'
|
||||
actual_dir.mkdir()
|
||||
old_dir.mkdir()
|
||||
for name in ('requests.csv', 'finite-audit.json', 'apl-pending-tail.float32.npy'):
|
||||
(actual_dir / name).write_bytes(b'fixed exact reference')
|
||||
(old_dir / name).write_bytes(b'fixed exact reference')
|
||||
def record():
|
||||
return dict(state={name: np.zeros(2, np.float64 if name in ('v', 'g') else np.int32)
|
||||
for name in replay.STATE_KEYS},
|
||||
terminal={'spike_ring': np.zeros((19, 2), np.uint8),
|
||||
'apl_state': np.zeros(2, np.float32),
|
||||
'apl_pending': np.zeros((18, 2), np.float32),
|
||||
'next_tick': np.asarray(1200, np.int64)},
|
||||
summary={**{key: 'same' for key in replay.SUMMARY_KEYS},
|
||||
'apl_component': {'environment': {'torch': 'fixed-original'}}},
|
||||
fresh=True, global_tick_offset=0)
|
||||
actual, original = record(), record()
|
||||
self.assertTrue(replay.compare_checkpoints(actual, original, actual_dir, old_dir)['exact'])
|
||||
actual['terminal']['spike_ring'][0, 1] = 1
|
||||
self.assertFalse(replay.compare_checkpoints(actual, original, actual_dir, old_dir)['exact'])
|
||||
actual = record()
|
||||
actual['summary']['apl_component']['environment']['torch'] = 'different'
|
||||
self.assertFalse(replay.compare_checkpoints(actual, original, actual_dir, old_dir)['exact'])
|
||||
actual = record()
|
||||
actual['summary']['effective_weights_raw_sha256'] = 'different'
|
||||
self.assertFalse(replay.compare_checkpoints(actual, original, actual_dir, old_dir)['exact'])
|
||||
actual = record()
|
||||
(actual_dir / 'requests.csv').write_bytes(b'different acceptance')
|
||||
self.assertFalse(replay.compare_checkpoints(actual, original, actual_dir, old_dir)['exact'])
|
||||
|
||||
def test_json_and_pin_authority_rejects_ambiguity_and_mutation(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
value = root / 'value.json'
|
||||
value.write_text('{"key":1,"key":2}', encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError, 'Duplicate'):
|
||||
replay.read(value)
|
||||
value.write_text('{"key":NaN}', encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError, 'Nonfinite'):
|
||||
replay.read(value)
|
||||
value.write_text('{"key":1}', encoding='utf-8')
|
||||
pins = {}
|
||||
replay.pin_add(pins, value, replay.sha(value))
|
||||
replay.verify(pins)
|
||||
with self.assertRaisesRegex(ValueError, 'Conflicting'):
|
||||
replay.pin_add(pins, value, 'f' * 64)
|
||||
value.write_text('{"key":2}', encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError, 'changed'):
|
||||
replay.verify(pins)
|
||||
with self.assertRaisesRegex(ValueError, 'leaves'):
|
||||
replay.contained(root, str(root.parent / 'outside'))
|
||||
|
||||
def test_loader_executes_only_verified_bytes_and_cannot_rebind_module(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
source = Path(directory) / 'source.py'
|
||||
source.write_text('value = 42\n', encoding='utf-8')
|
||||
name = '_brain_replay_host_test_unique_module'
|
||||
try:
|
||||
with self.assertRaisesRegex(ValueError, 'Unverified'):
|
||||
replay.load_source(name, source, '0' * 64)
|
||||
self.assertNotIn(name, sys.modules)
|
||||
module = replay.load_source(name, source, replay.sha(source))
|
||||
self.assertEqual(module.value, 42)
|
||||
with self.assertRaisesRegex(ValueError, 'repeated'):
|
||||
replay.load_source(name, source, replay.sha(source))
|
||||
finally:
|
||||
sys.modules.pop(name, None)
|
||||
|
||||
def test_parent_environment_is_original_only(self):
|
||||
with mock.patch.object(replay.sys, 'dont_write_bytecode', False):
|
||||
with self.assertRaisesRegex(ValueError, 'original registered'):
|
||||
replay.check_environment()
|
||||
|
||||
|
||||
class ProcessReceiptTests(unittest.TestCase):
|
||||
def paths(self, root):
|
||||
for name in ('jobs', 'processes'):
|
||||
(root / name).mkdir()
|
||||
report_path = root / 'report.json'
|
||||
replay.save(report_path, {'exact': True})
|
||||
result_path = root / 'result.json'
|
||||
replay.save(result_path, dict(complete=True, all_bitwise_exact=True, lane='fresh', count=1,
|
||||
records=[dict(report=str(report_path), sha256=replay.sha(report_path))]))
|
||||
return dict(lane='fresh', runs=[['fresh', 0]], result_file=str(result_path)), root / 'jobs/fresh.json', root / 'processes'
|
||||
|
||||
def test_child_receipt_requires_actual_return_and_keeps_outer_group(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
job, job_path, process_dir = self.paths(root)
|
||||
process = mock.Mock(pid=4321, returncode=0)
|
||||
process.wait.return_value = 0
|
||||
with mock.patch('brain_replay.subprocess.Popen', return_value=process) as popen:
|
||||
receipt, result = replay.launch(job, job_path, process_dir, replay.time.time() + 10)
|
||||
self.assertTrue(receipt['exit_independently_observed'])
|
||||
self.assertEqual(receipt['actual_returncode'], 0)
|
||||
self.assertEqual(receipt['child_pid'], 4321)
|
||||
self.assertNotIn('start_new_session', popen.call_args.kwargs)
|
||||
self.assertEqual(popen.call_args.kwargs['env']['CUDA_VISIBLE_DEVICES'], replay.GPU)
|
||||
self.assertEqual(popen.call_args.args[0][0], str(replay.ORIGINAL_PYTHON))
|
||||
self.assertEqual(replay.read(process_dir / 'fresh.json')['actual_returncode'], 0)
|
||||
self.assertTrue(result['all_bitwise_exact'])
|
||||
|
||||
def test_timeout_stops_child_retains_real_failure_receipt_and_never_retries(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
job, job_path, process_dir = self.paths(root)
|
||||
process = mock.Mock(pid=4321, returncode=-15)
|
||||
process.wait.side_effect = [subprocess.TimeoutExpired('mock child', 1), -15, -15]
|
||||
process.poll.return_value = None
|
||||
with mock.patch('brain_replay.subprocess.Popen', return_value=process) as popen:
|
||||
with self.assertRaisesRegex(ValueError, 'child failed'):
|
||||
replay.launch(job, job_path, process_dir, replay.time.time() + 10)
|
||||
self.assertEqual(popen.call_count, 1)
|
||||
process.terminate.assert_called_once()
|
||||
receipt = replay.read(process_dir / 'fresh.json')
|
||||
self.assertTrue(receipt['timed_out'])
|
||||
self.assertTrue(receipt['child_terminated_on_failure'])
|
||||
self.assertEqual(receipt['actual_returncode'], -15)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,100 @@
|
||||
"""Authority, full-byte IPC and cleanup tests without original production runs."""
|
||||
import base64
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
SCRIPT = Path(__file__).with_name('profile_original.py')
|
||||
SPEC = importlib.util.spec_from_file_location('test_original_profile_module', SCRIPT)
|
||||
P = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(P)
|
||||
|
||||
|
||||
class BoundaryTests(unittest.TestCase):
|
||||
def test_array_packet_uses_raw_signed_zero_bytes(self):
|
||||
reference = np.asarray([0., 1.], dtype=np.float32)
|
||||
P.compare_packet(P.pack_array(reference), reference)
|
||||
changed = np.asarray([-0., 1.], dtype=np.float32)
|
||||
with self.assertRaisesRegex(ValueError, 'full array bytes'):
|
||||
P.compare_packet(P.pack_array(changed), reference)
|
||||
|
||||
def test_packet_dtype_and_shape_are_not_repaired(self):
|
||||
reference = np.asarray([1.], dtype=np.float32)
|
||||
for array in (reference.astype(np.float64), reference.reshape(1, 1)):
|
||||
with self.assertRaisesRegex(ValueError, 'identity'):
|
||||
P.compare_packet(P.pack_array(array), reference)
|
||||
|
||||
def test_response_chain_binds_all_output_bytes_and_role(self):
|
||||
response = dict(role='producer', sequence=1, previous_response_sha256=None, complete=True,
|
||||
arrays={'delta_after': P.pack_array(np.zeros(3, np.float32))})
|
||||
response['response_sha256'] = P.payload_sha(response)
|
||||
self.assertEqual(P.verify_response(response, None, 1, 'producer'), response['response_sha256'])
|
||||
with self.assertRaisesRegex(ValueError, 'chain/role'):
|
||||
P.verify_response(response, None, 1, 'verifier')
|
||||
response['arrays']['delta_after']['data_base64'] = base64.b64encode(b'bad').decode()
|
||||
with self.assertRaisesRegex(ValueError, 'payload hash'):
|
||||
P.verify_response(response, None, 1, 'producer')
|
||||
|
||||
def test_response_chain_reordering_rejected(self):
|
||||
response = dict(role='producer', sequence=2, previous_response_sha256='a' * 64, complete=True)
|
||||
response['response_sha256'] = P.payload_sha(response)
|
||||
with self.assertRaisesRegex(ValueError, 'chain/role'):
|
||||
P.verify_response(response, 'b' * 64, 2, 'producer')
|
||||
|
||||
def test_manifest_paths_cannot_escape(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary).resolve()
|
||||
for name in ('../other', '/absolute', 'foo\\bar', 'x/../bar', 'C:/windows'):
|
||||
with self.assertRaises(ValueError):
|
||||
P.contained(root, name)
|
||||
self.assertEqual(P.contained(root, 'valid/input.npz'), root / 'valid/input.npz')
|
||||
|
||||
def test_output_writes_are_exclusive(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
path = Path(temporary).resolve() / 'result.json'
|
||||
P.save(path, {'complete': True})
|
||||
original = path.read_bytes()
|
||||
with self.assertRaises(FileExistsError):
|
||||
P.save(path, {'complete': False})
|
||||
self.assertEqual(path.read_bytes(), original)
|
||||
|
||||
def test_mismatching_source_pin_rejected(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
path = Path(temporary).resolve() / 'source.py'
|
||||
path.write_text('raise AssertionError("must not run")', encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError, 'identity'):
|
||||
P.load_source('untrusted_original_profile_test', path, '0' * 64)
|
||||
|
||||
def test_profile_categories_do_not_use_cumulative_totals(self):
|
||||
self.assertEqual(P.profile_category('/usr/lib/python3.10/ast.py', 'dump'), 'source_parse_compile_load')
|
||||
self.assertEqual(P.profile_category('/frozen/phase4j.py::trace-expression-only', '<module>'),
|
||||
'trace_expression_and_tensor_ops')
|
||||
self.assertEqual(P.profile_category('/frozen/bridge.py', 'trace_from_events'), 'trace_apply_python_self')
|
||||
|
||||
|
||||
class CleanupTests(unittest.TestCase):
|
||||
def test_cleanup_attempts_every_owned_child_after_failure(self):
|
||||
calls = []
|
||||
class Good:
|
||||
def abort(self):
|
||||
calls.append('good')
|
||||
class Bad:
|
||||
def abort(self):
|
||||
calls.append('bad')
|
||||
raise RuntimeError('simulated abort error')
|
||||
original = list(P.CHILDREN)
|
||||
try:
|
||||
P.CHILDREN[:] = [Good(), Bad()]
|
||||
with self.assertRaisesRegex(ValueError, 'cleanup errors'):
|
||||
P.cleanup_children()
|
||||
self.assertEqual(calls, ['bad', 'good'])
|
||||
finally:
|
||||
P.CHILDREN[:] = original
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Safety self-test only: a child/grandchild sleep tree to terminate by own group."""
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
child = subprocess.Popen([sys.executable, '-B', '-c', 'import time; time.sleep(90)'])
|
||||
print(child.pid, flush=True)
|
||||
time.sleep(90)
|
||||
@@ -0,0 +1,91 @@
|
||||
# Normal olfactory acquisition: independent D18 branch
|
||||
|
||||
This phase does not modify MaleCNS reference/runtime, Phase 1–4AQ data, the
|
||||
base graph, the 14,232 candidate edges, eligibility-v2, APL gain, cell thresholds,
|
||||
transmitter signs or any previously sealed failure. An engineering interface
|
||||
PASS is not evidence of learning.
|
||||
|
||||
## Fixed science
|
||||
|
||||
The original AO file (SHA-256
|
||||
`a7bda850ee87df4d9f647994e1a1a4074dfea5793184edb1822ab3d8c02e8216`)
|
||||
supplies master 20260930, all semantic seeds, ordered cues and control schedules.
|
||||
The old frozen evaluation policy supplies completed-epoch snapshot boundaries.
|
||||
There are 40 normal blocks: physiological/matched-energy × PAM15/PPL103 ×
|
||||
reciprocal reinforced odor × five training replicates. A is 4-ethylphenol, B is
|
||||
3-hexanone. Evaluation uses 80 independently registered input streams.
|
||||
|
||||
All seven arms are real: paired, D=0, frozen, random reward, unpaired, CS-only
|
||||
and DAN-only. 30,000 complete fresh training/control epochs and 3,920 real
|
||||
fresh A/B probes are required. Even identical baselines are executed, not
|
||||
relabelled copies. Snapshots 0/1/2/5/10/20/50 never authorize outcome selection.
|
||||
Only the 50-pairing terminal outcome determines acquisition. Every arm finishes
|
||||
its entire original schedule, including trailing neutral or blank epochs.
|
||||
|
||||
Epochs are 120 ms, CS is [0,100) ms, scheduled artificial US is at 90 ms.
|
||||
PAM15 and PPL103 use only their existing confirmed compartment-specific DAN
|
||||
identities. The positive/negative behavioral predictions are explicit model
|
||||
hypotheses, not a claim that every PAM/PPL neuron has that function. Scheduled
|
||||
D is an artificial dimensionless interface, not measured dopamine concentration
|
||||
or the number of accepted DAN spikes. US attempts/rejections and actual events
|
||||
remain in the original runtime artifacts. No resampling compensates for a
|
||||
rejected pulse.
|
||||
|
||||
Fresh neural state is reset each epoch; only the separately authenticated
|
||||
plastic delta carries forward. Original E/U compute the end-of-epoch update,
|
||||
then a separate CPU process recomputes it from sealed actual KC events. Probes
|
||||
have no US, no E/update and no feedback. Brain math is untouched.
|
||||
|
||||
## Readout and gates
|
||||
|
||||
The frozen AQ `learning_gates.py` and original `metrics.py` are pinned before
|
||||
sampling. All six controls, raw signed MBON balance, functional count/latency
|
||||
change, MBON separation and both downstream readouts remain mandatory. The
|
||||
same replicate must satisfy the conjunction; at least three of five pass in
|
||||
each of the eight cells. PAM/PPL or input modes are never pooled to rescue a
|
||||
failure. Original H mean-control rules are reported separately for each DAN
|
||||
control source, both required. Delta change alone cannot imply learning.
|
||||
|
||||
Readout populations are anatomical, never inferred from active/plastic subsets.
|
||||
The original H actual MBON downstream edge table defines legacyDownstream;
|
||||
nonMBONDownstream is its exact set difference with the full MBON population.
|
||||
Missing identity or an altered frozen source stops preparation.
|
||||
|
||||
## Execution, resources and integrity
|
||||
|
||||
Use only the registered 4090 UUID and serial execution. ComfyUI admission must
|
||||
be empty; never stop or evict a service. Source code is committed before
|
||||
registration. Static tables invoke the original L PN-rate transform, preserving
|
||||
all original PN columns for both modes. Shared CS aliases reuse saved input
|
||||
bytes only. The full 63-bit CUDA sampler, full matrix draw and CS window are
|
||||
unchanged; there is no CPU-RNG replacement.
|
||||
|
||||
The engineering ceiling is 256 GiB of new outputs, at least 100 GiB disk reserve,
|
||||
1,800 seconds per child and an absolute 21-day registration deadline. The AQ
|
||||
linear estimate is only planning arithmetic from limited warm measurements,
|
||||
not a measured forecast across all conditions. Exceeding a limit means an
|
||||
incomplete preserved experiment, not shortened trials or changed parameters.
|
||||
|
||||
Each child has an exclusive start record, actual parent-observed exit,
|
||||
dependency hashes and immutable output inventory. A stopped or uncommitted
|
||||
child is never silently retried. A persistent incremental ledger avoids
|
||||
rehashing every historical trial on every iteration; each invocation still
|
||||
rehashes its actual consumed dependencies. Full audits read every unique file
|
||||
and reject missing, extra, changed, linked or incomplete output. They are not
|
||||
claimed to be atomic filesystem snapshots. Mutable compiler cache is accounted
|
||||
separately. CPU/source tests are not described as GPU numerical regression.
|
||||
|
||||
A detached supervisor keeps the serial controller alive across SSH disconnects.
|
||||
Administrative logs live in `/data/digital-drosophila/logs/phase4ar-normal-conditioning/`,
|
||||
outside the immutable per-trial ledger. The final outer auditor must retain
|
||||
these logs and its actual exit receipt. A launch PID alone proves no completion.
|
||||
|
||||
All original event/state/queue/update artifacts are retained; no dense wholebrain
|
||||
time-by-neuron output is added. Complete historical sealed integrity is checked
|
||||
at the boundaries. The five historical reference trials are preserved evidence,
|
||||
not claimed as newly rerun here.
|
||||
|
||||
Normal acquisition is the only authorized scientific scope of this registration.
|
||||
No delayed/reversal/retention assay starts automatically, and no candidate is
|
||||
issued from normal acquisition alone. There is no game, action decoder, RL,
|
||||
visual input, training of base weights, web service or 3D interface.
|
||||
@@ -0,0 +1,442 @@
|
||||
"""Serial, immutable artifact accounting; not a process runner or science gate.
|
||||
|
||||
The long-lived parent hashes this cycle's declared inputs/outputs and the known
|
||||
ledger tail. It does NOT rehash all old artifacts per cycle. Reopening, inspect
|
||||
and final_verify perform full historical verification. Never infer a process's
|
||||
terminal state from a PID, missing file, elapsed time, or a live handle.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import contextmanager
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path, PurePosixPath
|
||||
import re
|
||||
import shutil
|
||||
import uuid
|
||||
|
||||
SCHEMA = 'normal-append-ledger-v1'
|
||||
CONTROL = '.append-ledger'
|
||||
REGISTRATION = 'protocol/preregistered.json'
|
||||
SHA = re.compile('[0-9a-f]{64}')
|
||||
ID = re.compile('[A-Za-z0-9][A-Za-z0-9_-]{0,127}')
|
||||
|
||||
|
||||
def require(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def raw_json(value):
|
||||
return (json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)+'\n').encode('utf-8')
|
||||
|
||||
|
||||
def read_json(path):
|
||||
def unique(items):
|
||||
result = {}
|
||||
for key, value in items:
|
||||
require(key not in result, 'Duplicate JSON key'); result[key] = value
|
||||
return result
|
||||
return json.loads(Path(path).read_bytes().decode('utf-8'), object_pairs_hook=unique,
|
||||
parse_constant=lambda _: (_ for _ in ()).throw(ValueError('Nonfinite JSON')))
|
||||
|
||||
|
||||
def digest(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as stream:
|
||||
for block in iter(lambda: stream.read(8 << 20), b''): h.update(block)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def relative_name(value):
|
||||
require(type(value) is str and bool(value) and '\\' not in value and '\x00' not in value and
|
||||
'\n' not in value and '\r' not in value, 'Invalid relative path')
|
||||
path = PurePosixPath(value)
|
||||
require(not path.is_absolute() and str(path) == value and
|
||||
all(p not in ('.', '..', '') and ':' not in p for p in path.parts), 'Escaping/noncanonical path')
|
||||
return value
|
||||
|
||||
|
||||
def unlinked(path):
|
||||
p = Path(path)
|
||||
require(p.is_absolute() and '..' not in p.parts, 'Absolute nonescaping path required')
|
||||
require(not any(q.is_symlink() or (hasattr(q, 'is_junction') and q.is_junction()) for q in (p, *p.parents)),
|
||||
'Linked path forbidden')
|
||||
return p
|
||||
|
||||
|
||||
def identity(path):
|
||||
p = unlinked(path)
|
||||
require(p.is_file(), 'Missing regular file: '+str(p))
|
||||
size = p.stat().st_size; sha = digest(p)
|
||||
require(p.stat().st_size == size, 'File changed while hashing')
|
||||
return dict(bytes=size, sha256=sha)
|
||||
|
||||
|
||||
def validate_identity(value):
|
||||
require(type(value) is dict and set(value) == {'bytes', 'sha256'} and type(value['bytes']) is int and
|
||||
value['bytes'] >= 0 and type(value['sha256']) is str and SHA.fullmatch(value['sha256']), 'Invalid SHA/byte identity')
|
||||
|
||||
|
||||
def _sync_directory(directory):
|
||||
# Windows has no portable directory fsync. File bytes are fsynced there.
|
||||
if os.name != 'nt':
|
||||
descriptor = os.open(directory, os.O_RDONLY)
|
||||
try: os.fsync(descriptor)
|
||||
finally: os.close(descriptor)
|
||||
|
||||
|
||||
def publish_exclusive(path, value):
|
||||
"""Atomic no-replace publication on filesystems supporting hard links.
|
||||
|
||||
No unsafe rename/replace fallback. An interrupted temporary is preserved;
|
||||
inspect/final audit rejects it. A failed destination collision also never
|
||||
deletes or replaces the pre-existing destination.
|
||||
"""
|
||||
path = unlinked(path); require(path.parent.is_dir(), 'Missing publication parent')
|
||||
require(not path.exists(), 'Immutable destination already exists; no retry')
|
||||
raw = raw_json(value); temporary = path.parent / ('.publishing-'+uuid.uuid4().hex)
|
||||
descriptor = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
||||
with os.fdopen(descriptor, 'wb') as stream:
|
||||
stream.write(raw); stream.flush(); os.fsync(stream.fileno())
|
||||
os.link(temporary, path) # Exclusive destination, same bytes/inode; never overwrite.
|
||||
_sync_directory(path.parent)
|
||||
require(path.read_bytes() == raw, 'Published bytes changed')
|
||||
temporary.unlink() # Only this function's exact, newly created temporary.
|
||||
_sync_directory(path.parent)
|
||||
return dict(bytes=len(raw), sha256=hashlib.sha256(raw).hexdigest())
|
||||
|
||||
|
||||
class Ledger:
|
||||
"""One long-lived instance per serial parent, never parallel scheduling.
|
||||
|
||||
Inventories map absolute or root-relative paths to {bytes, sha256}; initial
|
||||
inventory is root-relative and must contain the exact registration file.
|
||||
Call begin BEFORE spawn, then append only after the parent has observed
|
||||
actual exit 0 and saved its independent process receipt. Existing starts
|
||||
are never reissued. An interrupted append may be independently inspected,
|
||||
but automatic resume/rerun is not provided.
|
||||
"""
|
||||
def __init__(self, root, registration_sha, initial_inventory, max_output_bytes, reserve_bytes,
|
||||
shared_build_relative='extension-build'):
|
||||
self.root = unlinked(Path(root)).resolve(strict=True)
|
||||
require(self.root.is_dir(), 'Existing experiment root required')
|
||||
require(type(registration_sha) is str and SHA.fullmatch(registration_sha), 'External registration SHA required')
|
||||
require(type(max_output_bytes) is int and max_output_bytes > 0 and type(reserve_bytes) is int and reserve_bytes >= 0,
|
||||
'Explicit nonnegative reserve and positive output cap required')
|
||||
self.registration_sha = registration_sha; self.max_output_bytes = max_output_bytes; self.reserve_bytes = reserve_bytes
|
||||
self.build_name = relative_name(shared_build_relative)
|
||||
require(self.build_name != CONTROL and not self.build_name.startswith(CONTROL+'/'), 'Build overlaps ledger controls')
|
||||
self.control = self.root / CONTROL; self.header_path = self.control / 'header.json'
|
||||
self.starts = self.control / 'started'; self.entries = self.control / 'entries'
|
||||
require(type(initial_inventory) is dict and initial_inventory, 'Explicit initial inventory required')
|
||||
initial = {}
|
||||
for name, expected in initial_inventory.items():
|
||||
relative_name(name); self._payload_path(name); validate_identity(expected)
|
||||
require(identity(self.root/name) == expected, 'Initial file identity differs: '+name)
|
||||
initial[name] = dict(expected)
|
||||
require(initial.get(REGISTRATION, {}).get('sha256') == registration_sha, 'Initial registration binding missing')
|
||||
header = dict(schema=SCHEMA, root=str(self.root), registration_sha256=registration_sha,
|
||||
initial_inventory=initial, max_output_bytes=max_output_bytes, reserve_bytes=reserve_bytes,
|
||||
shared_mutable_build=self.build_name, initial_inventory_scope='caller supplied; entire tree checked only by final_verify',
|
||||
scientific_gate_claimed=False)
|
||||
if self.header_path.exists():
|
||||
require(read_json(self.header_path) == header, 'Existing ledger authority/options differ')
|
||||
else:
|
||||
require(not self.control.exists(), 'Partial ledger initialization; no automatic retry')
|
||||
self.control.mkdir(); self.starts.mkdir(); self.entries.mkdir()
|
||||
publish_exclusive(self.header_path, header)
|
||||
self.header_identity = identity(self.header_path); self.initial = initial
|
||||
self._tracked = dict(initial); self._controls = {CONTROL+'/header.json': self.header_identity}
|
||||
self._completed = []; self._completed_set = set(); self._pending = {}; self._tail = None
|
||||
self._immutable_bytes = sum(v['bytes'] for v in initial.values())
|
||||
self._control_bytes = self.header_identity['bytes']
|
||||
self._write_failed = False
|
||||
self._replay()
|
||||
self._budget()
|
||||
|
||||
def _payload_path(self, value):
|
||||
path = Path(value)
|
||||
if not path.is_absolute(): path = self.root / relative_name(str(value))
|
||||
path = unlinked(path)
|
||||
require(path.is_relative_to(self.root), 'Output escapes experiment')
|
||||
rel = path.relative_to(self.root).as_posix(); relative_name(rel)
|
||||
require(rel != CONTROL and not rel.startswith(CONTROL+'/') and rel != self.build_name and
|
||||
not rel.startswith(self.build_name+'/'), 'Immutable payload overlaps controls/shared build')
|
||||
return path, rel
|
||||
|
||||
def _rows(self, mapping, *, output, verified=None):
|
||||
require(type(mapping) is dict, 'Explicit inventory dictionary required')
|
||||
result = []; used = set()
|
||||
for text, expected in mapping.items():
|
||||
validate_identity(expected); p = Path(text)
|
||||
if output: p, rel = self._payload_path(text)
|
||||
else:
|
||||
if not p.is_absolute(): p = self.root / relative_name(str(text))
|
||||
p = unlinked(p); rel = p.relative_to(self.root).as_posix() if p.is_relative_to(self.root) else None
|
||||
p = p.resolve(strict=True)
|
||||
rel = p.relative_to(self.root).as_posix() if p.is_relative_to(self.root) else None
|
||||
require(str(p) not in used, 'Duplicate path aliases'); used.add(str(p))
|
||||
if not output and rel in self._tracked:
|
||||
require(expected == self._tracked[rel], 'Consumed immutable input differs from committed identity')
|
||||
observed = self._identity_once(p, verified)
|
||||
require(observed == expected, 'Actual file SHA/bytes differ: '+str(p))
|
||||
result.append(dict(path=str(p), relative_path=rel, **expected))
|
||||
return sorted(result, key=lambda row: row['path'])
|
||||
|
||||
@staticmethod
|
||||
def _identity_once(path, verified):
|
||||
"""One *invocation-local* actual SHA read per unique file, no stat cache."""
|
||||
if verified is None: return identity(path)
|
||||
key = str(path)
|
||||
if key not in verified: verified[key] = identity(path)
|
||||
return verified[key]
|
||||
|
||||
def _check_tail(self):
|
||||
require(not self._write_failed, 'Previous publication failed; independent inspection required, no automatic retry')
|
||||
require(identity(self.header_path) == self.header_identity, 'Ledger header changed')
|
||||
if self._completed:
|
||||
p = self.entries / f'{len(self._completed):016d}.json'
|
||||
require(identity(p)['sha256'] == self._tail, 'Known ledger tail changed')
|
||||
require(not (self.entries / f'{len(self._completed)+1:016d}.json').exists(), 'Unobserved appended entry; independently reopen/inspect')
|
||||
|
||||
@contextmanager
|
||||
def _writer(self):
|
||||
lock = self.control/'writer.lock'; token = uuid.uuid4().hex.encode()
|
||||
unlinked(lock)
|
||||
descriptor = os.open(lock, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
||||
try:
|
||||
with os.fdopen(descriptor, 'wb') as stream: stream.write(token); stream.flush(); os.fsync(stream.fileno())
|
||||
self._check_tail()
|
||||
yield
|
||||
finally:
|
||||
# Do not remove another actor's/stale lock or broadly delete a tree.
|
||||
if lock.is_file() and lock.read_bytes() == token: lock.unlink()
|
||||
|
||||
def _build_inventory(self):
|
||||
root = unlinked(self.root/self.build_name); result = {}
|
||||
if root.exists():
|
||||
require(root.is_dir(), 'Shared build must be a directory')
|
||||
for p in sorted(root.rglob('*')):
|
||||
unlinked(p)
|
||||
if p.is_file(): result[p.relative_to(self.root).as_posix()] = identity(p)
|
||||
else: require(p.is_dir(), 'Nonregular shared build file')
|
||||
return result
|
||||
|
||||
def _budget(self, *, outputs=(), extra_control=0):
|
||||
# O(new outputs), not O(all previous payload rows), for the serial path.
|
||||
added = {row['relative_path']:row['bytes'] for row in outputs}
|
||||
provisional = {}
|
||||
for attempt in self._pending.values():
|
||||
job = attempt['job']; rel = job['relative_path']
|
||||
if rel is not None and rel not in self._tracked and rel not in added: provisional[rel] = job['bytes']
|
||||
build = self._build_inventory()
|
||||
immutable = self._immutable_bytes+sum(added.values())
|
||||
control = self._control_bytes+extra_control
|
||||
build_bytes = sum(row['bytes'] for row in build.values())
|
||||
total = immutable+control+build_bytes+sum(provisional.values())
|
||||
require(total <= self.max_output_bytes, 'Tracked outputs/control/shared build exceed cap')
|
||||
require(shutil.disk_usage(self.root).free >= self.reserve_bytes+extra_control, 'Free-space reserve would be crossed')
|
||||
return dict(immutable_payload_bytes=immutable, ledger_control_bytes=control, shared_mutable_build_bytes=build_bytes,
|
||||
provisional_job_bytes=sum(provisional.values()), total_accounted_bytes=total,
|
||||
shared_mutable_build_inventory=build, unlisted_files_included=False,
|
||||
scope='tracked immutable payload + ledger controls + pending job files + current shared mutable build; unlisted files checked at final audit')
|
||||
|
||||
def begin(self, entry_id, job_file, metadata=None):
|
||||
"""Persist BEFORE spawning; success does not authorize automatic retry."""
|
||||
require(type(entry_id) is str and ID.fullmatch(entry_id), 'Unsafe entry ID')
|
||||
require(metadata is None or type(metadata) is dict, 'Begin metadata must be a JSON dictionary')
|
||||
with self._writer():
|
||||
require(not self._pending, 'Serial ledger has an uncommitted start; do not rerun it')
|
||||
require(entry_id not in self._completed_set and not (self.starts/(entry_id+'.json')).exists(), 'Entry already started/committed; no retry')
|
||||
path = Path(job_file)
|
||||
if not path.is_absolute(): path = self.root / relative_name(str(job_file))
|
||||
rows = self._rows({str(path):identity(path)}, output=False)
|
||||
value = dict(schema=SCHEMA+'-start', entry_id=entry_id, registration_sha256=self.registration_sha,
|
||||
next_sequence=len(self._completed)+1, prev_entry_sha256=self._tail, job=rows[0], metadata=metadata or {},
|
||||
terminal_state='unknown', retry_authorized=False)
|
||||
raw_json(value); self._pending[entry_id] = value
|
||||
try:
|
||||
self._budget(extra_control=len(raw_json(value)))
|
||||
info = publish_exclusive(self.starts/(entry_id+'.json'),value)
|
||||
except BaseException:
|
||||
self._write_failed = True
|
||||
self._pending.pop(entry_id, None); raise
|
||||
self._controls[f'{CONTROL}/started/{entry_id}.json'] = info
|
||||
self._control_bytes += info['bytes']
|
||||
return dict(entry_id=entry_id,start_sha256=info['sha256'],sequence=value['next_sequence'],terminal_state='unknown',retry_authorized=False)
|
||||
|
||||
def append(self, entry_id, inputs, outputs, metadata):
|
||||
"""Commit exactly one observed-successful serial parent job.
|
||||
|
||||
metadata requires job_file/process_receipt_file/scope/observed_returncode.
|
||||
The independent parent process JSON must declare entry_id, registration
|
||||
SHA, job SHA, complete=true, exit_code integer 0, timed_out=false,
|
||||
exit_observed_by_parent=true. These are authenticated recorded facts,
|
||||
not a new OS observation by this ledger.
|
||||
"""
|
||||
require(type(metadata) is dict and all(k in metadata for k in
|
||||
('job_file','process_receipt_file','scope','observed_returncode')), 'Complete parent metadata required')
|
||||
require(type(metadata['scope']) is str and bool(metadata['scope'].strip()) and
|
||||
type(metadata['observed_returncode']) is int and metadata['observed_returncode'] == 0,
|
||||
'Live/failed process cannot be committed as successful')
|
||||
raw_json(metadata)
|
||||
with self._writer():
|
||||
require(entry_id in self._pending and entry_id not in self._completed_set, 'No unique uncommitted start; no retry')
|
||||
start = self._pending[entry_id]; startfile = self.starts/(entry_id+'.json')
|
||||
require(identity(startfile) == self._controls[f'{CONTROL}/started/{entry_id}.json'] and read_json(startfile) == start,
|
||||
'Start authority changed')
|
||||
incoming = self._rows(inputs, output=False); outgoing = self._rows(outputs, output=True)
|
||||
require(outgoing, 'Empty completed output inventory')
|
||||
require(all(row['relative_path'] not in self._tracked for row in outgoing), 'Output overwrites previously tracked file')
|
||||
self._receipt(entry_id,start,incoming,outgoing,metadata)
|
||||
cumulative = self._immutable_bytes+sum(row['bytes'] for row in outgoing)
|
||||
budget = self._budget(outputs=outgoing)
|
||||
value = dict(schema=SCHEMA+'-entry', sequence=len(self._completed)+1, entry_id=entry_id,
|
||||
registration_sha256=self.registration_sha, prev_entry_sha256=self._tail,
|
||||
start_sha256=identity(startfile)['sha256'], consumed_inputs=incoming, new_outputs=outgoing,
|
||||
metadata=metadata, cumulative_immutable_bytes=cumulative, shared_mutable_build=budget['shared_mutable_build_inventory'],
|
||||
hash_scope='actual declared files and current head; historical payload is rehashed at inspect/reopen/final_verify',
|
||||
scientific_gate_claimed=False, OS_exit_independently_observed_here=False)
|
||||
budget = self._budget(outputs=outgoing,extra_control=len(raw_json(value)))
|
||||
require(budget['shared_mutable_build_inventory'] == value['shared_mutable_build'], 'Shared build changed during append accounting')
|
||||
try: info = publish_exclusive(self.entries/f'{value["sequence"]:016d}.json',value)
|
||||
except BaseException:
|
||||
self._write_failed = True; raise
|
||||
self._controls[f'{CONTROL}/entries/{value["sequence"]:016d}.json'] = info
|
||||
self._control_bytes += info['bytes']; self._immutable_bytes = cumulative
|
||||
self._tracked.update({r['relative_path']:{k:r[k] for k in ('bytes','sha256')} for r in outgoing})
|
||||
self._completed.append(entry_id); self._completed_set.add(entry_id); self._pending.pop(entry_id); self._tail = info['sha256']
|
||||
return dict(sequence=value['sequence'],entry_id=entry_id,entry_sha256=self._tail,
|
||||
cumulative_immutable_bytes=cumulative,budget=budget,scientific_gate_claimed=False)
|
||||
|
||||
def _receipt(self,entry_id,start,inputs,outputs,metadata):
|
||||
def path(value):
|
||||
p=Path(value)
|
||||
return str(unlinked(p if p.is_absolute() else self.root/relative_name(str(value))))
|
||||
jobpath=path(metadata['job_file']);receiptpath=path(metadata['process_receipt_file'])
|
||||
supplied={r['path']:r for r in inputs+outputs}
|
||||
require(jobpath == start['job']['path'] and jobpath in supplied and
|
||||
all(supplied[jobpath][k] == start['job'][k] for k in ('bytes','sha256')), 'Job not bound to original start')
|
||||
require(type(metadata.get('observed_returncode')) is int and metadata['observed_returncode'] == 0 and
|
||||
type(metadata.get('scope')) is str and bool(metadata['scope'].strip()), 'Invalid parent observation/scope')
|
||||
require(receiptpath in {r['path'] for r in outputs}, 'Parent process receipt must be a new output')
|
||||
receipt=read_json(receiptpath)
|
||||
require(receipt.get('entry_id') == entry_id and receipt.get('registration_sha256') == self.registration_sha and
|
||||
receipt.get('job_sha256') == start['job']['sha256'] and receipt.get('complete') is True and
|
||||
type(receipt.get('exit_code')) is int and receipt['exit_code'] == 0 and receipt.get('timed_out') is False and
|
||||
receipt.get('exit_observed_by_parent') is True, 'Missing bound observed-successful parent process receipt')
|
||||
|
||||
def _replay(self, verified=None):
|
||||
verified = {} if verified is None else verified
|
||||
header_observed = identity(self.header_path)
|
||||
require(header_observed == self.header_identity, 'Ledger header changed')
|
||||
verified[str(self.header_path)] = header_observed
|
||||
if self._completed:
|
||||
require(identity(self.entries/f'{len(self._completed):016d}.json')['sha256'] == self._tail,
|
||||
'Previously observed ledger head changed')
|
||||
require(not (self.control/'writer.lock').exists(), 'Writer/stale lock present; state unknown, never clear automatically')
|
||||
tracked=dict(self.initial);controls={CONTROL+'/header.json':self.header_identity};completed=[];completed_set=set();tail=None
|
||||
cumulative=sum(v['bytes'] for v in tracked.values())
|
||||
starts={}
|
||||
require(self.starts.is_dir() and self.entries.is_dir(), 'Missing ledger directories')
|
||||
for p in sorted(self.starts.iterdir()):
|
||||
unlinked(p);require(p.is_file() and p.suffix=='.json' and ID.fullmatch(p.stem), 'Unknown/partial start artifact')
|
||||
row=read_json(p);require(row.get('schema')==SCHEMA+'-start' and row.get('entry_id')==p.stem and
|
||||
row.get('registration_sha256')==self.registration_sha and row.get('retry_authorized') is False,
|
||||
'Invalid start schema/authority')
|
||||
require(row['job']==self._rows({row['job']['path']:{k:row['job'][k] for k in ('bytes','sha256')}},output=False,verified=verified)[0], 'Start job bytes changed')
|
||||
starts[p.stem]=row;controls[p.relative_to(self.root).as_posix()]=self._identity_once(p,verified)
|
||||
for index,p in enumerate(sorted(self.entries.iterdir()),1):
|
||||
unlinked(p);require(p.is_file() and p.name==f'{index:016d}.json','Missing/out-of-order/temporary ledger entry')
|
||||
row=read_json(p);entry_id=row.get('entry_id');require(entry_id in starts and entry_id not in completed_set,'Missing/duplicate start binding')
|
||||
start=starts[entry_id]
|
||||
require(row.get('schema')==SCHEMA+'-entry' and type(row.get('sequence')) is int and row['sequence']==index and
|
||||
row.get('registration_sha256')==self.registration_sha and row.get('prev_entry_sha256')==tail and
|
||||
start['next_sequence']==index and start['prev_entry_sha256']==tail and
|
||||
row['start_sha256']==controls[f'{CONTROL}/started/{entry_id}.json']['sha256'] and
|
||||
row.get('scientific_gate_claimed') is False,'Entry chain/start identity differs')
|
||||
for field,output in (('consumed_inputs',False),('new_outputs',True)):
|
||||
items=row[field];require(type(items) is list and len({r['path'] for r in items})==len(items),'Invalid stored file rows')
|
||||
observed=self._rows({r['path']:{k:r[k] for k in ('bytes','sha256')} for r in items},output=output,verified=verified)
|
||||
require(items==observed,'Stored absolute/relative/hash identity differs')
|
||||
require(row['new_outputs'] and all(r['relative_path'] not in tracked for r in row['new_outputs']), 'Immutable output repeated')
|
||||
self._receipt(entry_id,start,row['consumed_inputs'],row['new_outputs'],row['metadata'])
|
||||
tracked.update({r['relative_path']:{k:r[k] for k in ('bytes','sha256')} for r in row['new_outputs']})
|
||||
cumulative+=sum(r['bytes'] for r in row['new_outputs'])
|
||||
require(type(row['cumulative_immutable_bytes']) is int and row['cumulative_immutable_bytes']==cumulative,'Cumulative byte accounting differs')
|
||||
completed.append(entry_id);completed_set.add(entry_id);info=self._identity_once(p,verified);controls[p.relative_to(self.root).as_posix()]=info;tail=info['sha256']
|
||||
pending={k:v for k,v in starts.items() if k not in completed_set}
|
||||
require(len(pending)<=1 and all(v['next_sequence']==len(completed)+1 and v['prev_entry_sha256']==tail for v in pending.values()),
|
||||
'Uncommitted start does not follow actual head')
|
||||
for name,info in tracked.items():require(self._identity_once(self.root/name,verified)==info,'Historical payload changed: '+name)
|
||||
allowed=set(controls)
|
||||
for p in self.control.rglob('*'):
|
||||
unlinked(p)
|
||||
require(p.is_dir() or (p.is_file() and p.relative_to(self.root).as_posix() in allowed),'Unlisted/partial ledger control artifact')
|
||||
# Fresh head reads bracket this audit. This is not an atomic FS snapshot.
|
||||
require(identity(self.header_path)==self.header_identity,'Ledger header changed during audit')
|
||||
require(not (self.control/'writer.lock').exists() and not (self.entries/f'{len(completed)+1:016d}.json').exists(),
|
||||
'Concurrent writer/append detected; audit not terminal')
|
||||
if completed:require(identity(self.entries/f'{len(completed):016d}.json')['sha256']==tail,'Ledger head changed during audit')
|
||||
self._tracked=tracked;self._controls=controls;self._completed=completed;self._completed_set=completed_set;self._pending=pending;self._tail=tail
|
||||
self._immutable_bytes=cumulative
|
||||
self._control_bytes=sum(v['bytes'] for v in controls.values())
|
||||
|
||||
def inspect(self):
|
||||
"""Full historical read verification; no restart or retry authorization."""
|
||||
self._replay()
|
||||
return dict(schema=SCHEMA+'-inspection',registration_sha256=self.registration_sha,entries=len(self._completed),
|
||||
entry_ids=list(self._completed),head_sha256=self._tail,uncommitted_entry_ids=sorted(self._pending),
|
||||
uncommitted_state='STARTED-UNCOMMITTED-STATE-UNKNOWN' if self._pending else None,
|
||||
retry_authorized=False,all_tracked_history_rehashed=True,entire_experiment_tree_checked=False,
|
||||
SHA_scope='each unique payload path read during this invocation; no cross-invocation cache; not an atomic snapshot',
|
||||
budget=self._budget(),scientific_gate_claimed=False)
|
||||
|
||||
def final_verify(self,expected_entry_ids):
|
||||
"""Full tree at this instant, before caller writes any future final report.
|
||||
|
||||
expected IDs must be derived by caller from the externally pinned
|
||||
registration. Shared build is mutable and separately hashed/accounted,
|
||||
never silently accepted as an immutable payload.
|
||||
"""
|
||||
require(type(expected_entry_ids) is list and all(type(x) is str and ID.fullmatch(x) for x in expected_entry_ids) and
|
||||
len(set(expected_entry_ids))==len(expected_entry_ids),'Exact registered expected entry order required')
|
||||
errors=[];verified={}
|
||||
try:self._replay(verified)
|
||||
except (ValueError,OSError,KeyError,TypeError) as exc:errors.append(type(exc).__name__+': '+str(exc))
|
||||
expected={**self._tracked,**self._controls};actual={};links=[]
|
||||
for p in sorted(self.root.rglob('*')):
|
||||
rel=p.relative_to(self.root).as_posix()
|
||||
try:
|
||||
unlinked(p)
|
||||
if p.is_file():actual[rel]=self._identity_once(p,verified)
|
||||
else:require(p.is_dir(),'Nonregular artifact')
|
||||
except (ValueError,OSError) as exc:links.append(rel);errors.append(str(exc))
|
||||
build={k:v for k,v in actual.items() if k.startswith(self.build_name+'/')}
|
||||
immutable={k:v for k,v in actual.items() if k not in build}
|
||||
extra=sorted(set(immutable)-set(expected));missing=sorted(set(expected)-set(immutable))
|
||||
changed=sorted(k for k in set(expected)&set(immutable) if expected[k]!=immutable[k])
|
||||
exact_order=self._completed==expected_entry_ids
|
||||
actual_bytes=sum(v['bytes'] for v in actual.values());within_cap=actual_bytes<=self.max_output_bytes
|
||||
free_reserve=shutil.disk_usage(self.root).free>=self.reserve_bytes
|
||||
# Bracket the *entire* tree walk as well as replay. These fresh small
|
||||
# authority reads deliberately bypass the per-invocation payload cache.
|
||||
# They detect changed/appended heads, not an atomic filesystem snapshot.
|
||||
try:
|
||||
self._check_tail()
|
||||
require(not (self.control/'writer.lock').exists(), 'Concurrent writer detected at final audit end')
|
||||
except (ValueError,OSError) as exc:errors.append(type(exc).__name__+': '+str(exc))
|
||||
passed=not(errors or extra or missing or changed or self._pending) and exact_order and within_cap and free_reserve
|
||||
return dict(schema=SCHEMA+'-final-audit',pass_all=passed,registration_sha256=self.registration_sha,
|
||||
entry_ids=list(self._completed),expected_entry_ids=expected_entry_ids,expected_order_exact=exact_order,
|
||||
head_sha256=self._tail,extra_files=extra,missing_files=missing,changed_files=changed,unsafe_files=links,errors=errors,
|
||||
uncommitted_entry_ids=sorted(self._pending),uncommitted_state_unknown=bool(self._pending),retry_authorized=False,
|
||||
actual_total_bytes=actual_bytes,immutable_and_ledger_bytes=actual_bytes-sum(v['bytes'] for v in build.values()),
|
||||
shared_mutable_build_bytes=sum(v['bytes'] for v in build.values()),shared_mutable_build_inventory=build,
|
||||
output_cap_respected=within_cap,free_reserve_respected=free_reserve,
|
||||
all_current_files_rehashed=True,checked_before_future_final_report=True,
|
||||
SHA_scope='each unique path read during this invocation; fresh header/head checks bracket full audit; no cross-invocation cache; not an atomic snapshot',
|
||||
expected_inventory_authority='caller derives IDs from pinned registration; ledger does not interpret scientific plan',
|
||||
scientific_gate_claimed=False)
|
||||
@@ -0,0 +1,131 @@
|
||||
"""Exact frozen L rate transform and full-shape CUDA sampler, no brain/update.
|
||||
|
||||
Static table derivation is CPU/read-only. Sampling is a separate explicit job.
|
||||
Common-random aliases share only saved immutable CS bytes, never brain outputs.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import time
|
||||
import numpy as np
|
||||
from normal_io import *
|
||||
|
||||
PINS = {
|
||||
'conditioning_inputs.py': '19382e066e450140bb653a3661f980ffe7cc62f412020ef57df0b6e6b3cbb8ba',
|
||||
'conditioning_preflight_inputs.py': '846d2141b472f18b1bb728eed4aa33876896d4b33dece364787c81204f62995f',
|
||||
'trial_plan.py': '6fed3f494d075339a7e5b001d43b2598640b189e038952fbd4d41200bacac587',
|
||||
'seed_registry.py': '0da033b132095ec3087b5d9f64e53c2e391fa50ab0b7653b31296eeb84799b7e',
|
||||
}
|
||||
|
||||
def dependencies():
|
||||
verify({str(LAB/n): s for n,s in PINS.items()})
|
||||
require(not any(n in sys.modules for n in ('runtime_light','conditioning_epoch')), 'No neural modules in sampler')
|
||||
sys.path.insert(0, str(LAB))
|
||||
import conditioning_preflight_inputs as source
|
||||
import conditioning_inputs as inputs
|
||||
require(Path(source.__file__) == LAB/'conditioning_preflight_inputs.py' and
|
||||
Path(inputs.__file__) == LAB/'conditioning_inputs.py', 'Wrong input module identity')
|
||||
return source, inputs
|
||||
|
||||
def derive_rates(root=ROOT):
|
||||
"""Calls the original pinned pn_drive for both registered modes."""
|
||||
import pandas as pd
|
||||
import yaml
|
||||
source, inputs = dependencies()
|
||||
loaded = source.load_rate_tables(root)
|
||||
static = Path(root)/source.STATIC
|
||||
selection = read(static/'odor-encoder/selection.json')
|
||||
panel = pd.read_parquet(static/'odor-encoder/frozen-odor-panel.parquet')
|
||||
mapping = pd.read_parquet(static/'receptor-mapping/olfactory-mapping.parquet')
|
||||
config = yaml.safe_load((Path(root)/source.CONFIG_REL).read_text())
|
||||
drive, ast_sha = source._extract_drive((Path(root)/source.SOURCE_REL).read_bytes(), str(Path(root)/source.SOURCE_REL))
|
||||
vectors = npz(static/'odor-encoder/mapped-glomerular-vectors.npz')
|
||||
result = {}
|
||||
for mode in ('physiological','matched_energy'):
|
||||
for cue in ('A','B'):
|
||||
original = loaded['tables'][cue]
|
||||
targets, rates, frame = drive(original['odor_id'], vectors[original['odor_id']], mapping,
|
||||
selection['glomeruli_order'], mode, loaded['audit']['median_mapped_response_sum'], config)
|
||||
inputs.probabilities_f32(targets, rates)
|
||||
require(np.array_equal(frame.neuron_idx.to_numpy(np.int32), targets) and
|
||||
frame.rate_hz.to_numpy(np.float32).tobytes() == rates.tobytes(), 'Original PN order differs')
|
||||
if mode == 'physiological':
|
||||
require(all(original[n].tobytes() == a.tobytes() for n,a in (('targets',targets),('rates_hz',rates))),
|
||||
'Physiological reconstruction differs')
|
||||
prior = npz(Path(root)/f'experiments/phase4ao-conditioning-interface/inputs/static/{cue}-rates.npz')
|
||||
require(all(prior[n].dtype == a.dtype and prior[n].shape == a.shape and prior[n].tobytes() == a.tobytes()
|
||||
for n,a in (('targets',targets),('rates_hz',rates))), 'Prior AO rate bytes differ')
|
||||
result[mode+'--'+cue] = dict(targets=targets, rates_hz=rates)
|
||||
verify({str(Path(root)/p):s for p,s in source.SOURCE_PINS.items()})
|
||||
return result, dict(original_source_sha256=source.SOURCE_PINS, original_AST_sha256=ast_sha,
|
||||
physiological_matches_original_AO=True, original_PN_column_order_preserved=True,
|
||||
modes=['physiological','matched_energy'], clipping=False, gain_tuning=False,
|
||||
historical_dynamic_results_read=False, random_draws=0)
|
||||
|
||||
def descriptor(task):
|
||||
r = task['recipe']
|
||||
require(task['steps'] == 1200 and task['mode'] in ('physiological','matched_energy'), 'Wrong normal clock/mode')
|
||||
if task['kind'] == 'train':
|
||||
cs = r['cs']
|
||||
if cs is None: return None
|
||||
cue, seed, start, stop = cs['cue'],cs['seed'],cs['start_tick'],cs['stop_tick_exclusive']
|
||||
stream = cs['source_stream_id']
|
||||
else:
|
||||
require(task['kind'] == 'probe' and r['US_requested'] is False and r['weight_updates_enabled'] is False,
|
||||
'Probe contains US/update')
|
||||
cue, seed = r['cue'], r['input']['seed']
|
||||
start, stop, stream = r['cs_start_tick'], r['cs_stop_tick_exclusive'], r['input']['stream_id']
|
||||
require(cue in ('A','B') and type(seed) is int and 0 <= seed < 2**63 and (start,stop) == (0,1000),
|
||||
'CS timing/full seed differs')
|
||||
return dict(mode=task['mode'],cue=cue,seed=seed,steps=1200,cs_start_tick=start,cs_stop_tick_exclusive=stop,
|
||||
source_stream_id=stream,table_id=task['mode']+'--'+cue)
|
||||
|
||||
def inventory_from_plan(plan):
|
||||
descriptors, task_inputs = {}, {}
|
||||
for task in plan['tasks']:
|
||||
d = descriptor(task)
|
||||
key = None if d is None else content_sha(d)
|
||||
if d is not None:
|
||||
require(key not in descriptors or descriptors[key] == d, 'Conflicting shared CS descriptor')
|
||||
descriptors[key] = d
|
||||
require(task['task_id'] not in task_inputs, 'Duplicate planned task')
|
||||
task_inputs[task['task_id']] = key
|
||||
require(len(descriptors) == 4080, 'Expected 4,000 training + 80 evaluation streams')
|
||||
return dict(schema='normal-CS-input-inventory-v1',descriptors=descriptors,task_inputs=task_inputs,
|
||||
brain_output_deduplication=False,CS_only_saved=True,US_composed_from_each_original_epoch=True)
|
||||
|
||||
def sample(reg_sha):
|
||||
require(sys.dont_write_bytecode, 'Use -B')
|
||||
file = EXP/'protocol/preregistered.json'; require(digest(file) == reg_sha, 'Registration differs')
|
||||
reg = read(file); verify(reg['source_sha256']); verify(reg['static_input_sha256'])
|
||||
require(reg['scientific_scope'] == 'normal-acquisition-only', 'Wrong scientific scope')
|
||||
out = unlinked(EXP/'inputs/generated'); require(not out.exists(), 'Sampler cannot retry existing output')
|
||||
h = load_source('_normal_sampler_admission', AP/'isolated_workers.py', AP_SHA)
|
||||
os.environ['CUDA_VISIBLE_DEVICES'] = GPU
|
||||
admission = h._admit_brain()
|
||||
source, inputs = dependencies()
|
||||
inv = read(EXP/'protocol/input-inventory.json')
|
||||
require(digest(EXP/'protocol/input-inventory.json') == reg['prepared_sha256'][str(EXP/'protocol/input-inventory.json')],
|
||||
'Input inventory differs')
|
||||
out.mkdir(); start = time.perf_counter(); completed = {}
|
||||
for index,(key,d) in enumerate(inv['descriptors'].items()):
|
||||
if index % 100 == 0: h._admit_brain()
|
||||
table = npz(EXP/f"inputs/static/{d['table_id']}.npz")
|
||||
require(digest(EXP/f"inputs/static/{d['table_id']}.npz") ==
|
||||
reg['prepared_sha256'][str(EXP/f"inputs/static/{d['table_id']}.npz")], 'Rate file changed')
|
||||
result = inputs.generate_cs_requests(table['targets'],table['rates_hz'],seed=d['seed'],steps=1200,
|
||||
cs_start_tick=0,cs_stop_tick=1000,device='cuda:0',max_uniform_draws=reg['budget']['max_uniform_draws'])
|
||||
save_npz(out/(key+'.npz'),result['requests'])
|
||||
save(out/(key+'.json'),dict(descriptor=d,audit=result['audit'],requests_sha256=digest(out/(key+'.npz'))))
|
||||
completed[key] = dict(requests=pin(out/(key+'.npz')),audit=pin(out/(key+'.json')))
|
||||
verify(reg['source_sha256']); verify(reg['static_input_sha256'])
|
||||
save(EXP/'receipts/input-generation.json',dict(complete=True,registration_sha256=reg_sha,
|
||||
input_inventory_sha256=digest(EXP/'protocol/input-inventory.json'),inputs=completed,
|
||||
descriptors=len(completed),wall_seconds=time.perf_counter()-start,admission=admission,
|
||||
brain_executed=False,weight_updates_executed=False))
|
||||
|
||||
if __name__ == '__main__':
|
||||
p=argparse.ArgumentParser();p.add_argument('--registration-sha256',required=True)
|
||||
sample(p.parse_args().registration_sha256)
|
||||
@@ -0,0 +1,88 @@
|
||||
"""Small exclusive file helpers. No neural imports, mutation or retry policy."""
|
||||
from __future__ import annotations
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
ROOT = Path('/data/digital-drosophila')
|
||||
MODEL = Path(__file__).resolve().parent
|
||||
LAB = MODEL.parent/'olfactory-conditioning-lab-v1'
|
||||
AQ = MODEL.parent/'conditioning-execution-v1'
|
||||
AP = MODEL.parent/'conditioning-interface-v2'
|
||||
EXP = ROOT/'experiments/phase4ar-normal-conditioning'
|
||||
GPU = 'GPU-79f3a85d-adce-7833-7003-6488140ca596'
|
||||
AP_SHA = 'e47651a8ea99d7c44115107ff6b5dc71312183609ae11c891db65bb21ed61e30'
|
||||
|
||||
def require(ok, message):
|
||||
if not ok: raise ValueError(message)
|
||||
|
||||
def digest(path):
|
||||
h = hashlib.sha256()
|
||||
with Path(path).open('rb') as f:
|
||||
for data in iter(lambda: f.read(8 << 20), b''): h.update(data)
|
||||
return h.hexdigest()
|
||||
|
||||
def canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
||||
|
||||
def content_sha(value):
|
||||
return hashlib.sha256(canonical(value).encode()).hexdigest()
|
||||
|
||||
def read(path):
|
||||
def pairs(items):
|
||||
result = {}
|
||||
for key, value in items:
|
||||
require(key not in result, 'Duplicate JSON key'); result[key] = value
|
||||
return result
|
||||
return json.loads(Path(path).read_text(encoding='utf-8'), object_pairs_hook=pairs,
|
||||
parse_constant=lambda _: (_ for _ in ()).throw(ValueError('Nonfinite JSON')))
|
||||
|
||||
def save(path, value):
|
||||
with unlinked(path).open('x', encoding='utf-8', newline='\n') as f:
|
||||
json.dump(value, f, sort_keys=True, indent=2, ensure_ascii=False, allow_nan=False); f.write('\n')
|
||||
|
||||
def unlinked(path):
|
||||
p = Path(path)
|
||||
require(p.is_absolute() and '..' not in p.parts and not any(x.is_symlink() or
|
||||
(hasattr(x, 'is_junction') and x.is_junction()) for x in (p, *p.parents)), 'Unsafe linked path')
|
||||
return p
|
||||
|
||||
def identity(path):
|
||||
p = unlinked(path); require(p.is_file(), 'Missing regular file: '+str(p))
|
||||
return dict(sha256=digest(p), bytes=p.stat().st_size)
|
||||
|
||||
def pin(path):
|
||||
return dict(path=str(unlinked(path)), sha256=digest(path))
|
||||
|
||||
def verify(pins):
|
||||
for p, sha in pins.items(): require(identity(p)['sha256'] == sha, 'Pinned input changed: '+str(p))
|
||||
|
||||
def inventory(root):
|
||||
result = {}
|
||||
for p in sorted(unlinked(root).rglob('*')):
|
||||
unlinked(p)
|
||||
if p.is_file(): result[str(p)] = identity(p)
|
||||
else: require(p.is_dir(), 'Nonregular artifact')
|
||||
return result
|
||||
|
||||
def load_source(name, path, sha):
|
||||
path = unlinked(path); raw = path.read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest() == sha and name not in sys.modules, 'Source/module identity differs')
|
||||
spec = importlib.util.spec_from_file_location(name, path); module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[name] = module
|
||||
exec(compile(raw, str(path), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
def npz(path):
|
||||
import numpy as np
|
||||
with np.load(path, allow_pickle=False) as f: return {k: f[k].copy() for k in f.files}
|
||||
|
||||
def save_npz(path, values):
|
||||
import numpy as np
|
||||
with unlinked(path).open('xb') as f: np.savez_compressed(f, **values)
|
||||
|
||||
def task_key(task):
|
||||
# IDs remain verbatim in receipts; filesystem IDs never incorporate slashes.
|
||||
return 'task-'+hashlib.sha256(task['task_id'].encode()).hexdigest()
|
||||
@@ -0,0 +1,528 @@
|
||||
"""Read-only normal analysis, conditional on independent final integrity.
|
||||
|
||||
analyze(exp, registration_sha256, *, verified_inventory, final_ledger) consumes
|
||||
an externally authenticated absolute-path -> {bytes, sha256} inventory and the
|
||||
final append-ledger audit. Neither caller Boolean nor digest alone is treated
|
||||
as an OS observation: actual ledger/start/job/parent/worker receipts and every
|
||||
consumed file are rebound to bytes. SHA caching is invocation-local, never
|
||||
mtime-based. The outer verifier still owns complete tree/historical integrity,
|
||||
anatomical/source authority, concurrency exclusion and the final science claim.
|
||||
No writes, sampling, subprocesses, follow-up assays, candidates or new gates.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import defaultdict
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
from pathlib import Path
|
||||
import types
|
||||
|
||||
import numpy as np
|
||||
|
||||
GATES_SHA256 = '8ae9bcb77fe14dbdda164f86ffdbfc1e2976be752766ef526777577223b4dd99'
|
||||
PLAN_SHA256 = 'd1a6b840a547cb10b00df40f4d8b287867d09f355c9777e5f7a8b9489f5555ea'
|
||||
ARM_NAMES = dict(paired='paired', d_zero='D=0', frozen='frozen', random_reward='random reward',
|
||||
unpaired='unpaired', cs_only='CS-only', dan_only='DAN-only')
|
||||
ODORS = {'A': '4-ethylphenol', 'B': '3-hexanone'}
|
||||
POINTS = (0, 1, 2, 5, 10, 20, 50)
|
||||
|
||||
|
||||
def require(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
||||
|
||||
|
||||
def sha(value):
|
||||
return hashlib.sha256(canonical(value).encode()).hexdigest()
|
||||
|
||||
|
||||
def _module(name, path, expected):
|
||||
raw = path.read_bytes()
|
||||
require(hashlib.sha256(raw).hexdigest() == expected, 'Analysis dependency pin differs: ' + str(path))
|
||||
module = types.ModuleType(name)
|
||||
module.__file__ = str(path)
|
||||
exec(compile(raw, str(path), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
_HERE = Path(__file__).resolve().parent
|
||||
G = _module('_normal_frozen_gates', _HERE.parent / 'conditioning-execution-v1/learning_gates.py', GATES_SHA256)
|
||||
P = _module('_normal_frozen_plan', _HERE / 'normal_plan.py', PLAN_SHA256)
|
||||
M = G.M
|
||||
|
||||
|
||||
class Reader:
|
||||
"""Actual SHA once per unique path per invocation; not an atomic snapshot."""
|
||||
def __init__(self, inventory):
|
||||
require(type(inventory) is dict and inventory, 'Externally verified checksum inventory required')
|
||||
self.inventory = inventory
|
||||
self.seen = {}
|
||||
|
||||
def path(self, path):
|
||||
path = Path(path)
|
||||
require(path.is_absolute() and '..' not in path.parts and not any(p.is_symlink() or
|
||||
(hasattr(p, 'is_junction') and p.is_junction()) for p in (path, *path.parents)), 'Unsafe artifact path')
|
||||
key = str(path)
|
||||
require(key in self.inventory, 'Artifact absent from external checksum authority: ' + key)
|
||||
expected = self.inventory[key]
|
||||
require(type(expected) is dict and set(expected) == {'bytes', 'sha256'} and
|
||||
type(expected['bytes']) is int and expected['bytes'] >= 0 and M._sha(expected['sha256']), 'Invalid checksum authority')
|
||||
return path, expected
|
||||
|
||||
def check(self, path):
|
||||
path, expected = self.path(path)
|
||||
key = str(path)
|
||||
if key not in self.seen:
|
||||
require(path.is_file(), 'Missing artifact: ' + key)
|
||||
digest = hashlib.sha256()
|
||||
size = 0
|
||||
with path.open('rb') as stream:
|
||||
for part in iter(lambda: stream.read(8 << 20), b''):
|
||||
digest.update(part); size += len(part)
|
||||
require(dict(bytes=size, sha256=digest.hexdigest()) == expected, 'Actual file checksum differs: ' + key)
|
||||
self.seen[key] = dict(expected)
|
||||
require(self.seen[key] == expected, 'Checksum authority changed during analysis')
|
||||
return expected
|
||||
|
||||
def raw(self, path):
|
||||
self.check(path)
|
||||
# Parsed data are read from the now-bound file, not retained for every
|
||||
# trajectory. Concurrent mutation remains an outer quiescence obligation.
|
||||
return Path(path).read_bytes()
|
||||
|
||||
def json(self, path):
|
||||
def unique(items):
|
||||
result = {}
|
||||
for key, value in items:
|
||||
require(key not in result, 'Duplicate JSON field'); result[key] = value
|
||||
return result
|
||||
return json.loads(self.raw(path).decode('utf-8'), object_pairs_hook=unique,
|
||||
parse_constant=lambda _: (_ for _ in ()).throw(ValueError('Nonfinite JSON')))
|
||||
|
||||
def arrays(self, path):
|
||||
with np.load(io.BytesIO(self.raw(path)), allow_pickle=False) as archive:
|
||||
return {key: archive[key].copy() for key in archive.files}
|
||||
|
||||
|
||||
def task_key(task):
|
||||
return 'task-' + hashlib.sha256(task['task_id'].encode()).hexdigest()
|
||||
|
||||
|
||||
def expected_entries(plan):
|
||||
result = ['input-generation']
|
||||
for task in plan['tasks']:
|
||||
result.extend(task_key(task) + suffix for suffix in
|
||||
(('--brain', '--update', '--verify') if task['kind'] == 'train' else ('--brain',)))
|
||||
return result
|
||||
|
||||
|
||||
def audit_case(reader, exp, task, job, *, template, inputs, sampler, populations, population_file, output_cap):
|
||||
"""Independent raw CS/US composition and reset/spec checks; no brain call.
|
||||
|
||||
A scheduled US request is not an accepted spike or a successful behavior.
|
||||
The artificial D scalar remains the original recipe, never an event count.
|
||||
"""
|
||||
exp = Path(exp); case = exp / 'cases' / task_key(task)
|
||||
require(job['case_dir'] == str(case), 'Case path differs from original task')
|
||||
spec = reader.json(case / 'spec.json')
|
||||
removed = ('validation_cohort', 'odor_index', 'expected_external_events', 'training', 'cs_input_seed', 'cs_input_seed_bits',
|
||||
'seed_scope', 'odor_id', 'odor_name', 'source_panel_row', 'source_panel_split', 'rate_sum_hz', 'target_count',
|
||||
'expected_CS_requests', 'CS_window', 'outer_epoch_id', 'outer_arm', 'outer_protocol')
|
||||
fixed = {k: v for k, v in template.items() if k not in removed}
|
||||
fixed.update(name=task_key(task), steps=1200, duration_ms=120., max_steps=1200, budget_root=str(exp),
|
||||
output_budget_bytes=output_cap, mode=task['mode'], within_trial_weight_updates=False,
|
||||
outer_protocol='normal-acquisition-v1', outer_task_id=task['task_id'], outer_arm=task['arm'])
|
||||
require(canonical(spec) == canonical(fixed) and spec['seed'] == template['seed'] and spec['dt_ms'] == .1 and
|
||||
spec['apl_delay_steps'] == 18 and spec['precision'] == 'float64' and spec['apl_precision'] == 'float32' and
|
||||
spec['record_history'] is False and spec['kind'] == 'fullgraph', 'Scientific model/reset/clock spec changed')
|
||||
recipe = task['recipe']
|
||||
cs_recipe = recipe['cs'] if task['kind'] == 'train' else recipe
|
||||
expected = None
|
||||
if cs_recipe is not None:
|
||||
cue = cs_recipe['cue']
|
||||
seed = cs_recipe['seed'] if task['kind'] == 'train' else cs_recipe['input']['seed']
|
||||
stream = cs_recipe['source_stream_id'] if task['kind'] == 'train' else cs_recipe['input']['stream_id']
|
||||
require(type(seed) is int and 0 <= seed < 2**63, 'Original full63 seed required')
|
||||
expected = dict(mode=task['mode'], cue=cue, seed=seed, steps=1200, cs_start_tick=0,
|
||||
cs_stop_tick_exclusive=1000, source_stream_id=stream, table_id=task['mode'] + '--' + cue)
|
||||
csid = None if expected is None else sha(expected)
|
||||
require(inputs['task_inputs'][task['task_id']] == csid, 'Original task/CS descriptor mapping differs')
|
||||
binding = reader.json(case / 'input-binding.json')
|
||||
require(binding['task_id'] == task['task_id'] and binding['CS_descriptor_id'] == csid and
|
||||
binding['DAN_type'] == task['dan_type'] and binding['population_file'] ==
|
||||
dict(path=population_file, sha256=reader.check(population_file)['sha256']), 'Case input/population binding differs')
|
||||
empty = dict(tick=np.empty(0, np.int32), neuron_idx=np.empty(0, np.int32))
|
||||
source = empty
|
||||
if csid is None:
|
||||
require(binding['CS_source'] is None, 'No-CS epoch acquired an odor source')
|
||||
else:
|
||||
npzpath = exp / f'inputs/generated/{csid}.npz'; jsonpath = exp / f'inputs/generated/{csid}.json'
|
||||
generated = reader.json(jsonpath); audit = generated['audit']
|
||||
require(inputs['descriptors'][csid] == generated['descriptor'] == expected and
|
||||
generated['requests_sha256'] == reader.check(npzpath)['sha256'] and
|
||||
binding['CS_source'] == dict(path=str(npzpath), sha256=reader.check(npzpath)['sha256']) and
|
||||
sampler['inputs'][csid] == dict(requests=binding['CS_source'], audit=dict(path=str(jsonpath), sha256=reader.check(jsonpath)['sha256'])),
|
||||
'Saved sampler receipt/descriptor differs')
|
||||
require(audit['seed'] == audit['generator_initial_seed'] == seed and audit['seed_bits'] == 63 and
|
||||
audit['seed_conversion'] == 'exact integer; no truncation/modulo/offset' and audit['private_generator'] is True and
|
||||
audit['matrix_draw_calls'] == 1 and audit['uniform_matrix_shape'][0] == 1200 and audit['CS_window'] == [0, 1000],
|
||||
'Original sampler seed/full-shape/window evidence differs')
|
||||
source = reader.arrays(npzpath)
|
||||
|
||||
def keys(request):
|
||||
require(set(request) == {'tick', 'neuron_idx'} and all(v.dtype == np.int32 and v.ndim == 1 for v in request.values()) and
|
||||
request['tick'].shape == request['neuron_idx'].shape and np.all((request['tick'] >= 0) & (request['tick'] < 1200)) and
|
||||
np.all((request['neuron_idx'] >= 0) & (request['neuron_idx'] < 166700)), 'Invalid raw request arrays')
|
||||
result = request['tick'].astype(np.int64) * 166700 + request['neuron_idx']
|
||||
require(np.all(result[1:] > result[:-1]), 'Requests are not sorted unique')
|
||||
return result
|
||||
|
||||
source_keys = keys(source)
|
||||
require(np.all(source['tick'] < 1000), 'CS escaped original window')
|
||||
cs, us, combined = (reader.arrays(case / name) for name in ('cs_requests.npz', 'us_requests.npz', 'requests.npz'))
|
||||
cs_keys, us_keys, combined_keys = keys(cs), keys(us), keys(combined)
|
||||
require(np.array_equal(source_keys, cs_keys), 'Actual case CS differs from original saved input')
|
||||
requested = task['kind'] == 'train' and recipe['us']['requested']
|
||||
dan = populations[task['dan_type']]
|
||||
require(dan.dtype == np.int32 and dan.ndim == 1 and np.all(dan[1:] > dan[:-1]), 'Actual DAN mapping differs')
|
||||
require(binding['DAN_membership_sha256'] == hashlib.sha256(dan.tobytes()).hexdigest(), 'DAN membership binding differs')
|
||||
expected_us = 900 * 166700 + dan.astype(np.int64) if requested else np.empty(0, np.int64)
|
||||
require(np.array_equal(us_keys, expected_us) and not np.intersect1d(cs_keys, us_keys).size and
|
||||
np.array_equal(combined_keys, np.union1d(cs_keys, us_keys)), 'Actual scheduled US/CS composition differs')
|
||||
masks = reader.arrays(case / 'source-mask.npz')
|
||||
expected_mask = np.where(np.isin(combined_keys, cs_keys), 1, 2).astype(np.uint8)
|
||||
require(set(masks) == {'source_mask'} and masks['source_mask'].dtype == np.uint8 and
|
||||
np.array_equal(masks['source_mask'], expected_mask) and binding['composition']['policy'] == 'error' and
|
||||
binding['composition']['cross_source_conflict_count'] == 0, 'Raw composition/source-mask differs')
|
||||
|
||||
|
||||
class Evidence:
|
||||
def __init__(self, reader, exp, registration_sha, expected, final):
|
||||
require(final.get('schema') == 'normal-append-ledger-v1-final-audit' and
|
||||
final.get('registration_sha256') == registration_sha and final.get('pass_all') is True and
|
||||
final.get('entry_ids') == final.get('expected_entry_ids') == expected and
|
||||
final.get('expected_order_exact') is True, 'Final ledger authority/complete order differs')
|
||||
require(all(final.get(k) == [] for k in ('extra_files', 'missing_files', 'changed_files',
|
||||
'unsafe_files', 'errors', 'uncommitted_entry_ids')) and final.get('uncommitted_state_unknown') is False,
|
||||
'Incomplete/failed final ledger audit')
|
||||
self.r, self.exp, self.regsha, self.expected = reader, Path(exp), registration_sha, expected
|
||||
self.index, self.tail, self.final = 0, None, final
|
||||
|
||||
def process(self, entry_id, kind):
|
||||
self.index += 1
|
||||
require(self.expected[self.index - 1] == entry_id, 'Analysis process order differs')
|
||||
entry_path = self.exp / f'.append-ledger/entries/{self.index:016d}.json'
|
||||
entry = self.r.json(entry_path)
|
||||
start_path = self.exp / f'.append-ledger/started/{entry_id}.json'
|
||||
start = self.r.json(start_path)
|
||||
job_path = self.exp / f'jobs/{entry_id}.json'
|
||||
process_path = self.exp / 'receipts' / entry_id / 'process.json'
|
||||
require(entry['entry_id'] == start['entry_id'] == entry_id and entry['sequence'] == start['next_sequence'] == self.index and
|
||||
entry['registration_sha256'] == start['registration_sha256'] == self.regsha and
|
||||
entry['prev_entry_sha256'] == start['prev_entry_sha256'] == self.tail and
|
||||
entry['start_sha256'] == self.r.check(start_path)['sha256'] and start['retry_authorized'] is False,
|
||||
'Ledger/start chain differs')
|
||||
incoming = {row['path']: row for row in entry['consumed_inputs']}
|
||||
outgoing = {row['path']: row for row in entry['new_outputs']}
|
||||
require(len(incoming) == len(entry['consumed_inputs']) and len(outgoing) == len(entry['new_outputs']), 'Duplicate ledger files')
|
||||
for path, row in {**incoming, **outgoing}.items():
|
||||
_, bound = self.r.path(path)
|
||||
require(all(row[k] == bound[k] for k in ('bytes', 'sha256')), 'Ledger/checksum authority differs')
|
||||
metadata = entry['metadata']
|
||||
require(metadata['job_file'] == str(job_path) and metadata['process_receipt_file'] == str(process_path) and
|
||||
type(metadata['observed_returncode']) is int and metadata['observed_returncode'] == 0 and
|
||||
str(process_path) in outgoing and str(job_path) in incoming and
|
||||
start['job']['path'] == str(job_path) and start['job']['sha256'] == self.r.check(job_path)['sha256'],
|
||||
'Process/job not owned by committed ledger entry')
|
||||
process, job = self.r.json(process_path), self.r.json(job_path)
|
||||
require(process['entry_id'] == entry_id and process['registration_sha256'] == job['registration_sha256'] == self.regsha and
|
||||
process['job_sha256'] == self.r.check(job_path)['sha256'] and process['complete'] is True and
|
||||
type(process['exit_code']) is int and process['exit_code'] == 0 and process['timed_out'] is False and
|
||||
process['exit_observed_by_parent'] is True and job['kind'] == kind, 'Actual parent exit/job receipt differs')
|
||||
for path, digest in job['input_sha256'].items():
|
||||
require(path in incoming and self.r.check(path)['sha256'] == digest, 'Actual consumed job input differs')
|
||||
for label in ('stdout', 'stderr'):
|
||||
path = self.exp / f'logs/{entry_id}.{label}.log'
|
||||
require(str(path) in outgoing and self.r.check(path)['sha256'] == process[label + '_sha256'], 'Parent log differs')
|
||||
if kind in ('brain', 'update'):
|
||||
require(job['receipt_file'] in outgoing and job['receipt_file'] + '.attempt.json' in outgoing,
|
||||
'Worker/attempt receipt not ledger owned')
|
||||
worker = self.r.json(job['receipt_file'])
|
||||
closure = dict(job['input_sha256'])
|
||||
closure[str(job_path)] = self.r.check(job_path)['sha256']
|
||||
# The AP worker includes its own exact script source in its closure.
|
||||
script = process['argv'][2]
|
||||
closure[script] = self.r.check(script)['sha256']
|
||||
for value in job['sources'].values():
|
||||
require(self.r.check(value['path'])['sha256'] == value['sha256'], 'Worker source differs')
|
||||
closure[value['path']] = value['sha256']
|
||||
require(worker['schema'] == 'phase4ap-isolated-worker-receipt-v1' and worker['complete'] is True and
|
||||
worker['job_id'] == entry_id and worker['kind'] == kind and worker['registration_sha256'] == self.regsha and
|
||||
worker['job_sha256'] == self.r.check(job_path)['sha256'] and worker['verified_input_sha256'] == closure and
|
||||
worker['attempt_sha256'] == self.r.check(job['receipt_file'] + '.attempt.json')['sha256'], 'Worker/attempt binding differs')
|
||||
declared = {str(Path(p).relative_to(job['output_dir'])): row['sha256'] for p, row in outgoing.items()
|
||||
if Path(p).is_relative_to(job['output_dir'])}
|
||||
require(worker['output_files_sha256'] == declared, 'Worker output coverage differs')
|
||||
self.tail = self.r.check(entry_path)['sha256']
|
||||
return dict(job=job, outgoing=outgoing, process_sha256=self.r.check(process_path)['sha256'], process_path=str(process_path))
|
||||
|
||||
def finish(self):
|
||||
require(self.index == len(self.expected) and self.tail == self.final['head_sha256'], 'Missing process or terminal ledger head differs')
|
||||
|
||||
|
||||
def audit_records(reader, exp, reg, regsha, plan, evidence, *, template, inputs, populations):
|
||||
"""Bind all 33,920 tasks and actual update chains; retain only small indexes."""
|
||||
sample = evidence.process('input-generation', 'sample')
|
||||
sampler = reader.json(Path(exp) / 'receipts/input-generation.json')
|
||||
require(sampler['complete'] is True and sampler['registration_sha256'] == regsha and
|
||||
str(Path(exp) / 'receipts/input-generation.json') in sample['outgoing'], 'Sampler receipt not ledger owned')
|
||||
require(sampler['descriptors'] == len(inputs['descriptors']) == 4080 and set(sampler['inputs']) == set(inputs['descriptors']) and
|
||||
sampler['input_inventory_sha256'] == reader.check(Path(exp) / 'protocol/input-inventory.json')['sha256'], 'Actual sampler inventory incomplete')
|
||||
previous, probes, arms, record_hashes = {}, {}, defaultdict(list), []
|
||||
for task in plan['tasks']:
|
||||
key = task_key(task); result_path = Path(exp) / f'results/{key}.json'
|
||||
record = reader.json(result_path)
|
||||
require(record['schema'] == 'normal-task-result-v1' and record['complete'] is True and
|
||||
record['registration_sha256'] == regsha and canonical(record['task']) == canonical(task), 'Actual result/task differs')
|
||||
branch = task['block_id'], task['arm']
|
||||
overlay = previous.get(branch, reg['initial_overlay'])
|
||||
require(record['overlay_before'] == overlay, 'Delta ancestry changed or probe fed back')
|
||||
brain = evidence.process(key + '--brain', 'brain')
|
||||
audit_case(reader, exp, task, brain['job'], template=template, inputs=inputs, sampler=sampler,
|
||||
populations=populations, population_file=reg['population_file'], output_cap=reg['budget']['output_cap_bytes'])
|
||||
job = brain['job']; output = Path(exp) / 'runs' / key
|
||||
require(record['brain_process_receipt_path'] == brain['process_path'] and
|
||||
record['checkpoint_dir'] == job['output_dir'] == str(output) and
|
||||
all(job[k] == overlay[k] for k in ('overlay_file', 'overlay_manifest')) and
|
||||
job['diagnostic_mode'] == 'light', 'Brain result/overlay path differs')
|
||||
manifest = reader.json(output / 'checkpoint-manifest.json')
|
||||
require(record['checkpoint_manifest_sha256'] == record['brain_audit']['checkpoint_manifest_sha256'] ==
|
||||
reader.check(output / 'checkpoint-manifest.json')['sha256'] and
|
||||
record['brain_audit']['task_id'] == task['task_id'], 'Checkpoint binding differs')
|
||||
for name, digest in manifest['files_sha256'].items():
|
||||
require(reader.check(output / name)['sha256'] == digest, 'Checkpoint payload differs')
|
||||
record_hashes.append([task['task_id'], reader.check(result_path)['sha256']])
|
||||
if task['kind'] == 'probe':
|
||||
require(str(result_path) in brain['outgoing'], 'Probe result not ledger owned')
|
||||
probes[(task['block_id'], task['arm'], task['checkpoint'], task['recipe']['cue'])] = record
|
||||
continue
|
||||
update = evidence.process(key + '--update', 'update')
|
||||
cpu = evidence.process(key + '--verify', 'cpu_verify')
|
||||
require(record['update_process_receipt_path'] == update['process_path'] and record['cpu_process_receipt_path'] == cpu['process_path'] and
|
||||
str(result_path) in cpu['outgoing'], 'Training result/parent process ownership differs')
|
||||
authority = reader.json(record['epoch_authority']['path'])
|
||||
require(reader.check(record['epoch_authority']['path'])['sha256'] == record['epoch_authority']['sha256'] ==
|
||||
update['job']['authority_sha256'] == cpu['job']['authority_sha256'] and authority['epoch_id'] == task['task_id'] and
|
||||
authority['checkpoint_dir'] == str(output) and authority['checkpoint_manifest_sha256'] == record['checkpoint_manifest_sha256'],
|
||||
'Original E authority differs')
|
||||
command = dict(steps=1200, compartment=task['compartment_verbatim'], us_tick=task['recipe']['us']['tick'],
|
||||
d_command=task['recipe']['D_command'], frozen=not task['recipe']['update_enabled'], trace_backend='torch')
|
||||
require(authority['command'] == command, 'Original E command changed')
|
||||
valid = reader.json(record['cpu_validation']['path'])
|
||||
after = dict(overlay_file=str(Path(exp) / 'updates' / key / 'delta-after.npz'),
|
||||
overlay_manifest=str(Path(exp) / 'updates' / key / 'overlay-manifest.json'))
|
||||
require(record['update_dir'] == update['job']['output_dir'] == cpu['job']['update_dir'] == str(Path(exp) / 'updates' / key) and
|
||||
record['cpu_validation']['path'] == cpu['job']['receipt_file'] and record['cpu_validation']['path'] in cpu['outgoing'] and
|
||||
record['epoch_authority']['path'] == update['job']['authority_file'] == cpu['job']['authority_file'] and
|
||||
authority['files']['state'] == dict(path=str(output / 'state.npz'), sha256=reader.check(output / 'state.npz')['sha256']) and
|
||||
authority['files']['overlay_before'] == dict(path=overlay['overlay_file'], sha256=reader.check(overlay['overlay_file'])['sha256']) and
|
||||
authority['files']['overlay_manifest_before'] == dict(path=overlay['overlay_manifest'], sha256=reader.check(overlay['overlay_manifest'])['sha256']) and
|
||||
record['after_overlay'] == after and reader.check(record['cpu_validation']['path'])['sha256'] == record['cpu_validation']['sha256'] and
|
||||
valid['complete'] is True and valid['frozen_U_verify_receipt_recomputed'] is True and valid['actual_sealed_events_used'] is True and
|
||||
valid['epoch_authority_sha256'] == record['epoch_authority']['sha256'] and
|
||||
valid['after_overlay_sha256'] == reader.check(after['overlay_file'])['sha256'], 'Independent CPU update validation differs')
|
||||
if task['arm'] in ('d_zero', 'frozen', 'cs_only'):
|
||||
require(not reader.arrays(after['overlay_file'])['plastic_delta_mv'].view(np.uint32).any(), 'Zero control contains nonzero delta')
|
||||
previous[branch] = after
|
||||
arms[branch].append(dict(result=record_hashes[-1], brain=brain['process_sha256'],
|
||||
update=update['process_sha256'], cpu=cpu['process_sha256'], requested=task['recipe']['us']['requested']))
|
||||
evidence.finish()
|
||||
require(len(probes) == 3920 and len(arms) == 280 and len(record_hashes) == 33920, 'Incomplete actual task inventory')
|
||||
return probes, arms, sha(record_hashes)
|
||||
|
||||
|
||||
def build_registry(trial, plan, *, nodes, populations, population_binding_sha, regsha, input_hashes):
|
||||
membership = M.validate_populations(nodes, populations)
|
||||
blocks = {}
|
||||
inputs = {(r['block_id'], r['cue']): r for r in plan['evaluation_inputs']}
|
||||
for block in trial['plan']['blocks']:
|
||||
identity = block['block_id']
|
||||
source_rows = [r for r in trial['seed_manifest']['independent_streams']
|
||||
if r['key'][0] == identity and r['key'][1] == 'normal' and r['split'] in ('training', 'design')]
|
||||
sources = [dict(stream_id=P._FROZEN['trial_plan']._stream_id(P.MASTER, r['split'], r['key']),
|
||||
seed=r['seed'], split=r['split']) for r in source_rows]
|
||||
blocks[identity] = dict(mode=block['mode'], dan_type=block['dan_type'], compartment_verbatim=block['compartment_verbatim'],
|
||||
conditioned_cue=ODORS[block['initial_reinforced_cue']], replicate=block['replicate'], training_sources=sources,
|
||||
evaluation_sources={ODORS[c]: {k: inputs[(identity, c)][k] for k in ('stream_id', 'seed', 'split')} for c in ODORS},
|
||||
evaluation_input_sha256={ODORS[c]: input_hashes[(identity, c)] for c in ODORS})
|
||||
registry = dict(schema=G.REGISTRY_SCHEMA, protocol_sha256=regsha, population_binding_sha256=population_binding_sha,
|
||||
nodes_raw_sha256=M._hash(nodes), population_membership_sha256=membership['membership_sha256'], blocks=blocks)
|
||||
G.validate_registry(registry, expected_sha256=G.descriptor_sha256(registry))
|
||||
return registry
|
||||
|
||||
|
||||
def compact_metric(metric):
|
||||
return dict(rawS=metric['rawS'], rawB=metric['rawB'], separation=metric['separation'],
|
||||
cues={cue: dict(state_pre=summary['pre_state_raw_sha256'], state_post=summary['post_state_raw_sha256'],
|
||||
populations={name: {k: v for k, v in group.items() if not isinstance(v, list)}
|
||||
for name, group in summary['populations'].items()}) for cue, summary in metric['cues'].items()})
|
||||
|
||||
|
||||
def scientific_reports(probes, arms, *, registry, authority, nodes, populations, load_state):
|
||||
"""One cell's terminal vectors at a time; curve outputs contain no raw vectors."""
|
||||
curves, compact_reports = [], []
|
||||
|
||||
def cells():
|
||||
for mode in M.MODES:
|
||||
for dan in M.DAN_TYPES:
|
||||
for conditioned in M.CUES:
|
||||
rows = []
|
||||
selected = [(key, b) for key, b in registry['blocks'].items()
|
||||
if (b['mode'], b['dan_type'], b['conditioned_cue']) == (mode, dan, conditioned)]
|
||||
for identity, block in selected:
|
||||
arm_values = {}
|
||||
for name, legacy_name in ARM_NAMES.items():
|
||||
pre = {ODORS[c]: load_state(probes[(identity, name, 0, c)]) for c in ODORS}
|
||||
terminal = None
|
||||
for point in POINTS:
|
||||
post = pre if point == 0 else {ODORS[c]: load_state(probes[(identity, name, point, c)]) for c in ODORS}
|
||||
metric = M.arm_metrics(pre, post, conditioned_cue=conditioned, nodes=nodes, populations=populations)
|
||||
curves.append(dict(block_id=identity, arm=name, checkpoint=point, metrics=compact_metric(metric)))
|
||||
if point == 50:
|
||||
terminal = metric
|
||||
history = arms[(identity, name)]
|
||||
require(len(history) == (150 if name == 'unpaired' else 100), 'Missing actual training/control epochs')
|
||||
execution = dict(complete=True, recording_verified=True, receipt_sha256=sha(history), assay='normal',
|
||||
epoch_duration_ms=120., cs_duration_ms=100., us_tick=900, completed_epochs=len(history),
|
||||
reinforcement_opportunities=sum(r['requested'] for r in history), terminal_pairings=50)
|
||||
arm_values[legacy_name] = dict(metrics=terminal, execution=execution)
|
||||
rows.append(dict(replicate_id=identity, replicate_unit='independent_training',
|
||||
training_stream_ids=[x['stream_id'] for x in block['training_sources']],
|
||||
evaluation_stream_ids=[block['evaluation_sources'][c]['stream_id'] for c in M.CUES],
|
||||
assay='normal', mode=mode, dan_type=dan, conditioned_cue=conditioned, arms=arm_values))
|
||||
report = G.evaluate_acquisition(rows, assay='normal', mode=mode, dan_type=dan,
|
||||
conditioned_cue=conditioned, registry=registry, authority=authority)
|
||||
compact_reports.append({k: v for k, v in report.items()
|
||||
if k not in ('acquisition_metric_inputs', 'frozen_acquisition_result')})
|
||||
yield report
|
||||
|
||||
cohort = G.summarize_cohort(cells(), registry=registry, authority=authority, required_assays=('normal',))
|
||||
require(cohort['complete_inventory'], 'Missing normal cells')
|
||||
return dict(cells=compact_reports, cohort=cohort, curves=curves)
|
||||
|
||||
|
||||
def legacy_audit(reports, declared_mapping):
|
||||
"""G.H_MAPPING source layout; call the unchanged M scalar twice per group."""
|
||||
require(declared_mapping == G.H_MAPPING, 'Explicit original registered H mapping required')
|
||||
lookup = {(r['mode'], r['dan_type'], r['conditioned_cue']): r for r in reports}
|
||||
require(len(reports) == len(lookup) == 8, 'Exact eight-cell legacy input required')
|
||||
groups = []
|
||||
for mode in M.MODES:
|
||||
for cue in M.CUES:
|
||||
selected = {d: lookup[(mode, d, cue)] for d in M.DAN_TYPES}
|
||||
outcomes = {}
|
||||
for source in M.DAN_TYPES:
|
||||
gains = {label: [r['population_separation_gains']['MBON'] for r in selected[dan]['replicates']]
|
||||
for dan, label in (('PAM15', 'appetitive-conditioning'), ('PPL103', 'aversive-conditioning'))}
|
||||
for name, label in (('D=0', 'd-zero-control'), ('random reward', 'random-reward-control'), ('frozen', 'frozen-brain-control')):
|
||||
controls = selected[source]['legacy_control_MBON_gains'][name]
|
||||
require(set(controls) == {r['replicate_id'] for r in selected[source]['replicates']}, 'Legacy replicate control source differs')
|
||||
gains[label] = [controls[r['replicate_id']] for r in selected[source]['replicates']]
|
||||
outcomes[source] = M.legacy_h_mean_control_audit(gains)
|
||||
groups.append(dict(mode=mode, conditioned_cue=cue, control_sources=outcomes,
|
||||
both_pass=all(v['predicate_pass'] for v in outcomes.values())))
|
||||
return dict(schema=G.SCHEMA, status='CONDITIONAL-AUDIT', declared_mapping=declared_mapping, groups=groups,
|
||||
both_pass=all(g['both_pass'] for g in groups), original_H_data_layout_reproduced=False,
|
||||
new_stricter_control_source_mapping=True, **G._scope())
|
||||
|
||||
|
||||
def analyze(exp, registration_sha256, *, verified_inventory, final_ledger):
|
||||
exp, reader = Path(exp), Reader(verified_inventory)
|
||||
regpath = exp / 'protocol/preregistered.json'
|
||||
require(reader.check(regpath)['sha256'] == registration_sha256, 'Registration authority differs')
|
||||
reg = reader.json(regpath)
|
||||
require(reg['schema'] == 'normal-conditioning-registration-v1' and reg['scientific_scope'] == 'normal-acquisition-only' and
|
||||
reg['subsequent_assays_authorized'] is False, 'Wrong scientific authority')
|
||||
for collection in ('source_sha256', 'input_sha256', 'prepared_sha256'):
|
||||
for path, digest in reg[collection].items():
|
||||
require(reader.check(path)['sha256'] == digest, 'Registered dependency differs')
|
||||
plan = reader.json(exp / 'protocol/normal-plan.json')
|
||||
full = reader.json(reg['original_full_trial_plan']['path'])
|
||||
require(reader.check(reg['original_full_trial_plan']['path'])['sha256'] == reg['original_full_trial_plan']['sha256'] == P.AO_TRIAL_FILE_SHA256,
|
||||
'Original AO full plan differs')
|
||||
evaluation = P.expand_pinned_evaluation(full)
|
||||
P.validate_normal_plan(plan, full, evaluation)
|
||||
gates = reader.json(exp / 'protocol/gates.json')
|
||||
require(gates['H_mapping'] == G.H_MAPPING and gates['all_eight_cells_required'] is True and
|
||||
gates['same_replicate_conjunction_at_least'] == 3 and gates['training_replicates'] == 5 and gates['terminal_checkpoint'] == 50 and
|
||||
gates['intermediate_checkpoints_cannot_rescue_terminal'] is True, 'Registered scientific policy differs')
|
||||
template = reader.json(exp / 'protocol/case-template.json')
|
||||
nodes_path = Path(template['graph_dir']) / 'nodes.npy'
|
||||
nodes = np.load(io.BytesIO(reader.raw(nodes_path)), allow_pickle=False)
|
||||
require(nodes.dtype == np.int32 and len(nodes) == 166700, 'Full original graph nodes required')
|
||||
require('readout_population_file' in reg, 'Registered full legacy/non-MBON readout populations missing')
|
||||
populations = reader.arrays(reg['readout_population_file'])
|
||||
original = reader.arrays(reg['population_file'])
|
||||
for name in ('MBON', 'MBON01', 'MBON12'):
|
||||
require(np.array_equal(original[name], populations[name]), 'Original anatomical population changed')
|
||||
M.validate_populations(nodes, populations)
|
||||
require('readout_population_binding_file' in reg, 'Registered anatomical binding file missing')
|
||||
population_binding_sha = reader.check(reg['readout_population_binding_file'])['sha256']
|
||||
evidence = Evidence(reader, exp, registration_sha256, expected_entries(plan), final_ledger)
|
||||
inputs = reader.json(exp / 'protocol/input-inventory.json')
|
||||
probes, arms, inventory_sha = audit_records(reader, exp, reg, registration_sha256, plan, evidence,
|
||||
template=template, inputs=inputs, populations=original)
|
||||
input_hashes, seen_receipts = {}, set()
|
||||
|
||||
def load_state(record):
|
||||
task = record['task']; key = task_key(task)
|
||||
receipt = record['brain_process_receipt_path']
|
||||
require(receipt not in seen_receipts, 'Probe execution reused across snapshots')
|
||||
seen_receipts.add(receipt)
|
||||
csid = inputs['task_inputs'][task['task_id']]
|
||||
recipe = task['recipe']
|
||||
expected_descriptor = dict(mode=task['mode'], cue=recipe['cue'], seed=recipe['input']['seed'], steps=1200,
|
||||
cs_start_tick=0, cs_stop_tick_exclusive=1000, source_stream_id=recipe['input']['stream_id'],
|
||||
table_id=task['mode'] + '--' + recipe['cue'])
|
||||
require(csid == sha(expected_descriptor) and inputs['descriptors'][csid] == expected_descriptor,
|
||||
'Evaluation seed/stream/clock mapping differs from original plan')
|
||||
source = exp / f'inputs/generated/{csid}.npz'
|
||||
generated = reader.json(exp / f'inputs/generated/{csid}.json')
|
||||
require(generated['descriptor'] == inputs['descriptors'][csid] and generated['requests_sha256'] == reader.check(source)['sha256'],
|
||||
'Actual evaluation input descriptor differs')
|
||||
case = exp / 'cases' / key
|
||||
binding = reader.json(case / 'input-binding.json')
|
||||
require(binding['CS_source'] == dict(path=str(source), sha256=reader.check(source)['sha256']) and
|
||||
binding['CS_descriptor_id'] == csid and binding['task_id'] == task['task_id'], 'Probe shared input binding differs')
|
||||
requests, cs, us = (reader.arrays(path) for path in (case / 'requests.npz', source, case / 'us_requests.npz'))
|
||||
require(set(requests) == set(cs) == set(us) == {'tick', 'neuron_idx'} and
|
||||
all(not len(v) for v in us.values()) and all(np.array_equal(requests[k], cs[k]) for k in requests), 'Probe includes US or changed CS')
|
||||
state = reader.arrays(Path(record['checkpoint_dir']) / 'state.npz')
|
||||
actual = M.validate_state(state, nodes=nodes, steps=1200)
|
||||
require(actual['hashes'] == record['brain_audit']['state_raw_sha256'], 'Actual probe raw arrays differ')
|
||||
return state
|
||||
|
||||
for item in plan['evaluation_inputs']:
|
||||
record = probes[(item['block_id'], 'paired', 0, item['cue'])]
|
||||
csid = inputs['task_inputs'][record['task']['task_id']]
|
||||
input_hashes[(item['block_id'], item['cue'])] = reader.check(exp / f'inputs/generated/{csid}.npz')['sha256']
|
||||
registry = build_registry(full, plan, nodes=nodes, populations=populations, population_binding_sha=population_binding_sha,
|
||||
regsha=registration_sha256, input_hashes=input_hashes)
|
||||
authority = dict(schema=G.AUTHORITY_SCHEMA, registry_sha256=G.descriptor_sha256(registry),
|
||||
verification_receipt_sha256=sha(final_ledger), execution_inventory_sha256=inventory_sha,
|
||||
population_binding_sha256=population_binding_sha)
|
||||
result = scientific_reports(probes, arms, registry=registry, authority=authority, nodes=nodes, populations=populations, load_state=load_state)
|
||||
require(len(seen_receipts) == 3920, 'Not every independently executed probe was analyzed')
|
||||
result['legacy_H'] = legacy_audit(result['cells'], gates['H_mapping'])
|
||||
return dict(schema='normal-scientific-analysis-v1', status='CONDITIONAL-PENDING-OUTER-INTEGRITY',
|
||||
registration_sha256=registration_sha256, normal_plan_sha256=plan['payload_sha256'], registry=registry, authority=authority,
|
||||
analysis=result, analyzed_probe_calls=3920, curve_points=1960, consumed_file_count=len(reader.seen),
|
||||
subsequent_assays_status='NOT-RUN', subsequent_assays_authorized=False, candidate_generated=False,
|
||||
learning_pass_claimed=False, scientific_learning_pass_claimed=False, data_backed_claimed=False,
|
||||
external_full_tree_anatomy_historical_integrity_verified_here=False,
|
||||
retained_raw_evidence='original state and receipt files; terminal raw metric vectors recomputable, not duplicated in report')
|
||||
@@ -0,0 +1,199 @@
|
||||
"""Pure normal-only adapter of the AO-pinned, master-20260930 inventory.
|
||||
|
||||
No sampling, brain execution, file writes, biological identity certification,
|
||||
or execution authorization. Import reads and SHA-checks six frozen sources.
|
||||
The trial argument must reproduce the ORIGINAL AO saved-file bytes under its
|
||||
documented JSON encoding. The evaluation argument is a new exact expansion of
|
||||
the old pinned policy, NOT an independently archived AO evaluation artifact.
|
||||
Physical inputs, actual DAN mapping, checkpoints, model and process receipts
|
||||
remain the registering executor's responsibility. No scientific gate changes.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import builtins
|
||||
from collections import Counter
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import types
|
||||
|
||||
|
||||
SCHEMA = "normal-conditioning-plan-v1"
|
||||
MASTER = 20260930
|
||||
AO_TRIAL_FILE_SHA256 = "a7bda850ee87df4d9f647994e1a1a4074dfea5793184edb1822ab3d8c02e8216"
|
||||
AO_REGISTRATION_SHA256 = "9e2ed05879ce279da7dc0b4cac09a44d67665c230b56db94e2ca39c645bdc250"
|
||||
AP_REGISTRATION_SHA256 = "02a03b536a9f14196ad4b92fa9565b592732c6c863e72eeaee89b3b0ea8ed37d"
|
||||
AO_TRIAL_PATH = "/data/digital-drosophila/experiments/phase4ao-conditioning-interface/protocol/full-trial-plan.json"
|
||||
FROZEN_DIRECTORY = Path(__file__).resolve().parent.parent / "olfactory-conditioning-lab-v1"
|
||||
SOURCE_PINS = {
|
||||
"seed_registry.py": "0da033b132095ec3087b5d9f64e53c2e391fa50ab0b7653b31296eeb84799b7e",
|
||||
"trial_plan.py": "6fed3f494d075339a7e5b001d43b2598640b189e038952fbd4d41200bacac587",
|
||||
"evaluation_plan.py": "991c813ff3322b230947f302b12b04ec382c3b632817f94b698101e4b17efa7d",
|
||||
"evaluation_policy.py": "21331a9ff3567dc6f6399e16bb91ef486d74231f5db51799beb6dd1bf71d022b",
|
||||
"PROTOCOL_DRAFT.md": "8ebecb1f3d012ddc29a1cb727269dd277629c53565e09978bf9dbf7140cb8508",
|
||||
"EVALUATION_POLICY_DRAFT.md": "a84170a61564715a1532f20df4c6a330f0f9725c383db48b8f3e1a4b5fba0bc8",
|
||||
}
|
||||
|
||||
|
||||
def _require(condition, message):
|
||||
if not condition:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def _canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(",", ":"),
|
||||
ensure_ascii=False, allow_nan=False)
|
||||
|
||||
|
||||
def _sha(value):
|
||||
return hashlib.sha256(_canonical(value).encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def _load_frozen():
|
||||
"""Private module graph; never change sys.path or ordinary module caches."""
|
||||
sources = {}
|
||||
for filename, expected in SOURCE_PINS.items():
|
||||
raw = (FROZEN_DIRECTORY / filename).read_bytes()
|
||||
_require(hashlib.sha256(raw).hexdigest() == expected,
|
||||
"Frozen source pin mismatch: " + filename)
|
||||
sources[filename] = raw
|
||||
modules = {}
|
||||
ordinary_import = builtins.__import__
|
||||
|
||||
def private_import(name, globals=None, locals=None, fromlist=(), level=0):
|
||||
if level == 0 and name in modules:
|
||||
return modules[name]
|
||||
return ordinary_import(name, globals, locals, fromlist, level)
|
||||
|
||||
for name in ("seed_registry", "trial_plan", "evaluation_plan", "evaluation_policy"):
|
||||
module = types.ModuleType("_normal_frozen_" + name)
|
||||
module.__file__ = str(FROZEN_DIRECTORY / (name + ".py"))
|
||||
module.__dict__["__builtins__"] = dict(vars(builtins), __import__=private_import)
|
||||
exec(compile(sources[name + ".py"], module.__file__, "exec"), module.__dict__)
|
||||
modules[name] = module
|
||||
return modules
|
||||
|
||||
|
||||
_FROZEN = _load_frozen()
|
||||
|
||||
|
||||
def _validate_original_trial(trial):
|
||||
_require(type(trial) is dict and set(trial) ==
|
||||
{"plan", "seed_manifest", "budget", "payload_sha256"}, "Full original trial payload required")
|
||||
_require(type(trial["plan"]["master"]) is int and trial["plan"]["master"] == MASTER,
|
||||
"Original AO master is fixed; no seed selection")
|
||||
# This is the exact LF serialization used by AO engineering_prepare.save.
|
||||
# Its registered file pin is stronger than reconstructing with a new seed.
|
||||
encoded = json.dumps(trial, sort_keys=True, indent=2, ensure_ascii=False,
|
||||
allow_nan=False) + "\n"
|
||||
_require(hashlib.sha256(encoded.encode("utf-8")).hexdigest() == AO_TRIAL_FILE_SHA256,
|
||||
"Trial does not reproduce the AO registered full-trial-plan file")
|
||||
_require(_sha({k: v for k, v in trial.items() if k != "payload_sha256"}) ==
|
||||
trial["payload_sha256"], "Original trial self-hash mismatch")
|
||||
|
||||
|
||||
def _expand_validated_trial(trial):
|
||||
# Private frozen assembly is safe AFTER the exact archived-file pin above;
|
||||
# avoid the old public APIs' redundant 68,000-epoch trial reconstruction.
|
||||
policy = _FROZEN["evaluation_policy"]._assemble(trial)
|
||||
return _FROZEN["evaluation_plan"]._assemble(trial, policy["config"])
|
||||
|
||||
|
||||
def expand_pinned_evaluation(full_trial_payload):
|
||||
"""Expand the fixed historical policy; no new choices or sampled inputs."""
|
||||
_validate_original_trial(full_trial_payload)
|
||||
return _expand_validated_trial(full_trial_payload)
|
||||
|
||||
|
||||
def build_normal_plan(full_trial_payload, full_evaluation_payload):
|
||||
"""Return 33,920 ordered tasks; caller supplies both complete authorities."""
|
||||
trial, evaluation = full_trial_payload, full_evaluation_payload
|
||||
_validate_original_trial(trial)
|
||||
expected_evaluation = _expand_validated_trial(trial)
|
||||
_require(_canonical(evaluation) == _canonical(expected_evaluation),
|
||||
"Evaluation must exactly expand the AO-pinned evaluation policy")
|
||||
snapshots = {(s["block_id"], s["arm"], s["completed_epochs"]): s
|
||||
for s in evaluation["snapshots"] if s["assay"] == "normal"}
|
||||
probes = {(p["snapshot_id"], p["cue"]): p
|
||||
for p in evaluation["probes"] if p["assay"] == "normal"}
|
||||
tasks, inputs, blocks = [], [], []
|
||||
for block in trial["plan"]["blocks"]:
|
||||
common = dict(block_id=block["block_id"], mode=block["mode"], dan_type=block["dan_type"],
|
||||
compartment_verbatim=block["compartment_verbatim"],
|
||||
reinforced_cue=block["initial_reinforced_cue"], replicate=block["replicate"],
|
||||
assay="normal", steps=1200, artifact_validation_required=True)
|
||||
blocks.append(dict(common, DAN_target_binding=block["DAN_target_binding"]))
|
||||
for cue in ("A", "B"):
|
||||
sid = block["block_id"] + "/normal/paired/checkpoint-00"
|
||||
inputs.append(dict(block_id=block["block_id"], cue=cue, **probes[(sid, cue)]["input"]))
|
||||
suite = next(s for s in block["suites"] if s["assay"] == "normal")
|
||||
for arm in suite["arms"]:
|
||||
name = arm["arm"]
|
||||
delta = dict(arm["delta_start"])
|
||||
|
||||
def append_probes(completed):
|
||||
snapshot = snapshots.get((block["block_id"], name, completed))
|
||||
if snapshot is None:
|
||||
return
|
||||
_require(snapshot["delta_source"] == delta, "Snapshot delta dependency differs")
|
||||
for cue in ("A", "B"):
|
||||
recipe = probes[(snapshot["snapshot_id"], cue)]
|
||||
tasks.append(dict(common, kind="probe", arm=name, task_id=recipe["probe_id"],
|
||||
probe_id=recipe["probe_id"], snapshot_id=snapshot["snapshot_id"],
|
||||
checkpoint=snapshot["checkpoint"], completed_epochs=completed,
|
||||
evaluation_input_id=recipe["input"]["input_id"], delta_dependency=dict(delta),
|
||||
delta_output_id=None, neural_state_policy="common_frozen_reset_independent_probe",
|
||||
carry_between_epochs=[], original_E_required=False, cpu_validation_required=False,
|
||||
feedback_to_training_or_idle=False, recipe=recipe, snapshot_binding=snapshot,
|
||||
source_binding=dict(payload_sha256=evaluation["payload_sha256"],
|
||||
record_id=recipe["probe_id"], record_sha256=_sha(recipe))))
|
||||
|
||||
append_probes(0)
|
||||
for completed, epoch in enumerate(arm["epochs"], 1):
|
||||
tasks.append(dict(common, kind="train", arm=name, task_id=epoch["epoch_id"],
|
||||
epoch_id=epoch["epoch_id"], epoch_index=epoch["epoch_index"],
|
||||
delta_dependency=dict(delta), delta_output_id=epoch["epoch_id"] + "/delta-after",
|
||||
neural_state_policy=epoch["initial_neural_state"],
|
||||
carry_between_epochs=list(arm["carry_between_epochs"]),
|
||||
original_E_required=True, cpu_validation_required=True,
|
||||
feedback_to_training_or_idle=True, recipe=epoch,
|
||||
source_binding=dict(payload_sha256=trial["payload_sha256"],
|
||||
record_id=epoch["epoch_id"], record_sha256=_sha(epoch))))
|
||||
delta = dict(kind="epoch_delta_after", source=epoch["epoch_id"] + "/delta-after")
|
||||
append_probes(completed)
|
||||
counts = Counter(row["kind"] for row in tasks)
|
||||
_require(counts == {"train": 30000, "probe": 3920} and len(inputs) == 80 and len(blocks) == 40,
|
||||
"Normal inventory changed")
|
||||
_require(len({t["task_id"] for t in tasks}) == len(tasks), "Task IDs must be unique")
|
||||
result = dict(schema=SCHEMA, master=MASTER, assay="normal", blocks=blocks,
|
||||
tasks=tasks, evaluation_inputs=inputs,
|
||||
inventory=dict(blocks=40, training_replicates_per_cell=5, arms_per_block=7,
|
||||
nominal_reinforcements=50, checkpoints=[0, 1, 2, 5, 10, 20, 50],
|
||||
train_calls=30000, probe_calls=3920, brain_calls=33920,
|
||||
original_E_calls=30000, training_cpu_validation_calls=30000,
|
||||
brain_steps=40704000, biological_seconds=4070.4, evaluation_inputs=80,
|
||||
baseline_execution="execute_each_snapshot", baseline_output_deduplication=False),
|
||||
provenance=dict(trial_payload_sha256=trial["payload_sha256"],
|
||||
seed_manifest_sha256=trial["seed_manifest"]["payload_sha256"],
|
||||
evaluation_payload_sha256=evaluation["payload_sha256"],
|
||||
evaluation_config_sha256=evaluation["config_sha256"],
|
||||
ao_trial_file_sha256=AO_TRIAL_FILE_SHA256, ao_trial_path=AO_TRIAL_PATH,
|
||||
ao_registration_sha256=AO_REGISTRATION_SHA256, ap_registration_sha256=AP_REGISTRATION_SHA256,
|
||||
frozen_source_sha256=SOURCE_PINS,
|
||||
evaluation_authority="exact expansion of AO-pinned policy; not a historical saved evaluation artifact",
|
||||
external_inputs_mapping_processes_and_physical_source_files_verified=False),
|
||||
execution_authorized=False, inputs_generated=False, new_seed_streams=0,
|
||||
learning_pass_claimed=False, subsequent_assays_included=False)
|
||||
result["payload_sha256"] = _sha(result)
|
||||
# No returned nested structure aliases either caller argument or module pins.
|
||||
return json.loads(_canonical(result))
|
||||
|
||||
|
||||
def validate_normal_plan(payload, full_trial_payload, full_evaluation_payload):
|
||||
"""Fail closed even if a modified plan has been given a fresh self-hash."""
|
||||
_require(type(payload) is dict and "payload_sha256" in payload, "Normal payload required")
|
||||
_require(_sha({k: v for k, v in payload.items() if k != "payload_sha256"}) ==
|
||||
payload["payload_sha256"], "Normal plan self-hash mismatch")
|
||||
expected = build_normal_plan(full_trial_payload, full_evaluation_payload)
|
||||
_require(_canonical(payload) == _canonical(expected), "Normal plan exact reconstruction mismatch")
|
||||
return True
|
||||
@@ -0,0 +1,205 @@
|
||||
"""Register only normal acquisition; never sample inputs or execute a brain.
|
||||
|
||||
Prior sealed files stay read-only. Complete historical integrity is checked at
|
||||
the phase boundary; each trial rehashes its actual runtime dependency closure,
|
||||
not every historical engineering result. No source or budget changes after
|
||||
registration. Outcome files have no invented pre-outcome hashes.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import argparse
|
||||
import copy
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from normal_io import *
|
||||
import normal_plan as PLAN
|
||||
|
||||
AQ_EXP = ROOT/'experiments/phase4aq-conditioning-execution'
|
||||
AP_EXP = ROOT/'experiments/phase4ap-conditioning-interface-v2'
|
||||
AO_EXP = ROOT/'experiments/phase4ao-conditioning-interface'
|
||||
AQ_ANCHORS = {
|
||||
'protocol/preregistered.json':'dad0ba33ded8c6725662c419525ef4185a6ff169042a402c18d0bd760dad7358',
|
||||
'manifest.json':'2dc0feca75f718f2ee0d7c9240da503221823573fd25f1344d2fd97d97eb2db7',
|
||||
'audit/final-status.json':'dcbb58f296bd0d51e3c8757f0c45dd5585b3a76f8c2a0b5881f4c14076721882',
|
||||
}
|
||||
H_ANCHORS = {
|
||||
'audit/phase4h.py':'28bb2ab7c4c95af3d95b0bf0bc45a5a9bea791996c59ce296ec66b71e01b1695',
|
||||
'mappings/mbon-to-downstream-actual-edges.parquet':'76bac27c50cec41c48fd6414bcef5a6e270753ac4062b92537f38226018e9278',
|
||||
'manifests/checksums.sha256':'1ea0394fd0477bb40d656ed0854108964f3809d633b5561bed9de43cda630ba1',
|
||||
'manifests/manifest.json':'d1f187f164f7775a1a02fff259c8f5e31ae035929d808c3876cfc0013d19c73c',
|
||||
}
|
||||
|
||||
# Exact arrays consumed by the pinned isolated worker, not every reference file
|
||||
# colocated in its graph/APL directories. Tests compare these to that worker.
|
||||
GRAPH_FILES = ('nodes.npy', 'edge_id.npy', 'src.npy', 'dst.npy', 'signed_raw.npy', 'ptr.npy', 'weights.npy')
|
||||
APL_FILES = ('input_matrix.npy', 'output_matrix.npy', 'kc_globals.npy', 'apl_globals.npy')
|
||||
|
||||
def runtime_array_paths(template):
|
||||
return {str(Path(template['graph_dir'])/name) for name in GRAPH_FILES} | {
|
||||
str(Path(template['apl_bundle_dir'])/name) for name in APL_FILES} | {template['coefficients_path']}
|
||||
|
||||
def readout_populations(population_file):
|
||||
import numpy as np
|
||||
import pyarrow.parquet as pq
|
||||
h=ROOT/'experiments/phase4h-dopamine-plasticity'
|
||||
verify({str(h/p):s for p,s in H_ANCHORS.items()})
|
||||
rows=pq.read_table(h/'mappings/mbon-to-downstream-actual-edges.parquet',columns=['target_neuron_idx'])['target_neuron_idx'].to_numpy()
|
||||
require(rows.dtype==np.int32 and len(rows)==39279 and np.all((rows>=0)&(rows<166700)), 'Original H endpoint schema differs')
|
||||
old=npz(population_file)
|
||||
result={k:old[k] for k in ('MBON','MBON01','MBON12')}
|
||||
result['legacyDownstream']=np.unique(rows).astype(np.int32)
|
||||
result['nonMBONDownstream']=np.setdiff1d(result['legacyDownstream'],result['MBON'])
|
||||
require(not len(np.setdiff1d(result['MBON'],result['legacyDownstream'])),'H downstream no longer includes all MBON')
|
||||
hashes={k:hashlib.sha256(v.tobytes()).hexdigest() for k,v in result.items()}
|
||||
require(hashes['legacyDownstream']=='ce9edbb56854be8f6891bfb83559dd7529c70acac6867864947f32f933175dbc' and
|
||||
hashes['nonMBONDownstream']=='01e3fbdde8bf2558665f142cdf546d8b89b4898427b90e2f4368f21f4e241a7f',
|
||||
'Actual H readout membership changed')
|
||||
return result,dict(source_sha256={str(h/p):s for p,s in H_ANCHORS.items()},
|
||||
original_populations=pin(population_file),definition='unique actual H MBON-edge target_neuron_idx, int32; no plastic/active subset',
|
||||
nonMBON_definition='exact set difference legacyDownstream minus full anatomical MBON',
|
||||
counts={k:len(v) for k,v in result.items()},raw_membership_sha256=hashes,
|
||||
historical_current_model_source_used=False,original_sealed_audit_source_used=True)
|
||||
|
||||
def historical_integrity():
|
||||
verify({str(AQ_EXP/p):s for p,s in AQ_ANCHORS.items()})
|
||||
ar = read(AQ_EXP/'protocol/preregistered.json')
|
||||
verify(ar['source_sha256'])
|
||||
# This function is executed in a separate preparation/integrity CPU process.
|
||||
for p in (AQ, AP, LAB): sys.path.insert(0,str(p))
|
||||
old = load_source('_normal_previous_integrity',AQ/'prepare_execution.py',ar['source_sha256'][str(AQ/'prepare_execution.py')])
|
||||
prior = old.integrity()
|
||||
helper = load_source('_normal_AQ_seal_reader', MODEL.parent/'pn-recruitment-audit-v1/publication.py',
|
||||
'7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016')
|
||||
sealed = helper.verify_seal(AQ_EXP)
|
||||
require(read(AQ_EXP/'audit/final-status.json')['status'] ==
|
||||
'PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING','AQ gate differs')
|
||||
return dict(complete=True,prior=prior,AQ=sealed,old_experiments_reexecuted=False,
|
||||
frozen_five_reexecuted=False,scope='actual historical seal bytes reverified, preserved numerical evidence; not a new numerical trial')
|
||||
|
||||
def resource_policy():
|
||||
"""Engineering ceiling, not a measured all-condition forecast or stop-for-success."""
|
||||
return dict(root=str(EXP),output_cap_bytes=256*1024**3,minimum_free_reserve_bytes=100*1024**3,
|
||||
child_timeout_seconds=1800,workflow_timeout_seconds=21*86400,max_uniform_draws=10_000_000,
|
||||
next_child_headroom_bytes=4*1024**3,
|
||||
execution='serial_single_4090',no_automatic_retry=True,
|
||||
forecast_scope='rough planning arithmetic from one AQ warm training cycle and one probe; not condition-complete measurement',
|
||||
AQ_measured_training_cycle_seconds=24.771224757998425,AQ_measured_probe_seconds=10.394962482001574,
|
||||
AQ_linear_wall_scenario_seconds=30000*24.771224757998425+3920*10.394962482001574,
|
||||
uncertainties=['startup and materialization','event-dependent output size','all control/DAN/odor activity',
|
||||
'ledger growth','shared service contention','final full integrity audit'],
|
||||
cap_or_timeout_policy='preserve all outputs, stop incomplete; no shortening epochs or selecting favorable outcomes')
|
||||
|
||||
def prepare():
|
||||
require(sys.dont_write_bytecode and unlinked(EXP).is_dir() and not any(EXP.iterdir()), 'Exact new empty EXP and -B required')
|
||||
files=sorted(MODEL.iterdir())
|
||||
require(files and all(p.is_file() and not p.is_symlink() and p.suffix in ('.py','.md') for p in files), 'Source-only model directory')
|
||||
sources={str(p):digest(p) for p in files}
|
||||
commit=subprocess.check_output(['git','-C',str(ROOT),'rev-parse','HEAD']).decode().strip()
|
||||
for path,sha in sources.items():
|
||||
blob=subprocess.check_output(['git','-C',str(ROOT),'show',commit+':'+Path(path).relative_to(ROOT).as_posix()])
|
||||
require(hashlib.sha256(blob).hexdigest()==sha, 'Uncommitted source '+path)
|
||||
budget=resource_policy()
|
||||
budget['registered_utc']=datetime.now(timezone.utc).isoformat()
|
||||
budget['not_after_utc']=(datetime.now(timezone.utc)+timedelta(seconds=budget['workflow_timeout_seconds'])).isoformat()
|
||||
require(shutil.disk_usage(EXP).free >= budget['output_cap_bytes']+budget['minimum_free_reserve_bytes'], 'Insufficient reserved capacity')
|
||||
for name in ('protocol/source-snapshot','inputs/static','jobs','cases','runs','updates','validation','results','receipts','logs','audit','regression'):
|
||||
unlinked(EXP/name).mkdir(parents=True)
|
||||
tests=subprocess.run([sys.executable,'-B',str(MODEL/'run_cpu_tests.py'),'--output',str(EXP/'audit/cpu-tests.json')],
|
||||
capture_output=True,text=True,timeout=1800,env={**dict(__import__('os').environ),'CUDA_VISIBLE_DEVICES':''})
|
||||
save(EXP/'audit/cpu-tests.process.json',dict(exit_code=tests.returncode,stdout=tests.stdout,stderr=tests.stderr,
|
||||
actual_parent_observation=True))
|
||||
require(tests.returncode==0 and read(EXP/'audit/cpu-tests.json')['pass_all'] is True,
|
||||
'CPU/source tests failed; no sampler or brain started')
|
||||
# Old integrity readers may own a private R/C module graph. Keep them in an
|
||||
# exec-isolated CPU process, never the table/registration interpreter.
|
||||
integrity_command=[sys.executable,'-B',str(MODEL/'normal_prepare.py'),'integrity',
|
||||
'--output',str(EXP/'regression/integrity-before.json')]
|
||||
checked=subprocess.run(integrity_command,capture_output=True,text=True,timeout=1800,
|
||||
env={**dict(__import__('os').environ),'CUDA_VISIBLE_DEVICES':''})
|
||||
save(EXP/'regression/integrity-before.process.json',dict(argv=integrity_command,exit_code=checked.returncode,
|
||||
stdout=checked.stdout,stderr=checked.stderr,actual_parent_observation=True))
|
||||
require(checked.returncode==0,'Historical integrity child failed; preserve artifacts')
|
||||
before=read(EXP/'regression/integrity-before.json');require(before['complete'] is True,'Integrity child incomplete')
|
||||
aq=read(AQ_EXP/'protocol/preregistered.json')
|
||||
full=read(PLAN.AO_TRIAL_PATH)
|
||||
require(digest(PLAN.AO_TRIAL_PATH)==PLAN.AO_TRIAL_FILE_SHA256,'Original full plan pin differs')
|
||||
evaluation=PLAN.expand_pinned_evaluation(full)
|
||||
plan=PLAN.build_normal_plan(full,evaluation)
|
||||
from normal_inputs import derive_rates, inventory_from_plan, PINS, dependencies
|
||||
rate_tables,rate_audit=derive_rates()
|
||||
inputs=inventory_from_plan(plan)
|
||||
template_path=AP_EXP/'cases/D1--reference--epoch-001/spec.json'
|
||||
authority_path=AP_EXP/'jobs/D1--reference--epoch-001.authority.json'
|
||||
template=read(template_path); epoch=read(authority_path)
|
||||
pinned={**aq['input_sha256'],**aq['source_sha256'],**aq['prepared_file_sha256']}
|
||||
for path in (template_path,authority_path,AO_EXP/'inputs/static/populations.npz'):
|
||||
require(str(path) in pinned and digest(path)==pinned[str(path)],'Original template/population not pinned')
|
||||
for path in sources:
|
||||
with Path(path).open('rb') as i,(EXP/'protocol/source-snapshot'/Path(path).name).open('xb') as o:shutil.copyfileobj(i,o)
|
||||
save(EXP/'protocol/normal-plan.json',plan)
|
||||
save(EXP/'protocol/evaluation-policy.json',evaluation['config'])
|
||||
save(EXP/'protocol/input-inventory.json',inputs)
|
||||
save(EXP/'protocol/case-template.json',template)
|
||||
# Freeze scientific predicates before any new CS sample or outcome.
|
||||
gate_sources={str(AQ/'learning_gates.py'):'8ae9bcb77fe14dbdda164f86ffdbfc1e2976be752766ef526777577223b4dd99',
|
||||
str(LAB/'metrics.py'):'47319e21db3c8b030b1bafbf0703cd86fb588d23bb29436accbacdba73d08c3c'}
|
||||
verify(gate_sources)
|
||||
save(EXP/'protocol/gates.json',dict(source_sha256=gate_sources,all_eight_cells_required=True,
|
||||
same_replicate_conjunction_at_least=3,training_replicates=5,terminal_checkpoint=50,
|
||||
normal_failure_prevents_followups=True,intermediate_checkpoints_cannot_rescue_terminal=True,
|
||||
downstream_policy='nonMBONDownstream-pre-outcome-operationalization-v1',
|
||||
H_mapping='each-DAN-control-source-separately-both-pass-v1',
|
||||
physiological_and_matched_energy_not_pooled=True,unknown_compartments_not_guessed=True))
|
||||
save(EXP/'inputs/static/rate-audit.json',rate_audit)
|
||||
for key,table in rate_tables.items():save_npz(EXP/f'inputs/static/{key}.npz',table)
|
||||
populations,pop_audit=readout_populations(AO_EXP/'inputs/static/populations.npz')
|
||||
save_npz(EXP/'inputs/static/readout-populations.npz',populations)
|
||||
save(EXP/'inputs/static/readout-population-binding.json',pop_audit)
|
||||
# Actual consumed neural dependency closure, all inherited byte pins.
|
||||
required=runtime_array_paths(template)
|
||||
require(required <= pinned.keys(), 'Consumed runtime arrays missing inherited pins: '+str(sorted(required-pinned.keys())))
|
||||
original_sources={p:s for p,s in epoch['frozen_inputs'].items() if p.startswith(str(ROOT/'models/male-cns-lif/') )
|
||||
and ('author-' in p or 'apl-timing-lab-v1/' in p)}
|
||||
runtime={p:pinned[p] for p in required}
|
||||
runtime.update(original_sources)
|
||||
roles={k:v for k,v in epoch['files'].items() if k not in ('spec','requests','state','overlay_before','overlay_manifest_before')}
|
||||
runtime.update({v['path']:v['sha256'] for v in roles.values()})
|
||||
save(EXP/'protocol/epoch-template.json',dict(schema=epoch['schema'],files=roles,frozen_inputs=runtime))
|
||||
static={str(LAB/n):s for n,s in {**PLAN.SOURCE_PINS,**PINS}.items()}
|
||||
static.update({str(ROOT/p):s for p,s in rate_audit['original_source_sha256'].items()})
|
||||
external={**runtime,**static,**gate_sources,**pop_audit['source_sha256'],**{str(AQ_EXP/p):s for p,s in AQ_ANCHORS.items()},
|
||||
str(PLAN.AO_TRIAL_PATH):PLAN.AO_TRIAL_FILE_SHA256,str(AP/'isolated_workers.py'):AP_SHA,
|
||||
str(authority_path):pinned[str(authority_path)],str(template_path):pinned[str(template_path)],
|
||||
str(AO_EXP/'inputs/static/populations.npz'):pinned[str(AO_EXP/'inputs/static/populations.npz')],
|
||||
str(AQ/'validate_update_cpu.py'):aq['source_sha256'][str(AQ/'validate_update_cpu.py')]}
|
||||
for name in ('conditioning_epoch.py','conditioning_preflight_compare.py','engineering_compare.py'):
|
||||
path=str(LAB/name);require(path in pinned,'Missing original verifier source pin');external[path]=pinned[path]
|
||||
zero=aq['initial_overlay']
|
||||
external.update({p:digest(p) for p in zero.values()})
|
||||
verify(external)
|
||||
prepared={p:row['sha256'] for p,row in inventory(EXP).items()}
|
||||
reg=dict(schema='normal-conditioning-registration-v1',scientific_scope='normal-acquisition-only',
|
||||
subsequent_assays_authorized=False,source_code_commit=commit,source_sha256=sources,input_sha256=external,
|
||||
static_input_sha256=static,runtime_input_sha256=runtime,prepared_sha256=prepared,budget=budget,
|
||||
initial_overlay=zero,population_file=str(AO_EXP/'inputs/static/populations.npz'),
|
||||
readout_population_file=str(EXP/'inputs/static/readout-populations.npz'),
|
||||
readout_population_binding_file=str(EXP/'inputs/static/readout-population-binding.json'),
|
||||
original_full_trial_plan=pin(PLAN.AO_TRIAL_PATH),normal_inventory=plan['inventory'],
|
||||
evidence_scope='AQ validates exact interface, not learning; this new registration admits actual normal outcomes',
|
||||
brain_parameters_changed=False,learning_success_claimed=False,
|
||||
execution_order='original fixed block/arm order; actual A/B baseline each arm; no outcome selection',
|
||||
biological_hypotheses='D18 branch; PAM15/PPL103 compartment hypotheses only, not all-PAM/PPL functional assignment',
|
||||
historical_integrity_scope=before['scope'],failure_policy='stop preserve partials, never auto retry',
|
||||
administrative_supervisor_directory=str(ROOT/'logs/phase4ar-normal-conditioning'),
|
||||
supervisor_logging_scope='outside immutable EXP ledger; real top-level exit and logs must be included by final outer auditor',
|
||||
full_plan_in_old_frozen_location=True,future_artifact_hashes_fabricated=False)
|
||||
save(EXP/'protocol/preregistered.json',reg)
|
||||
return digest(EXP/'protocol/preregistered.json')
|
||||
|
||||
if __name__=='__main__':
|
||||
p=argparse.ArgumentParser();p.add_argument('mode',choices=('prepare','integrity'));p.add_argument('--output')
|
||||
a=p.parse_args()
|
||||
if a.mode=='prepare':print('REGISTRATION_SHA256',prepare(),flush=True)
|
||||
else:
|
||||
require(a.output,'Exclusive report path required');save(a.output,historical_integrity())
|
||||
@@ -0,0 +1,341 @@
|
||||
"""Serial normal conditioning. Original R/E/U executables stay unchanged.
|
||||
|
||||
Every fresh brain trial is followed by original E and independent original-U
|
||||
recomputation in separate exec processes. Probes never run E or feed back.
|
||||
Only fully committed steps may be skipped on explicit resume. An uncommitted
|
||||
start, failed child or partial task always stops; no inferred OS exit or retry.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import argparse
|
||||
import copy
|
||||
from datetime import datetime, timezone
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import numpy as np
|
||||
from normal_io import *
|
||||
from append_ledger import Ledger
|
||||
|
||||
def registration(expected):
|
||||
require(digest(EXP/'protocol/preregistered.json')==expected,'Registration hash differs')
|
||||
reg=read(EXP/'protocol/preregistered.json')
|
||||
require(reg['schema']=='normal-conditioning-registration-v1' and reg['scientific_scope']=='normal-acquisition-only'
|
||||
and reg['subsequent_assays_authorized'] is False,'Wrong authority')
|
||||
verify(reg['source_sha256']);verify(reg['input_sha256']);verify(reg['prepared_sha256'])
|
||||
return reg
|
||||
|
||||
def derive_spec(original,task,*,budget_root,output_cap):
|
||||
require(original['kind']=='fullgraph' and original['dt_ms']==.1 and original['apl_delay_steps']==18 and
|
||||
original['precision']=='float64' and original['apl_precision']=='float32' and original['record_history'] is False,
|
||||
'Original fixed D18 spec required')
|
||||
require(task['steps']==1200 and task['kind'] in ('train','probe'),'Wrong task')
|
||||
allowed=('validation_cohort','odor_index','expected_external_events','training','cs_input_seed','cs_input_seed_bits',
|
||||
'seed_scope','odor_id','odor_name','source_panel_row','source_panel_split','rate_sum_hz','target_count',
|
||||
'expected_CS_requests','CS_window','outer_epoch_id','outer_arm','outer_protocol')
|
||||
result={k:copy.deepcopy(v) for k,v in original.items() if k not in allowed}
|
||||
result.update(name=task_key(task),steps=1200,duration_ms=120.,max_steps=1200,budget_root=str(budget_root),
|
||||
output_budget_bytes=output_cap,mode=task['mode'],within_trial_weight_updates=False,
|
||||
outer_protocol='normal-acquisition-v1',outer_task_id=task['task_id'],outer_arm=task['arm'])
|
||||
# The frozen independent reset-control seed is retained, not derived from CS.
|
||||
require(result['seed']==original['seed'],'Reset seed changed')
|
||||
return result
|
||||
|
||||
def compose_requests(cs,dan,task,inputs):
|
||||
require(task['steps']==1200,'Only normal120ms tasks')
|
||||
if task['kind']=='probe':
|
||||
recipe=task['recipe'];require(recipe['US_requested'] is False and recipe['D_command']==0 and
|
||||
recipe['weight_updates_enabled'] is False and task['feedback_to_training_or_idle'] is False,'Probe command differs')
|
||||
nodes=np.empty(0,np.int32)
|
||||
else:
|
||||
recipe=task['recipe'];us=recipe['us']
|
||||
require(us['nominal_slot_tick']==900 and us['rng_seed'] is None and us['rng_draws']==0 and
|
||||
((us['requested'] is True and us['tick']==900) or (us['requested'] is False and us['tick'] is None)),
|
||||
'Scheduled artificial US differs')
|
||||
require(recipe['D_command']==(1. if us['requested'] and task['arm']!='d_zero' else 0.) and
|
||||
recipe['update_enabled'] is (task['arm']!='frozen'),'D/update command differs')
|
||||
require(dan.dtype==np.int32 and dan.ndim==1 and len(dan) in (2,4) and np.all(dan[1:]>dan[:-1]),'Bound DAN IDs required')
|
||||
nodes=dan.copy() if us['requested'] else np.empty(0,np.int32)
|
||||
us=dict(tick=np.full(len(nodes),900,np.int32),neuron_idx=nodes)
|
||||
composed=inputs.merge_requests(cs,us,steps=1200,conflict_policy='error')
|
||||
return composed,us
|
||||
|
||||
class Workflow:
|
||||
def __init__(self,sha):
|
||||
self.sha=sha;self.reg=registration(sha);self.start=time.perf_counter()
|
||||
require(not (EXP/'audit/stopped.json').exists() and not (EXP/'manifest.json').exists(), 'Stopped or sealed phase cannot run')
|
||||
self.plan=read(EXP/'protocol/normal-plan.json');self.input_plan=read(EXP/'protocol/input-inventory.json')
|
||||
self.tasks={x['task_id']:x for x in self.plan['tasks']}
|
||||
self.h=load_source('_normal_AP_helpers',AP/'isolated_workers.py',AP_SHA)
|
||||
self.inputs=load_source('_normal_request_composer',LAB/'conditioning_inputs.py',self.reg['static_input_sha256'][str(LAB/'conditioning_inputs.py')])
|
||||
self.metric=load_source('_normal_CPU_state_validation',LAB/'metrics.py',self.reg['input_sha256'][str(LAB/'metrics.py')])
|
||||
self.nodes=np.load(Path(read(EXP/'protocol/case-template.json')['graph_dir'])/'nodes.npy',allow_pickle=False)
|
||||
self.populations=npz(self.reg['population_file'])
|
||||
initial={Path(p).relative_to(EXP).as_posix():identity(p) for p in self.reg['prepared_sha256']}
|
||||
initial['protocol/preregistered.json']=identity(EXP/'protocol/preregistered.json')
|
||||
self.ledger=Ledger(EXP,sha,initial,self.reg['budget']['output_cap_bytes'],self.reg['budget']['minimum_free_reserve_bytes'])
|
||||
status=self.ledger.inspect();require(not status['uncommitted_entry_ids'],'Uncommitted OS state unknown; no automatic retry')
|
||||
self.completed=set(status['entry_ids']);self.expected=[]
|
||||
|
||||
def basepins(self):
|
||||
return {**self.reg['runtime_input_sha256'],str(EXP/'protocol/preregistered.json'):self.sha}
|
||||
|
||||
def immutable_pin(self,path):
|
||||
path=unlinked(path);rel=path.relative_to(EXP).as_posix()
|
||||
require(rel in self.ledger._tracked and identity(path)==self.ledger._tracked[rel],
|
||||
'Consumed immutable file differs from committed bytes: '+rel)
|
||||
return dict(path=str(path),sha256=self.ledger._tracked[rel]['sha256'])
|
||||
|
||||
def budget(self):
|
||||
require(time.perf_counter()-self.start < self.reg['budget']['workflow_timeout_seconds'],'Invocation wall cap exceeded')
|
||||
require(datetime.now(timezone.utc)<datetime.fromisoformat(self.reg['budget']['not_after_utc']),
|
||||
'Registered absolute deadline exceeded; resume cannot reset wall allowance')
|
||||
require(shutil.disk_usage(EXP).free>=self.reg['budget']['minimum_free_reserve_bytes'],'Free space reserve exceeded')
|
||||
# Running totals account only committed payload, ledger and shared build.
|
||||
# Each child also gets a fresh per-child output allowance; full tree at final.
|
||||
accounting=self.ledger._budget()
|
||||
require(accounting['total_accounted_bytes']+self.reg['budget']['next_child_headroom_bytes'] <=
|
||||
self.reg['budget']['output_cap_bytes'],'No registered headroom for another complete child')
|
||||
|
||||
def launch(self,name,job,argv,outputs,*,pre_outputs=(),post=None,ap=False):
|
||||
self.expected.append(name)
|
||||
require(name not in self.completed,'Internal attempt to rerun committed job')
|
||||
self.budget()
|
||||
unlinked(EXP/'receipts'/name).mkdir()
|
||||
jobfile=EXP/f'jobs/{name}.json';save(jobfile,job);jobsha=digest(jobfile)
|
||||
argv=[*argv]
|
||||
if ap:argv+=['--job',str(jobfile),'--job-sha256',jobsha]
|
||||
start=self.ledger.begin(name,jobfile,dict(kind=job['kind']))
|
||||
stdout=EXP/f'logs/{name}.stdout.log';stderr=EXP/f'logs/{name}.stderr.log'
|
||||
process=EXP/f'receipts/{name}/process.json'
|
||||
started=time.perf_counter();rc=None;timed=False;launch_error=None
|
||||
env=dict(os.environ);env['PYTHONDONTWRITEBYTECODE']='1'
|
||||
if job['kind'] not in ('brain','sample'):env['CUDA_VISIBLE_DEVICES']=''
|
||||
with unlinked(stdout).open('xb') as out,unlinked(stderr).open('xb') as err:
|
||||
try:rc=subprocess.run(argv,cwd=MODEL,env=env,stdout=out,stderr=err,
|
||||
timeout=self.reg['budget']['child_timeout_seconds']).returncode
|
||||
except subprocess.TimeoutExpired:timed=True
|
||||
except OSError as error:launch_error=type(error).__name__+': '+str(error)
|
||||
base=dict(entry_id=name,registration_sha256=self.sha,job_sha256=jobsha,argv=argv,
|
||||
exit_code=rc,timed_out=timed,exit_observed_by_parent=rc is not None or timed,launch_error=launch_error,
|
||||
child_wall_seconds=time.perf_counter()-started,observed_utc=datetime.now(timezone.utc).isoformat(),
|
||||
stdout_sha256=digest(stdout),stderr_sha256=digest(stderr))
|
||||
try:
|
||||
require(type(rc)is int and rc==0 and not timed,'Child failed; retain outputs and stop')
|
||||
verify(job['input_sha256'])
|
||||
if ap:
|
||||
receipt=read(job['receipt_file'])
|
||||
require(receipt['schema']=='phase4ap-isolated-worker-receipt-v1' and receipt['complete'] is True and
|
||||
receipt['job_sha256']==jobsha and receipt['registration_sha256']==self.sha and
|
||||
receipt['kind']==job['kind'] and receipt['job_id']==name,'Actual child receipt differs')
|
||||
expected={**job['input_sha256'],str(jobfile):jobsha,str(AP/'isolated_workers.py'):AP_SHA,
|
||||
**{v['path']:v['sha256'] for v in job['sources'].values()}}
|
||||
require(receipt['verified_input_sha256']==expected,'Worker input closure differs')
|
||||
actual={str(Path(p).relative_to(job['output_dir'])):v['sha256'] for p,v in inventory(Path(job['output_dir'])).items()}
|
||||
require(actual==receipt['output_files_sha256'],'Worker output inventory differs')
|
||||
require(digest(job['receipt_file']+'.attempt.json')==receipt['attempt_sha256'],'Attempt changed')
|
||||
if post is not None:post()
|
||||
base.update(complete=True,end_to_end_seconds=time.perf_counter()-started)
|
||||
save(process,base)
|
||||
files=[*pre_outputs,jobfile,stdout,stderr,process]
|
||||
for p in outputs:
|
||||
p=Path(p);files.extend(Path(x) for x in inventory(p)) if p.is_dir() else files.append(p)
|
||||
outgoing={str(p):identity(p) for p in files}
|
||||
incoming={p:identity(p) for p in job['input_sha256']}
|
||||
incoming[str(jobfile)]=identity(jobfile)
|
||||
self.ledger.append(name,incoming,outgoing,dict(job_file=str(jobfile),process_receipt_file=str(process),
|
||||
observed_returncode=rc,scope='actual serial child exit and immutable artifact verification'))
|
||||
self.completed.add(name)
|
||||
print(json.dumps(dict(complete=True,entry_id=name,wall_seconds=base['end_to_end_seconds']),sort_keys=True),flush=True)
|
||||
except BaseException as error:
|
||||
if not process.exists():save(process,dict(base,complete=False,error=str(error)))
|
||||
raise
|
||||
|
||||
def input_generation(self):
|
||||
name='input-generation'
|
||||
if name in self.completed:self.expected.append(name);return
|
||||
pins={**self.reg['source_sha256'],**self.reg['static_input_sha256'],
|
||||
**{p:s for p,s in self.reg['prepared_sha256'].items() if '/inputs/static/' in p or p.endswith('/input-inventory.json')},
|
||||
str(EXP/'protocol/preregistered.json'):self.sha}
|
||||
job=dict(kind='sample',registration_sha256=self.sha,input_sha256=pins)
|
||||
def validate_sample():
|
||||
report=read(EXP/'receipts/input-generation.json')
|
||||
require(report['complete'] is True and report['registration_sha256']==self.sha and
|
||||
set(report['inputs'])==set(self.input_plan['descriptors']) and report['descriptors']==4080,
|
||||
'Incomplete original sampling inventory')
|
||||
for key,d in self.input_plan['descriptors'].items():
|
||||
f=EXP/f'inputs/generated/{key}.npz';a=EXP/f'inputs/generated/{key}.json'
|
||||
audit=read(a)
|
||||
require(audit['descriptor']==d and audit['requests_sha256']==digest(f) and
|
||||
report['inputs'][key]==dict(requests=pin(f),audit=pin(a)), 'Saved sampler binding differs')
|
||||
self.inputs.validate_requests(npz(f),1200)
|
||||
self.launch(name,job,[sys.executable,'-B',str(MODEL/'normal_inputs.py'),'--registration-sha256',self.sha],
|
||||
[EXP/'inputs/generated',EXP/'receipts/input-generation.json'],post=validate_sample)
|
||||
|
||||
def overlay(self,task):
|
||||
self.overlay_dependency_pins={}
|
||||
dependency=task['delta_dependency']
|
||||
if dependency==dict(kind='zero',source=None):return copy.deepcopy(self.reg['initial_overlay'])
|
||||
require(dependency['kind']=='epoch_delta_after' and dependency['source'].endswith('/delta-after'),'Unknown delta dependency')
|
||||
previous=self.tasks[dependency['source'][:-len('/delta-after')]]
|
||||
key=task_key(previous);require(key+'--verify' in self.completed,'Previous real E+CPU validation missing')
|
||||
result_path=EXP/f'results/{key}.json'
|
||||
def committed(path):
|
||||
checked=self.immutable_pin(path)
|
||||
self.overlay_dependency_pins[checked['path']]=checked['sha256']
|
||||
committed(result_path);record=read(result_path)
|
||||
require(record['complete'] is True and record['task']==previous and previous['kind']=='train' and
|
||||
all(previous[k]==task[k] for k in ('block_id','arm')),'Delta cannot cross unrelated branch')
|
||||
validation=Path(record['cpu_validation']['path']);committed(validation)
|
||||
require(digest(validation)==record['cpu_validation']['sha256'],'CPU receipt changed')
|
||||
valid=read(validation)
|
||||
committed(Path(record['cpu_process_receipt_path']))
|
||||
process=read(record['cpu_process_receipt_path'])
|
||||
require(process['complete'] is True and type(process['exit_code']) is int and process['exit_code']==0 and
|
||||
process['entry_id']==key+'--verify' and process['registration_sha256']==self.sha,
|
||||
'Previous CPU exit missing')
|
||||
for role,filename,field in (('overlay_file','delta-after.npz','after_overlay_sha256'),
|
||||
('overlay_manifest','overlay-manifest.json','after_manifest_sha256')):
|
||||
path=Path(record['after_overlay'][role]);committed(path)
|
||||
require(path==Path(record['update_dir'])/filename and digest(path)==valid[field],
|
||||
'Next installed delta is not the actual independently verified output')
|
||||
return copy.deepcopy(record['after_overlay'])
|
||||
|
||||
def prepare_case(self,task):
|
||||
key=task_key(task);case=unlinked(EXP/'cases'/key);case.mkdir()
|
||||
template_file=EXP/'protocol/case-template.json'
|
||||
checked=self.immutable_pin(template_file)
|
||||
self.case_dependency_pins={checked['path']:checked['sha256'],
|
||||
self.reg['population_file']:self.reg['input_sha256'][self.reg['population_file']]}
|
||||
template=read(template_file)
|
||||
spec=derive_spec(template,task,budget_root=EXP,output_cap=self.reg['budget']['output_cap_bytes'])
|
||||
csid=self.input_plan['task_inputs'][task['task_id']]
|
||||
if csid is None:cs=dict(tick=np.empty(0,np.int32),neuron_idx=np.empty(0,np.int32));cs_source=None
|
||||
else:
|
||||
cs_source=EXP/f'inputs/generated/{csid}.npz'
|
||||
audit_file=EXP/'inputs/generated'/(csid+'.json')
|
||||
for path in (cs_source,audit_file):
|
||||
checked=self.immutable_pin(path);self.case_dependency_pins[checked['path']]=checked['sha256']
|
||||
generated=read(audit_file)
|
||||
require(generated['descriptor']==self.input_plan['descriptors'][csid] and
|
||||
generated['requests_sha256']==digest(cs_source),'Saved shared CS changed')
|
||||
cs=npz(cs_source)
|
||||
combined,us=compose_requests(cs,self.populations[task['dan_type']],task,self.inputs)
|
||||
save(case/'spec.json',spec);save_npz(case/'requests.npz',combined['requests'])
|
||||
save_npz(case/'cs_requests.npz',cs);save_npz(case/'us_requests.npz',us)
|
||||
save_npz(case/'source-mask.npz',dict(source_mask=combined['source_mask']))
|
||||
save(case/'input-binding.json',dict(task_id=task['task_id'],CS_source=None if cs_source is None else pin(cs_source),
|
||||
CS_descriptor_id=csid,composition=combined['audit'],DAN_type=task['dan_type'],
|
||||
DAN_membership_sha256=hashlib.sha256(self.populations[task['dan_type']].tobytes()).hexdigest(),
|
||||
population_file=pin(self.reg['population_file']),artificial_US_not_dopamine_concentration=True))
|
||||
return case
|
||||
|
||||
def ap_job(self,name,kind,output,*,case=None,overlay=None,authority=None):
|
||||
pins=self.basepins()
|
||||
job=dict(schema='phase4ap-isolated-worker-job-v1',job_id=name,kind=kind,registration_sha256=self.sha,
|
||||
worker_sha256=AP_SHA,output_dir=str(output),receipt_file=str(EXP/f'receipts/{name}/worker.json'))
|
||||
if kind=='brain':
|
||||
pins.update(self.overlay_dependency_pins)
|
||||
pins.update(self.case_dependency_pins)
|
||||
for p in (case/'spec.json',case/'requests.npz',overlay['overlay_file'],overlay['overlay_manifest']):pins[str(p)]=digest(p)
|
||||
job.update(case_dir=str(case),build_root=str(EXP/'extension-build'),**overlay,diagnostic_mode='light',
|
||||
admission=dict(gpu_uuid=GPU,comfy_queue_urls=list(self.h.COMFY_URLS)),
|
||||
sources={n:dict(path=str(LAB/(n+'.py')),sha256=self.h.SOURCE_PINS[n]) for n in ('runtime_light','runtime_continuation')})
|
||||
else:
|
||||
auth=read(authority);pins[str(authority)]=digest(authority)
|
||||
pins.update({v['path']:v['sha256'] for v in auth['files'].values()})
|
||||
pins.update(auth['frozen_inputs']);pins[str(Path(auth['checkpoint_dir'])/'checkpoint-manifest.json')]=auth['checkpoint_manifest_sha256']
|
||||
job.update(authority_file=str(authority),authority_sha256=digest(authority),
|
||||
sources={'conditioning_epoch':dict(path=str(LAB/'conditioning_epoch.py'),sha256=self.h.SOURCE_PINS['conditioning_epoch'])})
|
||||
job['input_sha256']=pins;return job
|
||||
|
||||
def brain_verify(self,task,case,output):
|
||||
summary=read(output/'summary.json');state=npz(output/'state.npz')
|
||||
checked=self.metric.validate_state(state,nodes=self.nodes,steps=1200)
|
||||
require(summary['all_finite'] is True and summary['steps']==1200 and summary['diagnostic_mode']=='light','Nonfinite/incomplete brain')
|
||||
require(int(state['counts'].sum())==summary['total_spikes'],'Spike event/count mismatch')
|
||||
manifest=read(output/'checkpoint-manifest.json')
|
||||
for rel,sha in manifest['files_sha256'].items():require(digest(output/rel)==sha,'Checkpoint payload changed')
|
||||
return dict(complete=True,state_raw_sha256=checked['hashes'],finite=True,
|
||||
checkpoint_manifest_sha256=digest(output/'checkpoint-manifest.json'),task_id=task['task_id'])
|
||||
|
||||
def task(self,task):
|
||||
key=task_key(task);brain=key+'--brain';up=key+'--update';cpu=key+'--verify'
|
||||
planned=[brain,up,cpu] if task['kind']=='train' else [brain]
|
||||
if all(x in self.completed for x in planned):self.expected.extend(planned);return
|
||||
require(not any(x in self.completed for x in planned),'Partially completed task: preserve and inspect; no implicit replay')
|
||||
overlay=self.overlay(task);case=self.prepare_case(task);output=EXP/'runs'/key
|
||||
record=dict(schema='normal-task-result-v1',complete=True,registration_sha256=self.sha,task=task,
|
||||
checkpoint_dir=str(output),overlay_before=overlay,brain_process_receipt_path=str(EXP/f'receipts/{brain}/process.json'))
|
||||
def after_brain():
|
||||
record['brain_audit']=self.brain_verify(task,case,output)
|
||||
record['checkpoint_manifest_sha256']=digest(output/'checkpoint-manifest.json')
|
||||
# Parent process receipt is produced later and is bound by the ledger,
|
||||
# avoiding a self-reference in a result written before process exit audit.
|
||||
if task['kind']=='probe':save(EXP/f'results/{key}.json',record)
|
||||
job=self.ap_job(brain,'brain',output,case=case,overlay=overlay)
|
||||
outs=[output,Path(job['receipt_file']),Path(job['receipt_file']+'.attempt.json')]
|
||||
if task['kind']=='probe':outs.append(EXP/f'results/{key}.json')
|
||||
self.launch(brain,job,[sys.executable,'-B',str(AP/'isolated_workers.py'),'brain'],outs,
|
||||
pre_outputs=[Path(p) for p in inventory(case)],post=after_brain,ap=True)
|
||||
if task['kind']=='probe':return
|
||||
template_pin=self.immutable_pin(EXP/'protocol/epoch-template.json')
|
||||
template=read(template_pin['path']);auth=copy.deepcopy(template)
|
||||
r=task['recipe'];auth.update(epoch_id=task['task_id'],diagnostic_mode='light',checkpoint_dir=str(output),
|
||||
checkpoint_manifest_sha256=digest(output/'checkpoint-manifest.json'),
|
||||
command=dict(steps=1200,compartment=task['compartment_verbatim'],us_tick=r['us']['tick'],d_command=r['D_command'],
|
||||
frozen=not r['update_enabled'],trace_backend='torch'))
|
||||
for role,path in dict(spec=case/'spec.json',requests=case/'requests.npz',state=output/'state.npz',
|
||||
overlay_before=overlay['overlay_file'],overlay_manifest_before=overlay['overlay_manifest']).items():auth['files'][role]=pin(path)
|
||||
authority=EXP/f'jobs/{key}.authority.json';save(authority,auth);update=EXP/'updates'/key
|
||||
job=self.ap_job(up,'update',update,authority=authority)
|
||||
job['input_sha256'][template_pin['path']]=template_pin['sha256']
|
||||
for path in (EXP/f'receipts/{brain}/process.json',EXP/f'receipts/{brain}/worker.json'):
|
||||
checked=self.immutable_pin(path);job['input_sha256'][checked['path']]=checked['sha256']
|
||||
self.launch(up,job,[sys.executable,'-B',str(AP/'isolated_workers.py'),'update'],
|
||||
[update,Path(job['receipt_file']),Path(job['receipt_file']+'.attempt.json')],pre_outputs=[authority],ap=True)
|
||||
out=unlinked(EXP/'validation'/key);out.mkdir();validation=out/'validation.json'
|
||||
script=AQ/'validate_update_cpu.py';verify({str(script):self.reg['input_sha256'][str(script)]})
|
||||
pins={**job['input_sha256'],str(script):self.reg['input_sha256'][str(script)]}
|
||||
for name in ('conditioning_epoch.py','conditioning_preflight_compare.py','engineering_compare.py'):
|
||||
path=str(LAB/name);pins[path]=self.reg['input_sha256'][path]
|
||||
pins.update({p:v['sha256'] for p,v in inventory(update).items()})
|
||||
job=dict(kind='cpu_verify',registration_sha256=self.sha,input_sha256=pins,authority_file=str(authority),
|
||||
authority_sha256=digest(authority),update_dir=str(update),chain_sha256=digest(update/'chain-receipt.json'),
|
||||
receipt_file=str(validation),validator_sha256=self.reg['input_sha256'][str(script)])
|
||||
def after_cpu():
|
||||
valid=read(validation)
|
||||
require(valid['complete'] is True and valid['frozen_U_verify_receipt_recomputed'] is True and
|
||||
valid['actual_sealed_events_used'] is True and valid['after_overlay_sha256']==digest(update/'delta-after.npz') and
|
||||
valid['epoch_authority_sha256']==digest(authority),'Independent update verification differs')
|
||||
if task['arm'] in ('d_zero','frozen','cs_only'):
|
||||
require(not npz(update/'delta-after.npz')['plastic_delta_mv'].view(np.uint32).any(),'Zero-update control became nonzero')
|
||||
record.update(epoch_authority=pin(authority),update_dir=str(update),cpu_validation=pin(validation),
|
||||
after_overlay=dict(overlay_file=str(update/'delta-after.npz'),overlay_manifest=str(update/'overlay-manifest.json')),
|
||||
update_process_receipt_path=str(EXP/f'receipts/{up}/process.json'),
|
||||
cpu_process_receipt_path=str(EXP/f'receipts/{cpu}/process.json'))
|
||||
save(EXP/f'results/{key}.json',record)
|
||||
self.launch(cpu,job,[sys.executable,'-B',str(script),'--authority',str(authority),'--authority-sha256',digest(authority),
|
||||
'--update-dir',str(update),'--chain-sha256',digest(update/'chain-receipt.json'),'--receipt',str(validation)],
|
||||
[out,EXP/f'results/{key}.json'],post=after_cpu)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.input_generation()
|
||||
for task in self.plan['tasks']:self.task(task)
|
||||
report=self.ledger.final_verify(self.expected)
|
||||
require(report['pass_all'],'Final ledger coverage/integrity failed')
|
||||
save(EXP/'audit/execution-complete.json',dict(complete=True,registration_sha256=self.sha,
|
||||
inventory=self.plan['inventory'],ledger=report,learning_success_claimed=False,
|
||||
next='independent scientific analysis and frozen integrity, no subsequent assay'))
|
||||
except BaseException as error:
|
||||
if not (EXP/'audit/stopped.json').exists():save(EXP/'audit/stopped.json',dict(complete=False,
|
||||
registration_sha256=self.sha,error_type=type(error).__name__,error=str(error),
|
||||
traceback=traceback.format_exc(),partial_files_preserved=True,automatic_retry=False))
|
||||
raise
|
||||
|
||||
if __name__=='__main__':
|
||||
p=argparse.ArgumentParser();p.add_argument('--registration-sha256',required=True)
|
||||
Workflow(p.parse_args().registration_sha256).run()
|
||||
@@ -0,0 +1,30 @@
|
||||
"""Exclusive CPU/source test receipt. No scientific execution or CUDA allowed."""
|
||||
import argparse
|
||||
import io
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
from normal_io import digest, save, require, MODEL
|
||||
|
||||
def run(output):
|
||||
require(sys.dont_write_bytecode,'Use -B')
|
||||
os.environ['CUDA_VISIBLE_DEVICES']=''
|
||||
before={p.name:digest(p) for p in MODEL.iterdir() if p.is_file()}
|
||||
suite=unittest.defaultTestLoader.discover(str(MODEL),pattern='test_*.py')
|
||||
text=io.StringIO();start=time.perf_counter()
|
||||
result=unittest.TextTestRunner(stream=text,verbosity=2).run(suite)
|
||||
after={p.name:digest(p) for p in MODEL.iterdir() if p.is_file()}
|
||||
no_neural_modules=not any(n in sys.modules for n in ('torch','runtime_light','conditioning_epoch'))
|
||||
success=result.wasSuccessful() and not result.skipped and before==after and no_neural_modules
|
||||
save(output,dict(schema='normal-CPU-tests-v1',pass_all=success,tests=result.testsRun,
|
||||
failures=len(result.failures),errors=len(result.errors),skips=len(result.skipped),
|
||||
source_sha256=before,sources_unchanged=before==after,wall_seconds=time.perf_counter()-start,
|
||||
stdout=text.getvalue(),fresh_process=True,CUDA_hidden=True,no_neural_modules=no_neural_modules,
|
||||
scope='CPU source and mock-process tests; not real GPU numerical or scientific evidence'))
|
||||
return success
|
||||
|
||||
if __name__=='__main__':
|
||||
p=argparse.ArgumentParser();p.add_argument('--output',required=True)
|
||||
sys.exit(0 if run(p.parse_args().output) else 1)
|
||||
@@ -0,0 +1,55 @@
|
||||
"""Detached parent supervisor, with real final exit receipts outside EXP.
|
||||
|
||||
Administrative stdout is separate from the immutable per-trial ledger. Launch
|
||||
is exclusive, never a retry policy. A launch PID is NOT a completion receipt.
|
||||
"""
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from normal_io import *
|
||||
|
||||
CONTROL=ROOT/'logs/phase4ar-normal-conditioning'
|
||||
|
||||
def authority(sha):
|
||||
require(sys.dont_write_bytecode,'Use -B')
|
||||
require(digest(EXP/'protocol/preregistered.json')==sha,'Registration differs')
|
||||
reg=read(EXP/'protocol/preregistered.json');verify(reg['source_sha256'])
|
||||
require(reg['scientific_scope']=='normal-acquisition-only' and unlinked(CONTROL).is_dir(),'Wrong scope/control directory')
|
||||
require(not (EXP/'audit/stopped.json').exists() and not (EXP/'audit/execution-complete.json').exists(),
|
||||
'Stopped/completed phase cannot launch')
|
||||
return reg
|
||||
|
||||
def launch(sha):
|
||||
authority(sha)
|
||||
require(not any(CONTROL.iterdir()),'Control directory nonempty: inspect, do not retry')
|
||||
save(CONTROL/'launch-attempt.json',dict(registration_sha256=sha,started_utc=datetime.now(timezone.utc).isoformat(),
|
||||
complete=False,terminal_state='UNKNOWN',automatic_retry=False))
|
||||
command=[sys.executable,'-B',str(MODEL/'run_normal.py'),'supervise','--registration-sha256',sha]
|
||||
with unlinked(CONTROL/'stdout.log').open('xb') as out,unlinked(CONTROL/'stderr.log').open('xb') as err:
|
||||
process=subprocess.Popen(command,cwd=MODEL,stdin=subprocess.DEVNULL,stdout=out,stderr=err,start_new_session=True,
|
||||
env={**os.environ,'PYTHONDONTWRITEBYTECODE':'1'})
|
||||
record=dict(supervisor_pid=process.pid,argv=command,registration_sha256=sha,launch_observed=True,
|
||||
final_exit_observed=False,not_evidence_of_completion=True)
|
||||
save(CONTROL/'launch.json',record);return record
|
||||
|
||||
def supervise(sha):
|
||||
authority(sha)
|
||||
save(CONTROL/'supervisor-start.json',dict(pid=os.getpid(),registration_sha256=sha,
|
||||
started_utc=datetime.now(timezone.utc).isoformat(),complete=False))
|
||||
command=[sys.executable,'-B',str(MODEL/'normal_runner.py'),'--registration-sha256',sha]
|
||||
started=time.perf_counter();code=None;error=None
|
||||
try:code=subprocess.run(command,cwd=MODEL,stdin=subprocess.DEVNULL).returncode
|
||||
except BaseException as exc:error=type(exc).__name__+': '+str(exc)
|
||||
save(CONTROL/'exit.json',dict(registration_sha256=sha,argv=command,exit_code=code,
|
||||
final_exit_observed=type(code)is int,wall_seconds=time.perf_counter()-started,error=error,
|
||||
complete=code==0,learning_success_claimed=False,scientific_analysis_required=True))
|
||||
return 0 if code==0 else 1
|
||||
|
||||
if __name__=='__main__':
|
||||
parser=argparse.ArgumentParser();parser.add_argument('mode',choices=('launch','supervise'))
|
||||
parser.add_argument('--registration-sha256',required=True);args=parser.parse_args()
|
||||
if args.mode=='launch':print(canonical(launch(args.registration_sha256)),flush=True)
|
||||
else:sys.exit(supervise(args.registration_sha256))
|
||||
@@ -0,0 +1,241 @@
|
||||
"""Temporary filesystem tests only; no process/brain/GPU execution."""
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import append_ledger as L
|
||||
|
||||
|
||||
def put(path, value):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_bytes(value if type(value) is bytes else L.raw_json(value))
|
||||
return L.identity(path)
|
||||
|
||||
|
||||
class LedgerTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp=tempfile.TemporaryDirectory();self.addCleanup(self.temp.cleanup)
|
||||
self.root=Path(self.temp.name).resolve()/'normal';self.root.mkdir()
|
||||
self.reg=self.root/L.REGISTRATION; info=put(self.reg,{'only':'synthetic-registration'})
|
||||
self.initial={L.REGISTRATION:info};self.sha=info['sha256']
|
||||
self.ledger=L.Ledger(self.root,self.sha,self.initial,1<<20,0)
|
||||
|
||||
def job(self,name):
|
||||
job=self.root/'jobs'/(name+'.json');put(job,{'entry_id':name})
|
||||
self.ledger.begin(name,job,{'synthetic':True})
|
||||
return job
|
||||
|
||||
def completion(self,name,job,*,payload=b'output',changes=None):
|
||||
out=self.root/'runs'/name/'payload.dat';put(out,payload)
|
||||
process=self.root/'receipts'/(name+'.json')
|
||||
value=dict(entry_id=name,registration_sha256=self.sha,job_sha256=L.digest(job),complete=True,
|
||||
exit_code=0,timed_out=False,exit_observed_by_parent=True)
|
||||
value.update(changes or {});put(process,value)
|
||||
inputs={str(self.reg):L.identity(self.reg),str(job):L.identity(job)}
|
||||
outputs={str(p):L.identity(p) for p in (job,out,process)}
|
||||
metadata=dict(job_file=str(job),process_receipt_file=str(process),scope='synthetic completed parent job only',observed_returncode=0)
|
||||
return inputs,outputs,metadata
|
||||
|
||||
def commit(self,name):
|
||||
job=self.job(name);args=self.completion(name,job)
|
||||
return self.ledger.append(name,*args)
|
||||
|
||||
def test_two_entries_chain_full_tree_and_cumulative_bytes(self):
|
||||
one=self.commit('one');two=self.commit('two')
|
||||
second=L.read_json(self.root/L.CONTROL/'entries/0000000000000002.json')
|
||||
self.assertEqual(second['prev_entry_sha256'],one['entry_sha256'])
|
||||
self.assertEqual(two['entry_sha256'],L.digest(self.root/L.CONTROL/'entries/0000000000000002.json'))
|
||||
inspected=self.ledger.inspect();self.assertEqual(inspected['entry_ids'],['one','two'])
|
||||
self.assertFalse(inspected['retry_authorized']);self.assertTrue(inspected['all_tracked_history_rehashed'])
|
||||
final=self.ledger.final_verify(['one','two']);self.assertTrue(final['pass_all'])
|
||||
self.assertEqual(final['actual_total_bytes'],sum(p.stat().st_size for p in self.root.rglob('*') if p.is_file()))
|
||||
self.assertFalse(final['scientific_gate_claimed'])
|
||||
|
||||
def test_reopen_independent_read_verifies_no_reexecution_or_duplicate_append(self):
|
||||
self.commit('one')
|
||||
reopened=L.Ledger(self.root,self.sha,self.initial,1<<20,0)
|
||||
self.assertEqual(reopened.inspect()['entry_ids'],['one'])
|
||||
with self.assertRaisesRegex(ValueError,'already started/committed'):
|
||||
reopened.begin('one',self.root/'jobs/one.json')
|
||||
with self.assertRaisesRegex(ValueError,'No unique uncommitted'):
|
||||
reopened.append('one',{}, {},dict(job_file='x',process_receipt_file='y',scope='s',observed_returncode=0))
|
||||
|
||||
def test_pending_or_live_handle_is_unknown_and_never_retry_authority(self):
|
||||
job=self.job('live');state=self.ledger.inspect()
|
||||
self.assertEqual(state['uncommitted_state'],'STARTED-UNCOMMITTED-STATE-UNKNOWN')
|
||||
self.assertFalse(state['retry_authorized'])
|
||||
with self.assertRaisesRegex(ValueError,'uncommitted start'):self.ledger.begin('another',job)
|
||||
args=list(self.completion('live',job));args[2]['observed_returncode']=None
|
||||
with self.assertRaisesRegex(ValueError,'Live/failed'):self.ledger.append('live',*args)
|
||||
final=self.ledger.final_verify(['live']);self.assertFalse(final['pass_all']);self.assertTrue(final['uncommitted_state_unknown'])
|
||||
reopened=L.Ledger(self.root,self.sha,self.initial,1<<20,0)
|
||||
self.assertEqual(reopened.inspect()['uncommitted_entry_ids'],['live'])
|
||||
|
||||
def test_actual_parent_receipt_required_not_worker_success_or_bool_exit(self):
|
||||
job=self.job('one')
|
||||
for mutation in ({'exit_code':False},{'complete':False},{'exit_observed_by_parent':False},
|
||||
{'timed_out':True},{'registration_sha256':'0'*64},{'job_sha256':'0'*64},{'entry_id':'other'}):
|
||||
args=self.completion('one',job,changes=mutation)
|
||||
with self.subTest(mutation=mutation),self.assertRaisesRegex(ValueError,'parent process receipt'):
|
||||
self.ledger.append('one',*args)
|
||||
|
||||
def test_same_size_same_mtime_mutation_fails_actual_SHA(self):
|
||||
job=self.job('one');args=self.completion('one',job,payload=b'aaaa')
|
||||
out=self.root/'runs/one/payload.dat';stat=out.stat();out.write_bytes(b'bbbb')
|
||||
os.utime(out,ns=(stat.st_atime_ns,stat.st_mtime_ns))
|
||||
with self.assertRaisesRegex(ValueError,'Actual file SHA/bytes'):self.ledger.append('one',*args)
|
||||
|
||||
def test_missing_extra_changed_files_reported_at_full_audit(self):
|
||||
self.commit('one');out=self.root/'runs/one/payload.dat'
|
||||
extra=self.root/'unexpected.log';put(extra,b'extra')
|
||||
final=self.ledger.final_verify(['one']);self.assertFalse(final['pass_all']);self.assertIn('unexpected.log',final['extra_files'])
|
||||
out.unlink();final=self.ledger.final_verify(['one'])
|
||||
self.assertIn('runs/one/payload.dat',final['missing_files'])
|
||||
put(out,b'different');final=self.ledger.final_verify(['one'])
|
||||
self.assertIn('runs/one/payload.dat',final['changed_files'])
|
||||
|
||||
def test_tail_and_middle_tamper_not_trusted_by_inspect(self):
|
||||
self.commit('one');self.commit('two')
|
||||
first=self.root/L.CONTROL/'entries/0000000000000001.json'
|
||||
value=L.read_json(first);value['metadata']['scope']='tampered'
|
||||
put(first,value)
|
||||
with self.assertRaisesRegex(ValueError,'chain/start identity'):self.ledger.inspect()
|
||||
self.assertFalse(self.ledger.final_verify(['one','two'])['pass_all'])
|
||||
|
||||
def test_previously_observed_head_rewrite_rejected_even_new_valid_JSON(self):
|
||||
self.commit('one');path=self.root/L.CONTROL/'entries/0000000000000001.json'
|
||||
value=L.read_json(path);value['metadata']['scope']='changed';put(path,value)
|
||||
with self.assertRaisesRegex(ValueError,'head changed'):self.ledger.inspect()
|
||||
|
||||
def test_registered_final_entry_order_and_coverage_are_exact(self):
|
||||
self.commit('one');self.commit('two')
|
||||
for expected in (['two','one'],['one'],['one','two','three']):
|
||||
report=self.ledger.final_verify(expected)
|
||||
self.assertFalse(report['pass_all']);self.assertFalse(report['expected_order_exact'])
|
||||
with self.assertRaisesRegex(ValueError,'expected entry order'):self.ledger.final_verify(['one','one'])
|
||||
|
||||
def test_path_escape_aliases_and_overwrite_rejected(self):
|
||||
self.commit('one');job=self.job('two');inputs,outputs,meta=self.completion('two',job)
|
||||
outside=self.root.parent/'outside.dat';put(outside,b'external')
|
||||
outputs[str(outside)]=L.identity(outside)
|
||||
with self.assertRaisesRegex(ValueError,'escapes experiment'):self.ledger.append('two',inputs,outputs,meta)
|
||||
del outputs[str(outside)];old=self.root/'runs/one/payload.dat';outputs[str(old)]=L.identity(old)
|
||||
with self.assertRaisesRegex(ValueError,'previously tracked'):self.ledger.append('two',inputs,outputs,meta)
|
||||
del outputs[str(old)];outputs['runs/two/payload.dat']=outputs[str(self.root/'runs/two/payload.dat')]
|
||||
with self.assertRaisesRegex(ValueError,'Duplicate path aliases'):self.ledger.append('two',inputs,outputs,meta)
|
||||
with self.assertRaisesRegex(ValueError,'Escaping/noncanonical'):L.relative_name('../escape')
|
||||
|
||||
def test_consumed_tracked_input_cannot_be_silently_reauthorized_with_new_SHA(self):
|
||||
self.commit('one');job=self.job('two');inputs,outputs,meta=self.completion('two',job)
|
||||
prior=self.root/'runs/one/payload.dat';put(prior,b'overwritten')
|
||||
inputs[str(prior)]=L.identity(prior)
|
||||
with self.assertRaisesRegex(ValueError,'committed identity'):self.ledger.append('two',inputs,outputs,meta)
|
||||
|
||||
def test_external_inputs_allowed_but_declared_bytes_reverified(self):
|
||||
job=self.job('one');inputs,outputs,meta=self.completion('one',job)
|
||||
external=self.root.parent/'frozen-reference.json';put(external,{'read_only':'data'})
|
||||
inputs[str(external)]=L.identity(external);self.ledger.append('one',inputs,outputs,meta)
|
||||
row=L.read_json(self.root/L.CONTROL/'entries/0000000000000001.json')
|
||||
self.assertIsNone(next(r for r in row['consumed_inputs'] if r['path']==str(external))['relative_path'])
|
||||
put(external,{'read_only':'changed'})
|
||||
with self.assertRaisesRegex(ValueError,'Actual file SHA/bytes'):self.ledger.inspect()
|
||||
|
||||
def test_full_audit_hashes_shared_external_input_once_per_invocation(self):
|
||||
external=self.root.parent/'large-shared-reference';put(external,b'fixed external bytes')
|
||||
expected=L.identity(external)
|
||||
for name in ('one','two','three'):
|
||||
job=self.job(name);inputs,outputs,meta=self.completion(name,job)
|
||||
inputs[str(external)]=expected;self.ledger.append(name,inputs,outputs,meta)
|
||||
original=L.digest;counts={}
|
||||
def counted(path):
|
||||
key=str(Path(path));counts[key]=counts.get(key,0)+1
|
||||
return original(path)
|
||||
with patch.object(L,'digest',side_effect=counted):
|
||||
self.assertTrue(self.ledger.final_verify(['one','two','three'])['pass_all'])
|
||||
self.assertEqual(counts[str(external)],1)
|
||||
counts.clear();self.ledger.inspect();self.assertEqual(counts[str(external)],1)
|
||||
counts.clear();self.ledger.inspect();self.assertEqual(counts[str(external)],1)
|
||||
oldstat=external.stat();external.write_bytes(b'other external bytes')
|
||||
os.utime(external,ns=(oldstat.st_atime_ns,oldstat.st_mtime_ns))
|
||||
with self.assertRaisesRegex(ValueError,'Actual file SHA/bytes'):self.ledger.inspect()
|
||||
|
||||
def test_append_does_not_iterate_or_sum_historical_maps_or_search_ordered_ids(self):
|
||||
self.commit('one')
|
||||
class LookupOnlyDict(dict):
|
||||
def __iter__(self):raise AssertionError('Historical map iteration in fast append')
|
||||
def keys(self):raise AssertionError('Historical map copy in fast append')
|
||||
def values(self):raise AssertionError('Historical map sum in fast append')
|
||||
def items(self):raise AssertionError('Historical map iteration in fast append')
|
||||
class NoLinearMembership(list):
|
||||
def __contains__(self,value):raise AssertionError('Linear completed-ID membership')
|
||||
self.ledger._tracked=LookupOnlyDict(self.ledger._tracked)
|
||||
self.ledger._controls=LookupOnlyDict(self.ledger._controls)
|
||||
self.ledger._completed=NoLinearMembership(self.ledger._completed)
|
||||
self.commit('two')
|
||||
self.assertEqual(self.ledger._completed,['one','two'])
|
||||
self.assertTrue(self.ledger.final_verify(['one','two'])['pass_all'])
|
||||
|
||||
def test_head_is_freshly_checked_after_cached_full_tree_walk(self):
|
||||
self.commit('one');tail=self.root/L.CONTROL/'entries/0000000000000001.json'
|
||||
original_replay=self.ledger._replay;original_identity=self.ledger._identity_once
|
||||
state={'walking':False,'mutated':False}
|
||||
def replay(verified):
|
||||
original_replay(verified);state['walking']=True
|
||||
def during_walk(path,verified):
|
||||
if state['walking'] and not state['mutated']:
|
||||
value=L.read_json(tail);value['metadata']['scope']='mutation during final walk'
|
||||
put(tail,value);state['mutated']=True
|
||||
return original_identity(path,verified)
|
||||
with patch.object(self.ledger,'_replay',side_effect=replay),\
|
||||
patch.object(self.ledger,'_identity_once',side_effect=during_walk):
|
||||
report=self.ledger.final_verify(['one'])
|
||||
self.assertTrue(state['mutated']);self.assertFalse(report['pass_all'])
|
||||
self.assertTrue(any('Known ledger tail changed' in message for message in report['errors']))
|
||||
|
||||
def test_shared_mutable_build_separate_current_inventory_and_cap(self):
|
||||
build=self.root/'extension-build/cache.bin';put(build,b'first');self.commit('one')
|
||||
put(build,b'changed build is allowed');self.commit('two')
|
||||
report=self.ledger.final_verify(['one','two']);self.assertTrue(report['pass_all'])
|
||||
self.assertEqual(report['shared_mutable_build_bytes'],len(b'changed build is allowed'))
|
||||
self.assertNotIn('extension-build/cache.bin',report['extra_files'])
|
||||
put(build,b'x'*(1<<20));report=self.ledger.final_verify(['one','two'])
|
||||
self.assertFalse(report['pass_all']);self.assertFalse(report['output_cap_respected'])
|
||||
|
||||
def test_stale_writer_lock_and_partial_publication_never_auto_cleared(self):
|
||||
lock=self.root/L.CONTROL/'writer.lock';put(lock,b'unknown owner')
|
||||
with self.assertRaises(FileExistsError):self.ledger.begin('one',self.reg)
|
||||
with self.assertRaisesRegex(ValueError,'state unknown'):self.ledger.inspect()
|
||||
self.assertEqual(lock.read_bytes(),b'unknown owner')
|
||||
|
||||
def test_exclusive_atomic_publication_and_preserved_failed_temporary(self):
|
||||
target=self.root/'standalone.json';info=L.publish_exclusive(target,{'a':1})
|
||||
self.assertEqual(info,L.identity(target))
|
||||
with self.assertRaisesRegex(ValueError,'already exists'):L.publish_exclusive(target,{'a':2})
|
||||
self.assertEqual(L.read_json(target),{'a':1})
|
||||
target2=self.root/'failed.json'
|
||||
with patch.object(L.os,'link',side_effect=OSError('synthetic unsupported filesystem')):
|
||||
with self.assertRaises(OSError):L.publish_exclusive(target2,{'a':2})
|
||||
self.assertFalse(target2.exists());self.assertEqual(len(list(self.root.glob('.publishing-*'))),1)
|
||||
|
||||
def test_linked_output_rejected_if_platform_supports_links(self):
|
||||
source=self.root.parent/'other';source.mkdir();link=self.root/'linked'
|
||||
try:link.symlink_to(source,target_is_directory=True)
|
||||
except OSError:self.skipTest('Platform disallows synthetic symlink')
|
||||
job=self.job('one');inputs,outputs,meta=self.completion('one',job)
|
||||
put(source/'payload',b'x');outputs[str(link/'payload')]=L.identity(source/'payload')
|
||||
with self.assertRaisesRegex(ValueError,'Linked'):self.ledger.append('one',inputs,outputs,meta)
|
||||
|
||||
def test_initial_and_header_authority_are_not_optional(self):
|
||||
for change in ('registration','options'):
|
||||
with self.subTest(change=change),self.assertRaises(ValueError):
|
||||
L.Ledger(self.root,'0'*64 if change=='registration' else self.sha,self.initial,
|
||||
2<<20 if change=='options' else 1<<20,0)
|
||||
header=self.root/L.CONTROL/'header.json';value=L.read_json(header);value['max_output_bytes']+=1;put(header,value)
|
||||
with self.assertRaisesRegex(ValueError,'header changed'):self.ledger.inspect()
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,73 @@
|
||||
"""CPU request descriptors and pinned static transform, never a CUDA test."""
|
||||
import copy
|
||||
import unittest
|
||||
import numpy as np
|
||||
import normal_inputs as I
|
||||
from normal_io import load_source, LAB
|
||||
from normal_runner import compose_requests, derive_spec
|
||||
|
||||
class InputsTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.inputs=load_source('_normal_test_CI', LAB/'conditioning_inputs.py',I.PINS['conditioning_inputs.py'])
|
||||
|
||||
def task(self,arm='paired',cs=True):
|
||||
return dict(task_id='block/normal/'+arm+'/000',kind='train',arm=arm,steps=1200,mode='physiological',
|
||||
recipe=dict(cs=None if not cs else dict(cue='A',seed=2**62+37,start_tick=0,stop_tick_exclusive=1000,source_stream_id='s'),
|
||||
us=dict(nominal_slot_tick=900,rng_seed=None,rng_draws=0,requested=True,tick=900),
|
||||
D_command=0. if arm=='d_zero' else 1.,update_enabled=arm!='frozen'))
|
||||
|
||||
def test_full63_seed_and_aliases(self):
|
||||
a=self.task();b=self.task('d_zero')
|
||||
self.assertEqual(I.descriptor(a),I.descriptor(b))
|
||||
self.assertEqual(I.descriptor(a)['seed'],2**62+37)
|
||||
|
||||
def test_empty_CS_is_not_resampled(self):
|
||||
self.assertIsNone(I.descriptor(self.task('dan_only',False)))
|
||||
|
||||
def test_all_DAN_ids_and_counterfactual_US(self):
|
||||
dan=np.array([10,20],np.int32);empty=dict(tick=np.empty(0,np.int32),neuron_idx=np.empty(0,np.int32))
|
||||
for arm in ('paired','d_zero','frozen'):
|
||||
composed,us=compose_requests(empty,dan,self.task(arm),self.inputs)
|
||||
np.testing.assert_array_equal(composed['requests']['neuron_idx'],dan)
|
||||
self.assertEqual(us['tick'].tolist(),[900,900])
|
||||
|
||||
def test_no_US_and_zero_command(self):
|
||||
task=self.task('cs_only');task['recipe']['us'].update(requested=False,tick=None);task['recipe']['D_command']=0.
|
||||
cs=dict(tick=np.array([1],np.int32),neuron_idx=np.array([5],np.int32))
|
||||
combined,us=compose_requests(cs,np.array([10,20],np.int32),task,self.inputs)
|
||||
self.assertEqual(len(us['tick']),0);self.assertEqual(combined['requests']['neuron_idx'].tolist(),[5])
|
||||
|
||||
def test_conflict_and_command_fail_closed(self):
|
||||
cs=dict(tick=np.array([900],np.int32),neuron_idx=np.array([10],np.int32))
|
||||
with self.assertRaises(ValueError):compose_requests(cs,np.array([10,20],np.int32),self.task(),self.inputs)
|
||||
task=self.task('d_zero');task['recipe']['D_command']=1.
|
||||
with self.assertRaises(ValueError):compose_requests(cs,np.array([10,20],np.int32),task,self.inputs)
|
||||
|
||||
def test_probe_no_US_no_update(self):
|
||||
p=dict(kind='probe',mode='matched_energy',steps=1200,feedback_to_training_or_idle=False,
|
||||
recipe=dict(cue='B',input=dict(seed=2**61,stream_id='eval'),cs_start_tick=0,cs_stop_tick_exclusive=1000,
|
||||
US_requested=False,D_command=0.,weight_updates_enabled=False))
|
||||
d=I.descriptor(p);self.assertEqual(d['table_id'],'matched_energy--B')
|
||||
empty=dict(tick=np.empty(0,np.int32),neuron_idx=np.empty(0,np.int32))
|
||||
combined,us=compose_requests(empty,np.array([10,20],np.int32),p,self.inputs)
|
||||
self.assertEqual(len(combined['requests']['tick']),0)
|
||||
p['feedback_to_training_or_idle']=True
|
||||
with self.assertRaises(ValueError):compose_requests(empty,np.array([10,20],np.int32),p,self.inputs)
|
||||
|
||||
def test_clock_rejected(self):
|
||||
task=self.task();task['steps']=1800
|
||||
with self.assertRaises(ValueError):I.descriptor(task)
|
||||
|
||||
def test_case_math_config_retained(self):
|
||||
original=dict(kind='fullgraph',dt_ms=.1,apl_delay_steps=18,precision='float64',apl_precision='float32',
|
||||
record_history=False,seed=1073741825,model=dict(tau=20),apl=dict(gain=.01),graph_dir='/frozen/graph',
|
||||
rate_sum_hz=1,mode='physiological')
|
||||
task=self.task();task['mode']='matched_energy';before=copy.deepcopy(original)
|
||||
spec=derive_spec(original,task,budget_root='/new/exp',output_cap=1234)
|
||||
self.assertEqual(original,before)
|
||||
for key in ('dt_ms','apl_delay_steps','precision','apl_precision','seed','model','apl','graph_dir'):
|
||||
self.assertEqual(spec[key],original[key])
|
||||
self.assertEqual(spec['steps'],1200);self.assertFalse(spec['within_trial_weight_updates'])
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,274 @@
|
||||
"""CPU arrays and mocked artifact I/O; these are not scientific observations."""
|
||||
import copy
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import io
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
|
||||
spec = importlib.util.spec_from_file_location('_test_normal_metrics', Path(__file__).with_name('normal_metrics.py'))
|
||||
N = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(N)
|
||||
|
||||
|
||||
def fixture():
|
||||
nodes = np.arange(6, dtype=np.int32)
|
||||
pops = {k: np.asarray(v, np.int32) for k, v in dict(MBON=[0, 1], MBON01=[0], MBON12=[1],
|
||||
legacyDownstream=[0, 1, 2, 3], nonMBONDownstream=[2, 3]).items()}
|
||||
blocks, probes, arms = {}, {}, {}
|
||||
seed = 1
|
||||
for mode in N.M.MODES:
|
||||
for dan in N.M.DAN_TYPES:
|
||||
for cue in ('A', 'B'):
|
||||
for rep in range(1, 6):
|
||||
identity = f'{mode}__{dan}__reinforce_{cue}__rep{rep:02d}'
|
||||
sources = []
|
||||
for split in ('training', 'design'):
|
||||
sources.append(dict(stream_id=identity + '/' + split, seed=seed, split=split)); seed += 1
|
||||
evaluation = {}
|
||||
for c in ('A', 'B'):
|
||||
evaluation[N.ODORS[c]] = dict(stream_id=identity + '/evaluation/' + c, seed=seed, split='evaluation'); seed += 1
|
||||
blocks[identity] = dict(mode=mode, dan_type=dan, compartment_verbatim=N.G.DAN_COMPARTMENTS[dan],
|
||||
conditioned_cue=N.ODORS[cue], replicate=rep, training_sources=sources, evaluation_sources=evaluation,
|
||||
evaluation_input_sha256={N.ODORS[c]: N.sha([identity, c]) for c in ('A', 'B')})
|
||||
for arm in N.ARM_NAMES:
|
||||
arms[(identity, arm)] = [dict(result=[identity, arm, e], requested=e < 50 and arm != 'cs_only')
|
||||
for e in range(150 if arm == 'unpaired' else 100)]
|
||||
for point in N.POINTS:
|
||||
for c in ('A', 'B'):
|
||||
probes[(identity, arm, point, c)] = dict(block=identity, arm=arm, point=point, cue=c,
|
||||
active=arm == 'paired' and point > 0 and c == cue and rep <= 3, dan=dan)
|
||||
membership = N.M.validate_populations(nodes, pops)
|
||||
registry = dict(schema=N.G.REGISTRY_SCHEMA, protocol_sha256='1' * 64, population_binding_sha256='2' * 64,
|
||||
nodes_raw_sha256=N.M._hash(nodes), population_membership_sha256=membership['membership_sha256'], blocks=blocks)
|
||||
authority = dict(schema=N.G.AUTHORITY_SCHEMA, registry_sha256=N.G.descriptor_sha256(registry),
|
||||
verification_receipt_sha256='3' * 64, execution_inventory_sha256='4' * 64, population_binding_sha256='2' * 64)
|
||||
return nodes, pops, registry, authority, probes, arms
|
||||
|
||||
|
||||
def state_for(record):
|
||||
ids = np.asarray(sorted([1 if record['dan'] == 'PAM15' else 0, 2]) if record['active'] else [], np.int32)
|
||||
state = dict(step=np.full(len(ids), 10, np.int32), neuron_idx=ids,
|
||||
counts=np.bincount(ids, minlength=6).astype(np.int32), v=np.zeros(6, np.float64),
|
||||
g=np.zeros(6, np.float64), ref=np.zeros(6, np.int32))
|
||||
if record['active']:
|
||||
state['g'][ids[0]] = .1
|
||||
return state
|
||||
|
||||
|
||||
class MockReader:
|
||||
def __init__(self, values):
|
||||
self.values = values
|
||||
self.inventory = {str(p): dict(bytes=len(N.canonical(v)), sha256=N.sha(v)) for p, v in values.items()}
|
||||
def json(self, path): return copy.deepcopy(self.values[str(path)])
|
||||
def check(self, path): return self.inventory[str(path)]
|
||||
def path(self, path): return Path(path), self.inventory[str(path)]
|
||||
|
||||
|
||||
def process_fixture():
|
||||
exp = Path.cwd() / 'mock-normal-evidence'
|
||||
entry_id = 'input-generation'; regsha = '1' * 64
|
||||
job_path = exp / 'jobs/input-generation.json'
|
||||
proc_path = exp / 'receipts/input-generation/process.json'
|
||||
start_path = exp / '.append-ledger/started/input-generation.json'
|
||||
entry_path = exp / '.append-ledger/entries/0000000000000001.json'
|
||||
values = {str(job_path): dict(kind='sample', registration_sha256=regsha, input_sha256={})}
|
||||
for label in ('stdout', 'stderr'):
|
||||
values[str(exp / f'logs/input-generation.{label}.log')] = {'log': label}
|
||||
values[str(proc_path)] = dict(entry_id=entry_id, registration_sha256=regsha, job_sha256=N.sha(values[str(job_path)]),
|
||||
complete=True, exit_code=0, timed_out=False, exit_observed_by_parent=True,
|
||||
stdout_sha256=N.sha({'log': 'stdout'}), stderr_sha256=N.sha({'log': 'stderr'}))
|
||||
r = MockReader(values)
|
||||
row = lambda p: dict(path=str(p), relative_path=Path(p).relative_to(exp).as_posix(), **r.inventory[str(p)])
|
||||
values[str(start_path)] = dict(entry_id=entry_id, registration_sha256=regsha, next_sequence=1,
|
||||
prev_entry_sha256=None, retry_authorized=False, job=row(job_path))
|
||||
values[str(entry_path)] = dict(entry_id=entry_id, registration_sha256=regsha, sequence=1,
|
||||
prev_entry_sha256=None, start_sha256=N.sha(values[str(start_path)]), consumed_inputs=[row(job_path)],
|
||||
new_outputs=[row(p) for p in list(values) if p != str(start_path)],
|
||||
metadata=dict(job_file=str(job_path), process_receipt_file=str(proc_path), observed_returncode=0))
|
||||
final = dict(schema='normal-append-ledger-v1-final-audit', registration_sha256=regsha, pass_all=True,
|
||||
entry_ids=[entry_id], expected_entry_ids=[entry_id], expected_order_exact=True,
|
||||
extra_files=[], missing_files=[], changed_files=[], unsafe_files=[], errors=[], uncommitted_entry_ids=[],
|
||||
uncommitted_state_unknown=False, head_sha256=N.sha(values[str(entry_path)]))
|
||||
return exp, values, final, proc_path, entry_path
|
||||
|
||||
|
||||
def case_fixture(no_cs=False):
|
||||
exp = Path.cwd() / 'mock-normal-case'; population_file = str(exp / 'population.npz')
|
||||
seed = (1 << 62) + 17
|
||||
task = dict(task_id='real-recipe/epoch-000', kind='train', mode='physiological', arm='dan_only' if no_cs else 'paired',
|
||||
dan_type='PAM15', recipe=dict(cs=None if no_cs else dict(cue='A', seed=seed, source_stream_id='independent-original'),
|
||||
us=dict(requested=True), D_command=1.0))
|
||||
case = exp / 'cases' / N.task_key(task)
|
||||
template = dict(kind='fullgraph', steps=1200, dt_ms=.1, apl_delay_steps=18, precision='float64',
|
||||
apl_precision='float32', record_history=False, seed=98765, synaptic_tau=5.0, cs_input_seed=999)
|
||||
spec = {k: v for k, v in template.items() if k != 'cs_input_seed'}
|
||||
spec.update(name=N.task_key(task), steps=1200, duration_ms=120., max_steps=1200, budget_root=str(exp),
|
||||
output_budget_bytes=123, mode=task['mode'], within_trial_weight_updates=False,
|
||||
outer_protocol='normal-acquisition-v1', outer_task_id=task['task_id'], outer_arm=task['arm'])
|
||||
descriptor = dict(mode=task['mode'], cue='A', seed=seed, steps=1200, cs_start_tick=0,
|
||||
cs_stop_tick_exclusive=1000, source_stream_id='independent-original', table_id='physiological--A')
|
||||
csid = None if no_cs else N.sha(descriptor)
|
||||
arrays = {}
|
||||
source = dict(tick=np.asarray([] if no_cs else [10], np.int32), neuron_idx=np.asarray([] if no_cs else [3], np.int32))
|
||||
dan = np.asarray([4, 5, 6, 7], np.int32)
|
||||
us = dict(tick=np.full(4, 900, np.int32), neuron_idx=dan)
|
||||
combined = {k: np.concatenate((source[k], us[k])) for k in source}
|
||||
for name, value in (('cs_requests.npz', source), ('us_requests.npz', us), ('requests.npz', combined),
|
||||
('source-mask.npz', dict(source_mask=np.asarray(([1] if not no_cs else []) + [2]*4, np.uint8)))):
|
||||
arrays[str(case / name)] = value
|
||||
values = {str(case / 'spec.json'): spec, population_file: {'artifact': 'actual-static-populations'}}
|
||||
source_pin = None; sampler = dict(inputs={})
|
||||
if not no_cs:
|
||||
source_path = exp / f'inputs/generated/{csid}.npz'; audit_path = exp / f'inputs/generated/{csid}.json'
|
||||
values[str(source_path)] = {'array-artifact': 'mock-sparse-CS'}
|
||||
arrays[str(source_path)] = source
|
||||
source_pin = dict(path=str(source_path), sha256=N.sha(values[str(source_path)]))
|
||||
values[str(audit_path)] = dict(descriptor=descriptor, requests_sha256=source_pin['sha256'], audit=dict(seed=seed,
|
||||
generator_initial_seed=seed, seed_bits=63, seed_conversion='exact integer; no truncation/modulo/offset',
|
||||
private_generator=True, matrix_draw_calls=1, uniform_matrix_shape=[1200, 1], CS_window=[0, 1000]))
|
||||
sampler['inputs'][csid] = dict(requests=source_pin, audit=dict(path=str(audit_path), sha256=N.sha(values[str(audit_path)])))
|
||||
values[str(case / 'input-binding.json')] = dict(task_id=task['task_id'], CS_descriptor_id=csid, CS_source=source_pin,
|
||||
DAN_type='PAM15', population_file=dict(path=population_file, sha256=N.sha(values[population_file])),
|
||||
DAN_membership_sha256=hashlib.sha256(dan.tobytes()).hexdigest(), composition=dict(policy='error', cross_source_conflict_count=0))
|
||||
reader = MockReader(values)
|
||||
reader.arrays = lambda p: {k: v.copy() for k, v in arrays[str(p)].items()}
|
||||
args = dict(template=template, inputs=dict(task_inputs={task['task_id']: csid}, descriptors={} if no_cs else {csid: descriptor}),
|
||||
sampler=sampler, populations=dict(PAM15=dan), population_file=population_file, output_cap=123)
|
||||
return reader, exp, task, dict(case_dir=str(case)), args, values, arrays, case
|
||||
|
||||
|
||||
class NormalMetricTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.nodes, cls.pops, cls.registry, cls.authority, cls.probes, cls.arms = fixture()
|
||||
cls.full_reports = {}
|
||||
original = N.G.evaluate_acquisition
|
||||
def capture(*args, **kwargs):
|
||||
result = original(*args, **kwargs)
|
||||
cls.full_reports[(result['mode'], result['dan_type'], result['conditioned_cue'])] = result
|
||||
return result
|
||||
with patch.object(N.G, 'evaluate_acquisition', side_effect=capture):
|
||||
cls.report = N.scientific_reports(cls.probes, cls.arms, registry=cls.registry, authority=cls.authority,
|
||||
nodes=cls.nodes, populations=cls.pops, load_state=state_for)
|
||||
|
||||
def test_full_fixed_curves_and_eight_same_replicate_gates(self):
|
||||
self.assertEqual(len(self.report['cells']), 8)
|
||||
self.assertEqual(len(self.report['curves']), 1960)
|
||||
self.assertTrue(self.report['cohort']['all_functional_predicates_pass'])
|
||||
self.assertTrue(all(r['successful_same_replicate_conjunctions'] == 3 for r in self.report['cells']))
|
||||
self.assertTrue(all('acquisition_metric_inputs' not in r for r in self.report['cells']))
|
||||
self.assertTrue(all(not r['scientific_learning_pass_claimed'] for r in self.report['cells']))
|
||||
self.assertEqual({r['checkpoint'] for r in self.report['curves']}, set(N.POINTS))
|
||||
self.assertTrue(all(r['metrics']['rawS'] == 0 for r in self.report['curves'] if r['checkpoint'] == 0))
|
||||
self.assertTrue(all(not isinstance(v, list) for r in self.report['curves']
|
||||
for cue in r['metrics']['cues'].values() for group in cue['populations'].values() for v in group.values()))
|
||||
|
||||
def test_legacy_mapping_exactly_matches_frozen_wrapper(self):
|
||||
expected = N.G.legacy_h_cohort_audit(list(self.full_reports.values()), registry=self.registry,
|
||||
authority=self.authority, declared_mapping=N.G.H_MAPPING)
|
||||
actual = N.legacy_audit(self.report['cells'], N.G.H_MAPPING)
|
||||
self.assertEqual(actual, expected)
|
||||
self.assertEqual(len(actual['groups']), 4)
|
||||
self.assertTrue(all(set(g['control_sources']) == {'PAM15', 'PPL103'} for g in actual['groups']))
|
||||
with self.assertRaises(ValueError): N.legacy_audit(self.report['cells'], None)
|
||||
|
||||
def test_training_evaluation_seed_collision_and_missing_control_fail_closed(self):
|
||||
registry = copy.deepcopy(self.registry)
|
||||
block = next(iter(registry['blocks'].values()))
|
||||
block['evaluation_sources'][N.M.CUES[0]]['seed'] = block['training_sources'][0]['seed']
|
||||
with self.assertRaisesRegex(ValueError, 'collision'):
|
||||
N.G.validate_registry(registry, expected_sha256=N.G.descriptor_sha256(registry))
|
||||
report = next(iter(self.full_reports.values()))
|
||||
rows = copy.deepcopy(report['acquisition_metric_inputs'])
|
||||
del rows[0]['arms']['DAN-only']
|
||||
with self.assertRaisesRegex(ValueError, 'six actual controls'):
|
||||
N.G.evaluate_acquisition(rows, assay='normal', mode=report['mode'], dan_type=report['dan_type'],
|
||||
conditioned_cue=report['conditioned_cue'], registry=self.registry, authority=self.authority)
|
||||
|
||||
def test_state_mutation_and_absent_probe_never_become_zero_metrics(self):
|
||||
probes = dict(self.probes); del probes[next(iter(probes))]
|
||||
with self.assertRaises((KeyError, ValueError)):
|
||||
N.scientific_reports(probes, self.arms, registry=self.registry, authority=self.authority,
|
||||
nodes=self.nodes, populations=self.pops, load_state=state_for)
|
||||
def corrupt(record):
|
||||
state = state_for(record); state['g'][0] = np.nan; return state
|
||||
with self.assertRaisesRegex(ValueError, 'Nonfinite'):
|
||||
N.scientific_reports(self.probes, self.arms, registry=self.registry, authority=self.authority,
|
||||
nodes=self.nodes, populations=self.pops, load_state=corrupt)
|
||||
|
||||
def test_actual_parent_receipt_nested_layout_and_exit_failure(self):
|
||||
exp, values, final, proc, _ = process_fixture()
|
||||
evidence = N.Evidence(MockReader(values), exp, '1' * 64, ['input-generation'], final)
|
||||
observed = evidence.process('input-generation', 'sample'); evidence.finish()
|
||||
self.assertEqual(observed['process_path'], str(exp / 'receipts/input-generation/process.json'))
|
||||
values[str(proc)]['exit_code'] = 1
|
||||
# Even a caller report saying pass_all cannot rescue a real exit failure.
|
||||
r = MockReader(values)
|
||||
entry = next(v for v in values.values() if 'new_outputs' in v)
|
||||
for row in entry['new_outputs']:
|
||||
if row['path'] == str(proc): row.update(r.inventory[str(proc)])
|
||||
with self.assertRaisesRegex(ValueError, 'Actual parent exit'):
|
||||
N.Evidence(MockReader(values), exp, '1' * 64, ['input-generation'], final).process('input-generation', 'sample')
|
||||
|
||||
def test_result_process_must_be_ledger_owned_not_only_metadata(self):
|
||||
exp, values, final, proc, entry_path = process_fixture()
|
||||
entry = values[str(entry_path)]
|
||||
entry['new_outputs'] = [r for r in entry['new_outputs'] if r['path'] != str(proc)]
|
||||
with self.assertRaisesRegex(ValueError, 'not owned'):
|
||||
N.Evidence(MockReader(values), exp, '1' * 64, ['input-generation'], final).process('input-generation', 'sample')
|
||||
bad = dict(final, uncommitted_entry_ids=['unknown-child'])
|
||||
with self.assertRaisesRegex(ValueError, 'Incomplete'):
|
||||
N.Evidence(MockReader(values), exp, '1' * 64, ['input-generation'], bad)
|
||||
|
||||
def test_reader_per_invocation_actual_sha_cache_and_no_boolean_substitution(self):
|
||||
path = Path.cwd() / 'mock-artifact.json'; raw = b'{"actual":true}'
|
||||
identity = dict(bytes=len(raw), sha256=hashlib.sha256(raw).hexdigest())
|
||||
with patch.object(Path, 'is_symlink', return_value=False), patch.object(Path, 'is_junction', return_value=False, create=True), \
|
||||
patch.object(Path, 'is_file', return_value=True), patch.object(Path, 'open', side_effect=lambda *a, **k: io.BytesIO(raw)) as opened:
|
||||
reader = N.Reader({str(path): identity})
|
||||
reader.check(path); reader.check(path)
|
||||
self.assertEqual(opened.call_count, 1)
|
||||
N.Reader({str(path): identity}).check(path)
|
||||
self.assertEqual(opened.call_count, 2)
|
||||
with self.assertRaisesRegex(ValueError, 'Actual file checksum'):
|
||||
N.Reader({str(path): dict(bytes=len(raw), sha256='0' * 64)}).check(path)
|
||||
|
||||
def test_real_inventory_process_count_and_no_followup(self):
|
||||
tasks = [dict(task_id='train-' + str(i), kind='train') for i in range(30000)]
|
||||
tasks += [dict(task_id='probe-' + str(i), kind='probe') for i in range(3920)]
|
||||
entries = N.expected_entries(dict(tasks=tasks))
|
||||
self.assertEqual(len(entries), 93921)
|
||||
self.assertEqual(len(set(entries)), 93921)
|
||||
self.assertEqual(entries[0], 'input-generation')
|
||||
self.assertTrue(entries[-1].endswith('--brain'))
|
||||
|
||||
def test_original_train_cs_us_seed_and_model_checked_independently(self):
|
||||
reader, exp, task, job, args, values, arrays, case = case_fixture()
|
||||
N.audit_case(reader, exp, task, job, **args)
|
||||
arrays[str(case / 'us_requests.npz')]['tick'][0] = 901
|
||||
with self.assertRaisesRegex(ValueError, 'sorted unique|scheduled US'):
|
||||
N.audit_case(reader, exp, task, job, **args)
|
||||
arrays[str(case / 'us_requests.npz')]['tick'][0] = 900
|
||||
values[str(case / 'spec.json')]['seed'] += 1
|
||||
with self.assertRaisesRegex(ValueError, 'model/reset/clock'):
|
||||
N.audit_case(reader, exp, task, job, **args)
|
||||
values[str(case / 'spec.json')]['seed'] -= 1
|
||||
generated = next(v for v in values.values() if 'audit' in v)
|
||||
generated['audit']['generator_initial_seed'] %= 2**32
|
||||
with self.assertRaisesRegex(ValueError, 'sampler seed'):
|
||||
N.audit_case(reader, exp, task, job, **args)
|
||||
|
||||
def test_no_cs_is_empty_and_dan_only_still_uses_original_fixed_us(self):
|
||||
reader, exp, task, job, args, values, arrays, case = case_fixture(no_cs=True)
|
||||
N.audit_case(reader, exp, task, job, **args)
|
||||
arrays[str(case / 'cs_requests.npz')] = dict(tick=np.asarray([10], np.int32), neuron_idx=np.asarray([3], np.int32))
|
||||
with self.assertRaisesRegex(ValueError, 'case CS'):
|
||||
N.audit_case(reader, exp, task, job, **args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,160 @@
|
||||
"""CPU-only fixed inventory, authority, and dependency regression tests."""
|
||||
from collections import Counter, defaultdict
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import random
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
_SPEC = importlib.util.spec_from_file_location("normal_plan_test_subject", Path(__file__).with_name("normal_plan.py"))
|
||||
P = importlib.util.module_from_spec(_SPEC)
|
||||
_SPEC.loader.exec_module(P)
|
||||
|
||||
|
||||
class NormalPlanTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Deterministic recipe construction, NOT neural random sampling.
|
||||
cls.trial = P._FROZEN["trial_plan"].build_trial_plan(P.MASTER)
|
||||
cls.evaluation = P.expand_pinned_evaluation(cls.trial)
|
||||
with patch.object(random, "random", side_effect=AssertionError("RNG draw")), \
|
||||
patch.object(random, "Random", side_effect=AssertionError("RNG instance")):
|
||||
cls.plan = P.build_normal_plan(cls.trial, cls.evaluation)
|
||||
|
||||
def test_complete_inventory_and_order(self):
|
||||
plan = self.plan
|
||||
self.assertEqual(Counter(t["kind"] for t in plan["tasks"]), {"train": 30000, "probe": 3920})
|
||||
self.assertEqual(sum(t["steps"] for t in plan["tasks"]), 40704000)
|
||||
self.assertEqual(len(plan["blocks"]), 40)
|
||||
self.assertEqual(Counter((b["mode"], b["dan_type"], b["reinforced_cue"]) for b in plan["blocks"]),
|
||||
{(m, d, c): 5 for m in ("physiological", "matched_energy")
|
||||
for d in ("PAM15", "PPL103") for c in ("A", "B")})
|
||||
groups = defaultdict(list)
|
||||
for row in plan["tasks"]:
|
||||
groups[(row["block_id"], row["arm"])].append(row)
|
||||
self.assertEqual(list(groups), [(b["block_id"], a) for b in self.trial["plan"]["blocks"]
|
||||
for a in P._FROZEN["trial_plan"].ARMS])
|
||||
for (_, arm), rows in groups.items():
|
||||
self.assertEqual([r["kind"] for r in rows[:3]], ["probe", "probe", "train"])
|
||||
self.assertEqual([r["recipe"]["cue"] for r in rows[:2]], ["A", "B"])
|
||||
self.assertEqual(len(rows), 164 if arm == "unpaired" else 114)
|
||||
self.assertEqual([r["checkpoint"] for r in rows if r["kind"] == "probe"],
|
||||
[n for n in (0, 1, 2, 5, 10, 20, 50) for _ in range(2)])
|
||||
self.assertEqual(len(groups), 280)
|
||||
|
||||
def test_every_dependency_is_earlier_same_arm_delta_and_probes_do_not_feed_back(self):
|
||||
previous, completed = {}, Counter()
|
||||
for row in self.plan["tasks"]:
|
||||
key = row["block_id"], row["arm"]
|
||||
expected = previous.get(key, {"kind": "zero", "source": None})
|
||||
self.assertEqual(row["delta_dependency"], expected)
|
||||
self.assertTrue(row["artifact_validation_required"])
|
||||
if row["kind"] == "train":
|
||||
self.assertEqual(row["epoch_index"], completed[key])
|
||||
completed[key] += 1
|
||||
self.assertEqual(row["carry_between_epochs"], ["plastic_delta_only"])
|
||||
self.assertEqual(row["neural_state_policy"], "frozen_reset_including_KC_trace_and_both_delay_queues")
|
||||
self.assertTrue(row["original_E_required"] and row["cpu_validation_required"])
|
||||
previous[key] = {"kind": "epoch_delta_after", "source": row["delta_output_id"]}
|
||||
else:
|
||||
self.assertEqual(row["completed_epochs"], completed[key])
|
||||
self.assertEqual(row["snapshot_binding"]["completed_epochs"], completed[key])
|
||||
self.assertFalse(row["feedback_to_training_or_idle"])
|
||||
self.assertFalse(row["original_E_required"] or row["cpu_validation_required"])
|
||||
self.assertFalse(row["recipe"]["US_requested"] or row["recipe"]["weight_updates_enabled"])
|
||||
self.assertEqual(row["recipe"]["D_command"], 0.0)
|
||||
self.assertIsNone(row["delta_output_id"])
|
||||
|
||||
def test_frozen_control_recipes_not_nominal_boundaries(self):
|
||||
actual = {r["task_id"]: r for r in self.plan["tasks"]}
|
||||
for block in self.trial["plan"]["blocks"]:
|
||||
normal = next(s for s in block["suites"] if s["assay"] == "normal")
|
||||
for arm in normal["arms"]:
|
||||
for recipe in arm["epochs"]:
|
||||
row = actual[recipe["epoch_id"]]
|
||||
self.assertEqual(row["recipe"], recipe)
|
||||
self.assertEqual(row["source_binding"]["record_sha256"], P._sha(recipe))
|
||||
self.assertEqual(row["source_binding"]["payload_sha256"], self.trial["payload_sha256"])
|
||||
self.assertEqual(sum(e["us"]["requested"] for e in arm["epochs"]),
|
||||
0 if arm["arm"] == "cs_only" else 50)
|
||||
if arm["arm"] == "unpaired":
|
||||
self.assertTrue(all(not (e["cs"] and e["us"]["requested"]) for e in arm["epochs"]))
|
||||
for original in self.evaluation["probes"]:
|
||||
if original["assay"] == "normal":
|
||||
self.assertEqual(actual[original["probe_id"]]["recipe"], original)
|
||||
self.assertTrue(any(r["kind"] == "probe" and r["arm"] == "unpaired" and
|
||||
r["checkpoint"] == 50 and r["completed_epochs"] == 150
|
||||
for r in actual.values()))
|
||||
|
||||
def test_evaluation_inputs_reused_not_redrawn_or_counted_as_replicates(self):
|
||||
inputs = self.plan["evaluation_inputs"]
|
||||
self.assertEqual(len(inputs), 80)
|
||||
self.assertEqual(len({r["stream_id"] for r in inputs}), 80)
|
||||
seeds = {r["seed"] for r in inputs}
|
||||
training = {r["recipe"]["cs"]["seed"] for r in self.plan["tasks"]
|
||||
if r["kind"] == "train" and r["recipe"]["cs"] is not None}
|
||||
self.assertFalse(seeds & training)
|
||||
self.assertTrue(all(type(s) is int and 0 <= s < 2**63 for s in seeds | training))
|
||||
reuse = Counter(r["evaluation_input_id"] for r in self.plan["tasks"] if r["kind"] == "probe")
|
||||
self.assertEqual(set(reuse.values()), {49})
|
||||
self.assertEqual(set(reuse), {r["input_id"] for r in inputs})
|
||||
self.assertTrue(all(not r["recipe"]["adds_training_replicate"] for r in self.plan["tasks"] if r["kind"] == "probe"))
|
||||
self.assertEqual(self.plan["new_seed_streams"], 0)
|
||||
self.assertFalse(self.plan["learning_pass_claimed"] or self.plan["execution_authorized"])
|
||||
|
||||
def test_no_mutable_alias_to_authorities(self):
|
||||
row = next(r for r in self.plan["tasks"] if r["kind"] == "train")
|
||||
before = row["recipe"]["D_command"]
|
||||
try:
|
||||
row["recipe"]["D_command"] = 999
|
||||
original = self.trial["plan"]["blocks"][0]["suites"][0]["arms"][0]["epochs"][0]
|
||||
self.assertEqual(original["D_command"], before)
|
||||
finally:
|
||||
row["recipe"]["D_command"] = before
|
||||
self.assertIsNot(self.plan["provenance"]["frozen_source_sha256"], P.SOURCE_PINS)
|
||||
|
||||
def test_private_loader_ignores_ordinary_module_cache_and_fails_closed_on_source_pin(self):
|
||||
sentinels = {name: object() for name in ("seed_registry", "trial_plan", "evaluation_plan", "evaluation_policy", "R", "E")}
|
||||
with patch.dict(sys.modules, sentinels):
|
||||
loaded = P._load_frozen()
|
||||
self.assertIs(loaded["trial_plan"].seed_registry, loaded["seed_registry"])
|
||||
self.assertIs(loaded["evaluation_policy"].evaluation_plan, loaded["evaluation_plan"])
|
||||
self.assertTrue(all(sys.modules[name] is value for name, value in sentinels.items()))
|
||||
with patch.object(Path, "read_bytes", return_value=b"unregistered mutation"):
|
||||
with self.assertRaisesRegex(ValueError, "Frozen source pin mismatch"):
|
||||
P._load_frozen()
|
||||
|
||||
def test_original_trial_and_policy_mutation_rejected(self):
|
||||
master = self.trial["plan"]["master"]
|
||||
try:
|
||||
self.trial["plan"]["master"] = master + 1
|
||||
with self.assertRaisesRegex(ValueError, "master"):
|
||||
P.build_normal_plan(self.trial, self.evaluation)
|
||||
finally:
|
||||
self.trial["plan"]["master"] = master
|
||||
binding = self.evaluation["config"]["snapshot_bindings"][1]
|
||||
count = binding["completed_epochs"]
|
||||
try:
|
||||
binding["completed_epochs"] += 1
|
||||
with self.assertRaisesRegex(ValueError, "exactly expand"):
|
||||
P.build_normal_plan(self.trial, self.evaluation)
|
||||
finally:
|
||||
binding["completed_epochs"] = count
|
||||
|
||||
def test_validates_exact_reconstruction_and_rejects_rehashed_task_mutation(self):
|
||||
self.assertTrue(P.validate_normal_plan(self.plan, self.trial, self.evaluation))
|
||||
row, original_hash = self.plan["tasks"][0], self.plan["payload_sha256"]
|
||||
try:
|
||||
row["feedback_to_training_or_idle"] = True
|
||||
self.plan["payload_sha256"] = P._sha({k: v for k, v in self.plan.items() if k != "payload_sha256"})
|
||||
with self.assertRaisesRegex(ValueError, "exact reconstruction"):
|
||||
P.validate_normal_plan(self.plan, self.trial, self.evaluation)
|
||||
finally:
|
||||
row["feedback_to_training_or_idle"] = False
|
||||
self.plan["payload_sha256"] = original_hash
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,387 @@
|
||||
"""Pure temporary-file and mock-process tests; no sampler, Torch, brain or GPU."""
|
||||
import copy
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import numpy as np
|
||||
import normal_runner as R
|
||||
import normal_prepare as P
|
||||
|
||||
|
||||
def load_readonly(name, path):
|
||||
spec=importlib.util.spec_from_file_location(name,path)
|
||||
module=importlib.util.module_from_spec(spec)
|
||||
exec(compile(path.read_bytes(),str(path),'exec'),module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
LAB=Path(__file__).resolve().parent.parent/'olfactory-conditioning-lab-v1'
|
||||
COMPOSER=load_readonly('_runner_test_original_composer',LAB/'conditioning_inputs.py')
|
||||
WORKER=load_readonly('_runner_test_original_worker',LAB.parent/'conditioning-interface-v2/isolated_workers.py')
|
||||
|
||||
|
||||
def task(arm='paired', *, requested=True, kind='train', dan='PAM15', number=1):
|
||||
value=dict(task_id=f'block/normal/{arm}/epoch-{number:03d}',kind=kind,steps=1200,
|
||||
block_id='block',arm=arm,mode='physiological',dan_type=dan,
|
||||
compartment_verbatim="y5B'2a" if dan=='PAM15' else "y2a'1",
|
||||
delta_dependency=dict(kind='zero',source=None),feedback_to_training_or_idle=kind=='train')
|
||||
if kind=='probe':
|
||||
value['recipe']=dict(US_requested=False,D_command=0,weight_updates_enabled=False)
|
||||
else:
|
||||
value['recipe']=dict(us=dict(nominal_slot_tick=900,rng_seed=None,rng_draws=0,
|
||||
requested=requested,tick=900 if requested else None),
|
||||
D_command=1. if requested and arm!='d_zero' else 0.,update_enabled=arm!='frozen')
|
||||
return value
|
||||
|
||||
|
||||
class RunnerTests(unittest.TestCase):
|
||||
def test_runtime_array_closure_matches_original_worker_not_directory_glob(self):
|
||||
self.assertEqual(P.GRAPH_FILES,WORKER.GRAPH_FILES)
|
||||
self.assertEqual(P.APL_FILES,WORKER.APL_FILES)
|
||||
with tempfile.TemporaryDirectory() as folder:
|
||||
root=Path(folder);graph=root/'graph';apl=root/'apl'
|
||||
graph.mkdir();apl.mkdir()
|
||||
# Additional reference arrays are neither consumed nor required.
|
||||
for name in ('apl_out_ids.npy','input_raw.npy','output_raw.npy','pn_globals.npy'):
|
||||
(apl/name).touch()
|
||||
template=dict(graph_dir=str(graph),apl_bundle_dir=str(apl),coefficients_path=str(root/'coeff.json'))
|
||||
paths=P.runtime_array_paths(template)
|
||||
expected={str(graph/name) for name in WORKER.GRAPH_FILES} | {
|
||||
str(apl/name) for name in WORKER.APL_FILES} | {template['coefficients_path']}
|
||||
self.assertEqual(paths,expected);self.assertEqual(len(paths),12)
|
||||
|
||||
def setUp(self):
|
||||
temporary=tempfile.TemporaryDirectory();self.addCleanup(temporary.cleanup)
|
||||
self.root=Path(temporary.name).resolve()
|
||||
for rel in ('protocol','jobs','cases','runs','updates','validation','results','receipts','logs','audit'):
|
||||
(self.root/rel).mkdir()
|
||||
self.addCleanup(patch.stopall)
|
||||
patch.object(R,'EXP',self.root).start()
|
||||
self.regfile=self.root/'protocol/preregistered.json';R.save(self.regfile,{'synthetic':True})
|
||||
self.sha=R.digest(self.regfile)
|
||||
self.w=R.Workflow.__new__(R.Workflow);self.w.sha=self.sha
|
||||
self.w.start=time.perf_counter();self.w.completed=set();self.w.expected=[];self.w.tasks={}
|
||||
self.w.overlay_dependency_pins={};self.w.case_dependency_pins={}
|
||||
self.w.reg=dict(budget=dict(output_cap_bytes=8<<20,minimum_free_reserve_bytes=0,
|
||||
workflow_timeout_seconds=60,child_timeout_seconds=10,not_after_utc='2099-01-01T00:00:00+00:00',
|
||||
next_child_headroom_bytes=65536),runtime_input_sha256={},
|
||||
input_sha256={},initial_overlay=dict(overlay_file=str(self.root/'protocol/zero.npz'),
|
||||
overlay_manifest=str(self.root/'protocol/zero.json')))
|
||||
R.save_npz(self.root/'protocol/zero.npz',dict(plastic_delta_mv=np.zeros(2,np.float32)))
|
||||
R.save(self.root/'protocol/zero.json',dict(synthetic=True))
|
||||
initial={p.relative_to(self.root).as_posix():R.identity(p) for p in (self.root/'protocol').iterdir()}
|
||||
self.w.ledger=R.Ledger(self.root,self.sha,initial,8<<20,0)
|
||||
|
||||
def test_original_composer_no_US_D0_frozen_and_PPL_requests(self):
|
||||
cs=dict(tick=np.array([10,20],np.int32),neuron_idx=np.array([3,4],np.int32))
|
||||
for arm,requested,dan in (('paired',False,'PAM15'),('d_zero',True,'PAM15'),
|
||||
('frozen',True,'PAM15'),('paired',True,'PPL103')):
|
||||
item=task(arm,requested=requested,dan=dan)
|
||||
ids=np.array([10,11,12,13] if dan=='PAM15' else [14,15],np.int32)
|
||||
composed,us=R.compose_requests(cs,ids,item,COMPOSER)
|
||||
self.assertEqual(len(us['tick']),len(ids) if requested else 0)
|
||||
self.assertEqual(composed['audit']['US_attempts'],len(us['tick']))
|
||||
self.assertEqual(item['recipe']['D_command'],0. if not requested or arm=='d_zero' else 1.)
|
||||
self.assertEqual(item['recipe']['update_enabled'],arm!='frozen')
|
||||
if requested:self.assertTrue(np.array_equal(us['neuron_idx'],ids))
|
||||
bad=task('d_zero');bad['recipe']['D_command']=1.
|
||||
with self.assertRaisesRegex(ValueError,'D/update'):R.compose_requests(cs,ids,bad,COMPOSER)
|
||||
|
||||
def test_probe_refuses_US_update_or_feedback(self):
|
||||
cs=dict(tick=np.array([7],np.int32),neuron_idx=np.array([3],np.int32))
|
||||
value=task(kind='probe');combined,us=R.compose_requests(cs,np.array([9,10],np.int32),value,COMPOSER)
|
||||
self.assertEqual(len(us['tick']),0);self.assertEqual(combined['audit']['US_attempts'],0)
|
||||
for role in ('US_requested','weight_updates_enabled','feedback_to_training_or_idle'):
|
||||
bad=copy.deepcopy(value)
|
||||
(bad if role=='feedback_to_training_or_idle' else bad['recipe'])[role]=True
|
||||
with self.assertRaisesRegex(ValueError,'Probe command'):R.compose_requests(cs,np.array([9,10],np.int32),bad,COMPOSER)
|
||||
|
||||
def test_frozen_clock_and_reset_seed_retained(self):
|
||||
original=dict(kind='fullgraph',dt_ms=.1,apl_delay_steps=18,precision='float64',
|
||||
apl_precision='float32',record_history=False,seed=1234,training=False,cs_input_seed=999)
|
||||
actual=R.derive_spec(original,task(),budget_root=self.root,output_cap=123456)
|
||||
self.assertEqual(actual['seed'],1234);self.assertEqual(actual['steps'],1200)
|
||||
self.assertEqual(actual['duration_ms'],120.);self.assertNotIn('cs_input_seed',actual)
|
||||
self.assertFalse(actual['within_trial_weight_updates']);self.assertFalse(original['training'])
|
||||
with self.assertRaisesRegex(ValueError,'fixed D18'):R.derive_spec(dict(original,apl_delay_steps=0),task(),budget_root=self.root,output_cap=1)
|
||||
|
||||
def test_actual_successful_parent_receipt_commits_ledger(self):
|
||||
output=self.root/'runs/synthetic.txt'
|
||||
job=dict(kind='cpu_verify',input_sha256={str(self.regfile):self.sha})
|
||||
def fake_run(argv,**kwargs):
|
||||
self.assertEqual(kwargs['env']['CUDA_VISIBLE_DEVICES'],'')
|
||||
self.assertEqual(kwargs['env']['PYTHONDONTWRITEBYTECODE'],'1')
|
||||
kwargs['stdout'].write(b'synthetic child only\n');output.write_bytes(b'new immutable output')
|
||||
return SimpleNamespace(returncode=0)
|
||||
with patch.object(R.subprocess,'run',side_effect=fake_run) as run:
|
||||
self.w.launch('unit',job,['not-a-real-executable'],[output])
|
||||
self.assertEqual(run.call_count,1);self.assertIn('unit',self.w.completed)
|
||||
self.assertTrue(self.w.ledger.final_verify(['unit'])['pass_all'])
|
||||
process=R.read(self.root/'receipts/unit/process.json')
|
||||
self.assertEqual(process['exit_code'],0);self.assertTrue(process['complete'])
|
||||
with self.assertRaisesRegex(ValueError,'rerun committed'):
|
||||
self.w.launch('unit',job,['not-real'],[output])
|
||||
|
||||
def test_failed_child_is_uncommitted_unknown_and_cannot_rerun(self):
|
||||
job=dict(kind='cpu_verify',input_sha256={str(self.regfile):self.sha})
|
||||
with patch.object(R.subprocess,'run',return_value=SimpleNamespace(returncode=9)):
|
||||
with self.assertRaisesRegex(ValueError,'Child failed'):self.w.launch('failed',job,['not-real'],[])
|
||||
receipt=R.read(self.root/'receipts/failed/process.json')
|
||||
self.assertFalse(receipt['complete']);self.assertEqual(receipt['exit_code'],9)
|
||||
self.assertEqual(self.w.ledger.inspect()['uncommitted_entry_ids'],['failed'])
|
||||
with self.assertRaises(FileExistsError):self.w.launch('failed',job,['not-real'],[])
|
||||
|
||||
def test_timed_out_child_never_gets_success_commit(self):
|
||||
job=dict(kind='cpu_verify',input_sha256={str(self.regfile):self.sha})
|
||||
with patch.object(R.subprocess,'run',side_effect=subprocess.TimeoutExpired('not-real',10)):
|
||||
with self.assertRaisesRegex(ValueError,'Child failed'):self.w.launch('timeout',job,['not-real'],[])
|
||||
receipt=R.read(self.root/'receipts/timeout/process.json')
|
||||
self.assertTrue(receipt['timed_out']);self.assertIsNone(receipt['exit_code'])
|
||||
self.assertNotIn('timeout',self.w.completed)
|
||||
|
||||
def test_spawn_OSerror_retains_failed_receipt_without_fake_exit(self):
|
||||
job=dict(kind='cpu_verify',input_sha256={str(self.regfile):self.sha})
|
||||
with patch.object(R.subprocess,'run',side_effect=OSError('synthetic spawn failure')):
|
||||
with self.assertRaisesRegex(ValueError,'Child failed'):self.w.launch('spawn-error',job,['not-real'],[])
|
||||
receipt=R.read(self.root/'receipts/spawn-error/process.json')
|
||||
self.assertFalse(receipt['complete']);self.assertIsNone(receipt['exit_code'])
|
||||
self.assertFalse(receipt['exit_observed_by_parent']);self.assertIn('synthetic spawn failure',receipt['launch_error'])
|
||||
self.assertEqual(self.w.ledger.inspect()['uncommitted_entry_ids'],['spawn-error'])
|
||||
|
||||
def test_after_process_input_mutation_stops_before_commit(self):
|
||||
dependency=self.root/'protocol/input.json';R.save(dependency,dict(value=1))
|
||||
job=dict(kind='cpu_verify',input_sha256={str(dependency):R.digest(dependency)})
|
||||
def fake_run(*a,**k):
|
||||
dependency.write_bytes(b'{"value":2}');return SimpleNamespace(returncode=0)
|
||||
with patch.object(R.subprocess,'run',side_effect=fake_run):
|
||||
with self.assertRaisesRegex(ValueError,'Pinned input changed'):self.w.launch('mutation',job,['not-real'],[])
|
||||
self.assertNotIn('mutation',self.w.completed)
|
||||
|
||||
def _delta_fixture(self):
|
||||
old=task();new=task(number=2);new['delta_dependency']=dict(kind='epoch_delta_after',source=old['task_id']+'/delta-after')
|
||||
self.w.tasks={old['task_id']:old};key=R.task_key(old)
|
||||
self.w.completed.add(key+'--verify')
|
||||
output=self.root/'updates'/key;output.mkdir()
|
||||
R.save_npz(output/'delta-after.npz',dict(plastic_delta_mv=np.array([-.25,0.],np.float32)))
|
||||
R.save(output/'overlay-manifest.json',dict(synthetic=True))
|
||||
validation=self.root/'validation/previous.json';R.save(validation,dict(complete=True,
|
||||
after_overlay_sha256=R.digest(output/'delta-after.npz'),after_manifest_sha256=R.digest(output/'overlay-manifest.json')))
|
||||
process=self.root/f'receipts/{key}--verify/process.json';process.parent.mkdir()
|
||||
R.save(process,dict(complete=True,exit_code=0,
|
||||
entry_id=key+'--verify',registration_sha256=self.sha))
|
||||
overlay=dict(overlay_file=str(output/'delta-after.npz'),overlay_manifest=str(output/'overlay-manifest.json'))
|
||||
result=self.root/f'results/{key}.json'
|
||||
R.save(result,dict(complete=True,task=old,cpu_validation=R.pin(validation),after_overlay=overlay,
|
||||
cpu_process_receipt_path=str(process),update_dir=str(output)))
|
||||
for path in (result,validation,process,output/'delta-after.npz',output/'overlay-manifest.json'):
|
||||
self.w.ledger._tracked[path.relative_to(self.root).as_posix()]=R.identity(path)
|
||||
return old,new,overlay,result,validation
|
||||
|
||||
def test_delta_dependency_requires_same_branch_completed_verify_and_receipt(self):
|
||||
old,new,overlay,result,validation=self._delta_fixture()
|
||||
self.w.completed.clear()
|
||||
with self.assertRaisesRegex(ValueError,'CPU validation missing'):self.w.overlay(new)
|
||||
self.w.completed.add(R.task_key(old)+'--verify')
|
||||
self.assertEqual(self.w.overlay(new),overlay)
|
||||
self.assertIn(str(result),self.w.overlay_dependency_pins)
|
||||
self.assertIn(str(validation),self.w.overlay_dependency_pins)
|
||||
for field in ('arm','block_id'):
|
||||
altered=copy.deepcopy(new);altered[field]='unrelated'
|
||||
with self.assertRaisesRegex(ValueError,'unrelated branch'):self.w.overlay(altered)
|
||||
validation.write_bytes(b'{}')
|
||||
with self.assertRaisesRegex(ValueError,'committed bytes'):self.w.overlay(new)
|
||||
|
||||
def test_alternate_valid_overlay_cannot_replace_previous_verified_delta(self):
|
||||
_,new,_,result,_=self._delta_fixture()
|
||||
alternative=self.root/'updates/other-valid';alternative.mkdir()
|
||||
R.save_npz(alternative/'delta-after.npz',dict(plastic_delta_mv=np.array([-.5,0.],np.float32)))
|
||||
R.save(alternative/'overlay-manifest.json',dict(synthetic=True,other=True))
|
||||
for path in alternative.iterdir():self.w.ledger._tracked[path.relative_to(self.root).as_posix()]=R.identity(path)
|
||||
record=R.read(result);record['update_dir']=str(alternative)
|
||||
record['after_overlay']={k:str(alternative/name) for k,name in
|
||||
(('overlay_file','delta-after.npz'),('overlay_manifest','overlay-manifest.json'))}
|
||||
result.write_text(R.canonical(record),encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError,'committed bytes'):self.w.overlay(new)
|
||||
# Even a synthetic "committed" bad result must fail its independent CPU output binding.
|
||||
self.w.ledger._tracked[result.relative_to(self.root).as_posix()]=R.identity(result)
|
||||
with self.assertRaisesRegex(ValueError,'independently verified output'):self.w.overlay(new)
|
||||
|
||||
def test_zero_dependency_does_not_carry_previous_lineage_pins(self):
|
||||
self.w.overlay_dependency_pins={'stale':'0'*64}
|
||||
self.assertEqual(self.w.overlay(task()),self.w.reg['initial_overlay'])
|
||||
self.assertEqual(self.w.overlay_dependency_pins,{})
|
||||
|
||||
def _case_fixture(self):
|
||||
item=task();template=self.root/'protocol/case-template.json'
|
||||
R.save(template,dict(kind='fullgraph',dt_ms=.1,apl_delay_steps=18,precision='float64',
|
||||
apl_precision='float32',record_history=False,seed=1234))
|
||||
population=self.root/'protocol/populations.npz'
|
||||
self.w.populations=dict(PAM15=np.array([10,11,12,13],np.int32),PPL103=np.array([14,15],np.int32))
|
||||
R.save_npz(population,self.w.populations);self.w.reg['population_file']=str(population)
|
||||
self.w.reg['input_sha256'][str(population)]=R.digest(population)
|
||||
directory=self.root/'inputs/generated';directory.mkdir(parents=True)
|
||||
source=directory/'source.npz';audit=directory/'source.json'
|
||||
R.save_npz(source,dict(tick=np.array([5],np.int32),neuron_idx=np.array([3],np.int32)))
|
||||
descriptor=dict(synthetic=True)
|
||||
R.save(audit,dict(descriptor=descriptor,requests_sha256=R.digest(source)))
|
||||
self.w.input_plan=dict(task_inputs={item['task_id']:'source'},descriptors={'source':descriptor})
|
||||
self.w.inputs=COMPOSER
|
||||
for path in (template,population,source,audit):
|
||||
self.w.ledger._tracked[path.relative_to(self.root).as_posix()]=R.identity(path)
|
||||
return item,template,source,audit
|
||||
|
||||
def test_prepare_case_reads_only_committed_template_and_shared_CS(self):
|
||||
item,template,source,audit=self._case_fixture()
|
||||
directory=self.w.prepare_case(item)
|
||||
self.assertEqual(R.read(directory/'spec.json')['seed'],1234)
|
||||
self.assertTrue({str(template),str(source),str(audit)} <= set(self.w.case_dependency_pins))
|
||||
self.assertEqual(R.npz(directory/'us_requests.npz')['tick'].tolist(),[900]*4)
|
||||
|
||||
def test_changed_case_template_is_rejected_before_new_spec_write(self):
|
||||
item,template,_,_=self._case_fixture();value=R.read(template);value['seed']=9876
|
||||
template.write_text(R.canonical(value),encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError,'committed bytes'):self.w.prepare_case(item)
|
||||
self.assertFalse((self.root/'cases'/R.task_key(item)/'spec.json').exists())
|
||||
|
||||
def test_changed_CS_and_self_rehashed_audit_are_both_rejected(self):
|
||||
item,_,source,audit=self._case_fixture()
|
||||
with source.open('wb') as stream:np.savez_compressed(stream,tick=np.array([9],np.int32),neuron_idx=np.array([4],np.int32))
|
||||
value=R.read(audit);value['requests_sha256']=R.digest(source)
|
||||
audit.write_text(R.canonical(value),encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError,'committed bytes'):self.w.prepare_case(item)
|
||||
self.assertFalse((self.root/'cases'/R.task_key(item)/'requests.npz').exists())
|
||||
|
||||
def test_exclusive_helpers_reject_linked_parent_before_writes(self):
|
||||
destination=self.root/'external';destination.mkdir();link=self.root/'alias'
|
||||
try:link.symlink_to(destination,target_is_directory=True)
|
||||
except OSError:self.skipTest('Platform disallows temporary symlinks')
|
||||
for filename,write in (('x.json',lambda p:R.save(p,{'a':1})),
|
||||
('x.npz',lambda p:R.save_npz(p,{'a':np.array([1],np.int32)}))):
|
||||
with self.assertRaisesRegex(ValueError,'linked path'):write(link/filename)
|
||||
self.assertFalse((destination/filename).exists())
|
||||
|
||||
def _mock_task(self,item):
|
||||
"""Exercise real orchestration/control closures, with no scientific child."""
|
||||
validator=self.root/'validator.py';validator.write_bytes(b'# not executed\n')
|
||||
self.w.reg['input_sha256'][str(validator)]=R.digest(validator)
|
||||
patch.object(R,'AQ',self.root).start()
|
||||
target=self.root/'validate_update_cpu.py';target.write_bytes(validator.read_bytes())
|
||||
self.w.reg['input_sha256'][str(target)]=R.digest(target)
|
||||
for name in ('conditioning_epoch.py','conditioning_preflight_compare.py','engineering_compare.py'):
|
||||
self.w.reg['input_sha256'][str(LAB/name)]=R.digest(LAB/name)
|
||||
R.save(self.root/'protocol/epoch-template.json',dict(schema='synthetic',files={},frozen_inputs={}))
|
||||
self.w.ledger._tracked['protocol/epoch-template.json']=R.identity(self.root/'protocol/epoch-template.json')
|
||||
calls=[];authorities=[]
|
||||
def case(task_value):
|
||||
result=self.root/'cases'/R.task_key(task_value);result.mkdir()
|
||||
R.save(result/'spec.json',dict(steps=1200));R.save_npz(result/'requests.npz',dict(tick=np.empty(0,np.int32),neuron_idx=np.empty(0,np.int32)))
|
||||
return result
|
||||
def ap_job(name,kind,output,**kwargs):
|
||||
return dict(kind=kind,output_dir=str(output),receipt_file=str(self.root/f'receipts/{name}/worker.json'),
|
||||
input_sha256={},authority_file=str(kwargs.get('authority','')))
|
||||
def launch(name,job,argv,outputs,*,pre_outputs=(),post=None,ap=False):
|
||||
calls.append(job['kind'])
|
||||
if job['kind']=='brain':
|
||||
out=Path(job['output_dir']);out.mkdir();R.save(out/'checkpoint-manifest.json',dict(synthetic=True))
|
||||
R.save_npz(out/'state.npz',dict(step=np.empty(0,np.int32)))
|
||||
for filename in ('process.json','worker.json'):
|
||||
receipt=self.root/f'receipts/{name}/{filename}';receipt.parent.mkdir(exist_ok=True)
|
||||
R.save(receipt,dict(synthetic=True))
|
||||
self.w.ledger._tracked[receipt.relative_to(self.root).as_posix()]=R.identity(receipt)
|
||||
elif job['kind']=='update':
|
||||
authorities.append(R.read(job['authority_file']))
|
||||
out=Path(job['output_dir']);out.mkdir()
|
||||
R.save_npz(out/'delta-after.npz',dict(plastic_delta_mv=np.zeros(2,np.float32)))
|
||||
R.save(out/'overlay-manifest.json',{});R.save(out/'chain-receipt.json',{})
|
||||
else:
|
||||
out=Path(job['update_dir'])
|
||||
R.save(job['receipt_file'],dict(complete=True,frozen_U_verify_receipt_recomputed=True,
|
||||
actual_sealed_events_used=True,after_overlay_sha256=R.digest(out/'delta-after.npz'),
|
||||
epoch_authority_sha256=job['authority_sha256']))
|
||||
if post is not None:post()
|
||||
self.w.completed.add(name)
|
||||
with patch.object(self.w,'prepare_case',side_effect=case),patch.object(self.w,'ap_job',side_effect=ap_job),\
|
||||
patch.object(self.w,'launch',side_effect=launch),patch.object(self.w,'brain_verify',return_value={'synthetic':True}):
|
||||
self.w.task(item)
|
||||
return calls,authorities,R.read(self.root/f'results/{R.task_key(item)}.json')
|
||||
|
||||
def test_probe_orchestration_never_calls_E_or_CPU_update(self):
|
||||
calls,authorities,record=self._mock_task(task(kind='probe'))
|
||||
self.assertEqual(calls,['brain']);self.assertEqual(authorities,[])
|
||||
self.assertNotIn('after_overlay',record);self.assertNotIn('cpu_validation',record)
|
||||
|
||||
def test_training_no_US_preserves_None_and_zero_D(self):
|
||||
calls,authorities,record=self._mock_task(task(requested=False))
|
||||
self.assertEqual(calls,['brain','update','cpu_verify'])
|
||||
self.assertIsNone(authorities[0]['command']['us_tick'])
|
||||
self.assertEqual(authorities[0]['command']['d_command'],0.)
|
||||
self.assertFalse(authorities[0]['command']['frozen']);self.assertIn('after_overlay',record)
|
||||
|
||||
def test_D0_keeps_US_but_passes_zero_D_to_original_E(self):
|
||||
calls,authorities,_=self._mock_task(task('d_zero'))
|
||||
self.assertEqual(calls,['brain','update','cpu_verify'])
|
||||
self.assertEqual(authorities[0]['command']['us_tick'],900)
|
||||
self.assertEqual(authorities[0]['command']['d_command'],0.)
|
||||
self.assertFalse(authorities[0]['command']['frozen'])
|
||||
|
||||
def test_frozen_keeps_D_request_but_explicitly_disables_update(self):
|
||||
_,authorities,_=self._mock_task(task('frozen'))
|
||||
self.assertEqual(authorities[0]['command']['d_command'],1.)
|
||||
self.assertTrue(authorities[0]['command']['frozen'])
|
||||
|
||||
def test_PPL_compartment_not_replaced_by_PAM_or_sign_flip(self):
|
||||
_,authorities,_=self._mock_task(task(dan='PPL103'))
|
||||
self.assertEqual(authorities[0]['command']['compartment'],"y2a'1")
|
||||
self.assertEqual(authorities[0]['command']['d_command'],1.)
|
||||
self.assertEqual(authorities[0]['command']['trace_backend'],'torch')
|
||||
|
||||
def test_partial_task_cannot_silently_resume_remaining_children(self):
|
||||
item=task();self.w.completed.add(R.task_key(item)+'--brain')
|
||||
with patch.object(self.w,'launch') as launch:
|
||||
with self.assertRaisesRegex(ValueError,'Partially completed task'):self.w.task(item)
|
||||
launch.assert_not_called()
|
||||
|
||||
def test_real_AP_validation_accepts_brain_job_and_rejects_protected_outputs(self):
|
||||
# Actual frozen parser only, using small synthetic files, no runtime load.
|
||||
frozen=self.root/'frozen';frozen.mkdir();graph=frozen/'graph';graph.mkdir();apl=frozen/'apl';apl.mkdir()
|
||||
for name in WORKER.GRAPH_FILES:(graph/name).write_bytes(b'synthetic graph bytes')
|
||||
for name in WORKER.APL_FILES:(apl/name).write_bytes(b'synthetic APL bytes')
|
||||
for name in ('mask.npy','base.npy','coeff.json'):(frozen/name).write_bytes(b'synthetic authority')
|
||||
case=self.root/'cases/first';case.mkdir()
|
||||
R.save(case/'spec.json',dict(graph_dir=str(graph),apl_bundle_dir=str(apl),coefficients_path=str(frozen/'coeff.json')))
|
||||
R.save_npz(case/'requests.npz',dict(tick=np.empty(0,np.int32),neuron_idx=np.empty(0,np.int32)))
|
||||
overlay=self.w.reg['initial_overlay'];manifest=Path(overlay['overlay_manifest'])
|
||||
am=LAB.parent/'wholebrain-plastic-interface-v1/overlay.py'
|
||||
manifest.write_text(R.canonical(dict(mask_path=str(frozen/'mask.npy'),mask_sha256=R.digest(frozen/'mask.npy'),
|
||||
base_candidate_path=str(frozen/'base.npy'),base_candidate_sha256=R.digest(frozen/'base.npy'),
|
||||
am_overlay_path=str(am),am_overlay_sha256=R.digest(am))),encoding='utf-8')
|
||||
self.w.reg['runtime_input_sha256']={p:v['sha256'] for p,v in R.inventory(frozen).items()}
|
||||
self.w.reg['runtime_input_sha256'][str(am)]=R.digest(am);self.w.h=WORKER
|
||||
name='parser-brain';job=self.w.ap_job(name,'brain',self.root/'runs/first',case=case,overlay=overlay)
|
||||
Path(job['receipt_file']).parent.mkdir()
|
||||
file=self.root/'jobs/parser.json';R.save(file,job)
|
||||
parsed,paths,_,_=WORKER.validate_job(file,R.digest(file),'brain')
|
||||
self.assertEqual(parsed['diagnostic_mode'],'light');self.assertFalse(paths['output'].exists())
|
||||
for field in ('output_dir','receipt_file','build_root'):
|
||||
altered=copy.deepcopy(job);altered[field]=str(case/('forbidden-'+field))
|
||||
alternative=self.root/'jobs'/(field+'.json');R.save(alternative,altered)
|
||||
with self.assertRaisesRegex(ValueError,'protected input/source'):
|
||||
WORKER.validate_job(alternative,R.digest(alternative),'brain')
|
||||
self.assertFalse((case/'forbidden-output_dir').exists())
|
||||
|
||||
def test_separate_receipt_directories_allow_original_worker_lineage_protection(self):
|
||||
# Real AP path validator should not interpret a previous receipt as
|
||||
# authorizing writes into its parent. New receipts must be siblings.
|
||||
prior=self.root/'receipts/previous';prior.mkdir()
|
||||
previous=prior/'process.json';R.save(previous,dict(synthetic=True))
|
||||
self.w.overlay_dependency_pins={str(previous):R.digest(previous)}
|
||||
self.test_real_AP_validation_accepts_brain_job_and_rejects_protected_outputs()
|
||||
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,37 @@
|
||||
"""Pure temporary-file supervisor bookkeeping tests, no actual child launch."""
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
import run_normal as R
|
||||
|
||||
class SupervisorTests(unittest.TestCase):
|
||||
def test_launch_is_exclusive_not_completion(self):
|
||||
with tempfile.TemporaryDirectory() as temp,patch.object(R,'CONTROL',Path(temp)),patch.object(R,'authority',return_value={}):
|
||||
with patch.object(R.subprocess,'Popen',return_value=SimpleNamespace(pid=123)) as spawn:
|
||||
record=R.launch('a'*64)
|
||||
self.assertEqual(spawn.call_count,1)
|
||||
self.assertTrue(spawn.call_args.kwargs['start_new_session'])
|
||||
self.assertFalse(record['final_exit_observed'])
|
||||
self.assertFalse((Path(temp)/'exit.json').exists())
|
||||
with self.assertRaises(ValueError):R.launch('a'*64)
|
||||
self.assertEqual(spawn.call_count,1)
|
||||
|
||||
def test_final_exit_is_parent_observed_not_learning(self):
|
||||
with tempfile.TemporaryDirectory() as temp,patch.object(R,'CONTROL',Path(temp)),patch.object(R,'authority',return_value={}):
|
||||
with patch.object(R.subprocess,'run',return_value=SimpleNamespace(returncode=0)):
|
||||
self.assertEqual(R.supervise('b'*64),0)
|
||||
record=R.read(Path(temp)/'exit.json')
|
||||
self.assertTrue(record['complete'] and record['final_exit_observed'])
|
||||
self.assertFalse(record['learning_success_claimed'])
|
||||
|
||||
def test_failed_spawn_has_no_fabricated_exit(self):
|
||||
with tempfile.TemporaryDirectory() as temp,patch.object(R,'CONTROL',Path(temp)),patch.object(R,'authority',return_value={}):
|
||||
with patch.object(R.subprocess,'run',side_effect=OSError('fixture')):
|
||||
self.assertEqual(R.supervise('b'*64),1)
|
||||
record=R.read(Path(temp)/'exit.json')
|
||||
self.assertIsNone(record['exit_code'])
|
||||
self.assertFalse(record['complete'] or record['final_exit_observed'])
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
@@ -0,0 +1,43 @@
|
||||
# CPU / GPU 方案保存 — 2026-10-01
|
||||
|
||||
用户要求保存当前方案并上传,之后再继续。**原 Phase4AR 保持停止,未训练、未安装新权重,未进入下一科学阶段。**
|
||||
|
||||
## 保存内容
|
||||
|
||||
| 方案 | 代码 | 状态 |
|
||||
|---|---|---|
|
||||
| 原 CPU 更新与独立验证 | `models/male-cns-lif/olfactory-conditioning-lab-v1/`、`conditioning-interface-v2/` | 注册实现保留,未替换 |
|
||||
| V100/4090 eligibility 更新原型 | `models/male-cns-lif/conditioning-acceleration-v1/` | 固定案例逐位回放 PASS,不是全脑已迁移到 V100 |
|
||||
| CPU 常驻与 4090 全脑常驻 | `models/male-cns-lif/conditioning-pipeline-acceleration-v1/` | 42 次全脑精确回放 PASS,不是已验收生产运行时 |
|
||||
|
||||
本目录的 `gpu/`、`pipeline/` 保存原报告、manifest 与完整性说明的原字节副本;`publication-catalog.json` 逐项记录公开归档成员和有意排除项。完整数值回放、请求、状态和诊断回执封装在 `artifacts/acceleration-20261001/` 的两个 Git LFS 归档中。
|
||||
|
||||
代码版本:GPU 核心 `221e1f13f758ebe8d9f188bab976c361f7cacf45`;常驻回放封存 `018f038c7857c7e0236dd7408a680458520d92ce`。原科学登记源码 `80aeb2093db655329774eff7b32fb6e417b8b40b` 不变。
|
||||
|
||||
原科学现场停在 1,033 轮已提交且 CPU 校验的训练、138 个已提交 probe。完整科学执行、独立学习 gate 未完成;本次性能成果不代表学会关联记忆。
|
||||
|
||||
## 来源、许可与排除
|
||||
|
||||
MaleCNS v1.0 原数据来源为 [官方数据页](https://male-cns.janelia.org/download/),既有许可审计为 CC BY 4.0。署名保留 Male CNS collaboration:FlyEM/HHMI Janelia、University of Cambridge、MRC Laboratory of Molecular Biology、Google Research 及原论文作者。本项目进行了既有 neuron-only 过滤/重编号和模型模拟;本次只原字节复制已生成的回放数据,不重新推导或修改科学数值。
|
||||
|
||||
嗅觉输入来源链中的 DoOR.data 2.0.1(commit `eea72d64b42a4e91dafe822cf0b5204de33f8d34`)维持 CC BY-SA 4.0,作者 Daniel Münch、C. Giovanni Galizia、Shouwen Ma、Martin Strauch、Anja Nissler。涉及其派生输入的成员保留此 ShareAlike/署名约束;不将其许可泛化至无关代码。[DoOR 论文](https://doi.org/10.1038/srep21841)。Shiu 作者源码维持其原 MIT 声明;本项目是 adapted dynamics,不是严格原模型复现。
|
||||
|
||||
原资源许可证据及上游 notices 在 `codex/lfs-public-resources` 的 `registry/publication-20261001/`,固定发布提交 `5b1d1b7`。本次没有打包 NVIDIA SDK、CuPy/PyTorch 环境、FlyVis、论文全文或其他服务。软件没有被擅自统一换证,仍适用仓库 NOTICE 和各上游声明。
|
||||
|
||||
明确排除:虚拟环境、CUDA 编译缓存/中间产物/二进制、安装下载日志。完整原实验(包括失败与编译诊断)仍原样留在服务器;原 sealed manifest 包含未上传缓存的哈希。因此公开归档应使用 **publication-catalog.json** 校验,不能要求原始全目录 SHA 清单在省略缓存的副本中全部通过。没有丢弃科学失败案例。
|
||||
|
||||
旧原始/参考大数据不重复上传,它们在 `codex/lfs-public-resources`。本次发布不是全服务器或全部历史科学目录灾备,也没有打包已停止 AR 的所有 64,034 个现场文件。
|
||||
|
||||
## 恢复与验证(不运行模型)
|
||||
|
||||
在新目录 clone 本分支,安装 Git LFS,执行:
|
||||
|
||||
```sh
|
||||
git lfs pull --include='artifacts/acceleration-20261001/**'
|
||||
python3 -B tools/acceleration-publication/archive_results.py verify
|
||||
```
|
||||
|
||||
验证器只读流式校验归档 SHA、成员集合、每个成员字节数与 SHA,不解包、不运行模型。
|
||||
如需解包,只解到新建空目录;不得覆盖 `/data/digital-drosophila` 或直接运行旧封存脚本。性能原型依赖固定科学源与历史输入,不能只 clone 就自动恢复正式训练。
|
||||
|
||||
`delivery.json` 只在真实远端 push、独立新 LFS store 下载和完整成员验证成功后写入。没有该回执时,不能把打包完成称为异机恢复已通过。
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"branch": "codex/v100-conditioning-acceleration",
|
||||
"catalog_sha256": "28071f276848ea60149f21a9794653486b404670a58b34d97b1aaae742095245",
|
||||
"complete_training_restore": false,
|
||||
"data_commit": "f2de8797372b2d7558a0547e450928fdc231b860",
|
||||
"downloaded_LFS_objects": 2,
|
||||
"downloaded_bytes": 76447085,
|
||||
"fresh_download_proven": true,
|
||||
"fsck_exit_code": 0,
|
||||
"groups": {
|
||||
"gpu": {
|
||||
"archive_bytes": 1679158,
|
||||
"files": 614,
|
||||
"original_bytes": 13242628,
|
||||
"sha256": "50acdc85342a2c79c3516e50ee4542b909813d179518451edaaf2d94150c534b",
|
||||
"verified": true
|
||||
},
|
||||
"pipeline": {
|
||||
"archive_bytes": 74767927,
|
||||
"files": 1066,
|
||||
"original_bytes": 103062185,
|
||||
"sha256": "fdc39013d71fb7d14313d8249c929601a8a7050cc2eac88b733d692bbe1b6b42",
|
||||
"verified": true
|
||||
}
|
||||
},
|
||||
"historical_scientific_gate_reexecuted": false,
|
||||
"initial_LFS_objects": 0,
|
||||
"pass_all": true,
|
||||
"pull_exit_code": 0,
|
||||
"remote": "ssh://git@192.168.10.31:2222/qishizhe/digital-drosophila.git",
|
||||
"schema": "acceleration-fresh-remote-delivery-v1",
|
||||
"scientific_experiments_run": 0,
|
||||
"scope": "Remote Git commit, two actual LFS downloads, complete public archive contents and 22 sealed code files; not all external scientific dependencies",
|
||||
"sealed_source_files_checked": 22,
|
||||
"training_resumed": false,
|
||||
"transport": "Previously audited LAN-pinned HTTPS adapter, verified TLS and SSH short-lived authorization",
|
||||
"verification": "Full streamed members, no extraction or model execution",
|
||||
"verified_utc": "2026-10-01T07:46:04.143650+00:00",
|
||||
"wall_seconds": 3.1022417009999117
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# V100 conditioning acceleration — engineering replay result
|
||||
|
||||
Status: **PASS-ELIGIBILITY-UPDATE-REPLAY-EQUIVALENCE**. This is not a learning result or a production-training promotion.
|
||||
|
||||
Benchmark code commit: `221e1f13f758ebe8d9f188bab976c361f7cacf45`.
|
||||
|
||||
| Device | Real-fixture replay median (prep + transfers + comparison) | Resident CUDA kernel median |
|
||||
|---|---:|---:|
|
||||
| Tesla V100-SXM2-16GB (v100a-02) | 3.430 ms | 0.122 ms |
|
||||
| Tesla V100-SXM2-16GB (v100b-01) | 3.344 ms | 0.122 ms |
|
||||
| NVIDIA GeForce RTX 4090 (rtx4090-01) | 3.327 ms | 0.074 ms |
|
||||
|
||||
Each GPU passed14sealed real fixtures +16fixed synthetic cases, with sampled trace, final trace, allUS snapshots and delta byte-identical to the original independent CPU oracle. Six invalid inputs were rejected on each GPU.
|
||||
|
||||
CPU warm reference includes the original API's repeated provenance checks and AST parsing; it is only one warm sample perfixture. GPU authenticates the source and complete anatomical mapping once. Therefore ratios in JSON describe API implementation replay, not pure hardware acceleration.
|
||||
|
||||
The CUDA kernels preserve every timestep, float32 separate round-to-nearest operations, exact US timing, noUS zeros, compartment/frozen/D0 identity and the depression floor. No gain/learning-rate/tau/threshold/connectome/sign changes. No dense time×neuron matrix.
|
||||
|
||||
A new candidate-only CuPy environment and explicit CUDA12.6 nvcc compilation are used. Original science and ComfyUI environments are unchanged. All three ComfyUI queues were checked before each fixture; no services were stopped.
|
||||
|
||||
Integrity: 64034 saved files, 3103901058 bytes, 16 registered source files checked; no mismatch. This is the saved Phase4AR inventory, not a new Phase1–4AQ numerical regression.
|
||||
|
||||
Phase4AR remains stopped at1033/30000CPU-verified epochs and138/3920probes. No weights were installed and no training was resumed.
|
||||
|
||||
Next: a separately validated persistent-worker pipeline and end-to-end benchmark. This local optimization does not justify dividing the9-day estimate by the kernel speedup. Independent-seed V100 parallelism is not yet measured.
|
||||
|
||||
Preserved failures: candidate packaging incompatibility (--report unsupported bypip22); first CuPy compile FTZ flag conflict (before any kernel ran). Both were corrected only in the independent branch.
|
||||
|
||||
Compiler references: [CuPy precompiled RawModule](https://docs.cupy.dev/en/v13.6.0/reference/generated/cupy.RawModule.html), [CUDA12.6 compiler options](https://docs.nvidia.com/cuda/archive/12.6.3/cuda-compiler-driver-nvcc/index.html).
|
||||
@@ -0,0 +1,660 @@
|
||||
b63b6d799a83f46c3c69805cfbec316537b06ae7f8e4b63703c9b02575c11cc1 RESULTS.md
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 candidate-freeze.stderr.log
|
||||
8ddcbb332825939eb1e091d87a6f73459de707defedb93654727662a0d4e2f0e candidate-freeze.stdout.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 create-venv.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 create-venv.stdout.log
|
||||
e3cc62cc576238a0d08ebbcfcfb151ba5c6f4bfe4891c3b46c39f66e1ccd5d21 create-worktree.stderr.log
|
||||
8960fa67e787f4103b0ae3dfb1d17d6133754ae9c97244877b148ebba1a302af create-worktree.stdout.log
|
||||
1687fe1688fffa492da67c2a638aff8062fb73dfc9c35931342f7b9bb005d37f cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/build-receipt.json
|
||||
41e670729a7d787b5327f5ae0934bc58147bb7d92f98c43973d68c81c3c56ba7 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/compile-command.json
|
||||
51948332982f31fc0d6612158542ad093a0a728669d4b5c296ec5ccd07ec77b6 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/compiler-identity.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/compiler.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/compiler.stdout.log
|
||||
e6b87f94e8e7c1a5edd09299c15731f5682e1a8b9b689155d615025b37c3a0b2 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.cpp1.ii
|
||||
d91416da2badd78eef607dd5fc261162d05cdb79189237e0ded8554785eddf66 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.cu
|
||||
03ebf12750449e7b99dff31db4cb70e5f49e4819c753b673c43be244d320d40b cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.cubin
|
||||
c5649b5b5bd2b001266af9a4f599237f756e0abb364be2d92f5fc72b10ead562 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.cudafe1.c
|
||||
debb1845f7a23e6a8e351b2f240d30e629ca66a82285f85e4af8558dc14456df cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.cudafe1.gpu
|
||||
a32a96aeddc2ddb97bea81426c4892237a3756f994360ba2f53e43ee28e73915 cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.cudafe1.stub.c
|
||||
9400013920a21185d1c277ee98a62c33659c7cbd4334d75c33ffe71d9486173a cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.module_id
|
||||
b1464ec5c35a33a4b26b6726a0a9e3d38626d09c2f2c073b7b4a52071cedf47f cupy-cache-4090/eligibility-nvcc/c26699b5e4dde91a432b9dc12a348e137c3c290dd9335e9b27785ea9ec9f1ec8/eligibility.ptx
|
||||
e79530a1bddad4ccd3cee9fb123a1c74fcb31cfa9dcf16b4d658b648290eb6e5 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/build-receipt.json
|
||||
d3795422398083d596ac14e849651e420d8a7783459e97b716f3f030c408aac6 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compile-command.json
|
||||
7f442f9e5a883861cec21f6b0539fb8cbba6f5ca81dd9613a841b8cc1bf1767f cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compiler-identity.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compiler.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compiler.stdout.log
|
||||
e3fe0937285d9ce97be26ad25080291cc6fdb55ae0204ebaef33e79ccb31e20c cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cpp1.ii
|
||||
d91416da2badd78eef607dd5fc261162d05cdb79189237e0ded8554785eddf66 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cu
|
||||
812362ec496914d948e3bbafab3febafb01a5af9f91cdf0aa1c52efd6f76aeab cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cubin
|
||||
685c3336b57137584e97a44690889f4d76f18dbd19c47c1f473fd183852e131d cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cudafe1.c
|
||||
72fbd9b61bd45f97b49ccb3b3175b1fb0225c12d3cb58b4fc81c5532f5269203 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cudafe1.gpu
|
||||
aa0746bf3d2c596e9dc24f9a4192e18024bd65f8b65f04bef8440f7f175eab00 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cudafe1.stub.c
|
||||
5765dba7d94e57db96df0b36300efe7b4767f283f2e08e07b8a3b5af79768a87 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.module_id
|
||||
45a7cc53c2d488cff4c012f3b57fdb0dc4644f8e221f81a54bc7805878bc1fc6 cupy-cache-v100a/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.ptx
|
||||
f65343fc1406047f75072fe9be50c6e97a7f69e7a60a53a51a5fd7d66d0f9b2f cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/build-receipt.json
|
||||
7dbf5552fa4d5d7530692b7d5b05b643fea96648bfdf8bebd9a5cbe2aa4625dc cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compile-command.json
|
||||
7f442f9e5a883861cec21f6b0539fb8cbba6f5ca81dd9613a841b8cc1bf1767f cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compiler-identity.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compiler.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/compiler.stdout.log
|
||||
b5e707bffb848e57191ce029e3f8decf55b9531b3edbbe7e10d8d64523c193c0 cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cpp1.ii
|
||||
d91416da2badd78eef607dd5fc261162d05cdb79189237e0ded8554785eddf66 cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cu
|
||||
812362ec496914d948e3bbafab3febafb01a5af9f91cdf0aa1c52efd6f76aeab cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cubin
|
||||
a4009f94f1839fed9e136e7e7f2e83a2a93b4758b61b533d16cb8faafcaf1382 cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cudafe1.c
|
||||
11fc13fae5097a0dfb0580ae21de5d4820ce14abd06b289bc4381b6fade8f879 cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cudafe1.gpu
|
||||
583af03a0f2f6de36a11e8c7a823b5624b3d6afcc4f005ebf0e91046fc3d23fb cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.cudafe1.stub.c
|
||||
444a6ec9096efd45b32931ca90225146ac84b5dbbc5202ee0a37ef26fead346e cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.module_id
|
||||
45a7cc53c2d488cff4c012f3b57fdb0dc4644f8e221f81a54bc7805878bc1fc6 cupy-cache-v100b/eligibility-nvcc/6020224e345a164954bb922d05bd2aa9d89677bf427c34dac24f75400d404458/eligibility.ptx
|
||||
06df3158d0329dc925ecd7ceabe47f7c83ee8974f4fd959516411e82ed0dc34b environment-authority.json
|
||||
794855bb5509c4773378f7023219574f90e1bc393d48570161c9e024a91e7eb9 final-summary.json
|
||||
b5b896ac413d5fcbd8510e553993884a3e941d10f2a4bbbf25f7ccb4bc263781 fixtures/00-cs_only/authority.json
|
||||
e70005480e1d88131e9b41c6acda1c5fa0454ec2d9a1c4cdb80c08150cbe89dc fixtures/00-cs_only/command.json
|
||||
9dfe7afae9438a9df33f32ab8f982d1e24ed5d9a5c72329cfedd65403d25dbe9 fixtures/00-cs_only/fixture.json
|
||||
6e4f6c0ccdad03049c75e056a4222e87c7b1f1d3f90bffb59a1b77ec4b363843 fixtures/00-cs_only/fixture.npz
|
||||
5aa38f581478835ef2c2bb25218556959195ea1b913eb5167b837b276475c84c fixtures/00-cs_only/fresh-cpu-validation.json
|
||||
2a8d5e9b0072e40d69e46258ff8ced3379f3e72bd9d86e49caaa74918a00be42 fixtures/00-cs_only/inputs.npz
|
||||
9e72a3b9c88f74278273f551a2231fd4fedab085393bf2e36103295c397aa0e3 fixtures/00-cs_only/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/00-cs_only/reference-sources.json
|
||||
f9d18b20bf096f8bae6b1ddf23c12925a36caf4b7f8bcf17e7cca9e1afd4793c fixtures/00-cs_only/reference-timing.json
|
||||
d0a74fa23c5d8c8634218ad9124b95d3ec893563bcfc9d283a124c6de4e4d33e fixtures/00-cs_only/reference-update-receipt.json
|
||||
fe4a3481bb9921e6efec04bfe9803d7adc085ed0b2452c50e224f570e880ae2f fixtures/00-cs_only/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/00-cs_only/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/00-cs_only/reference.stdout.log
|
||||
d3ff59060963eb84cb2dda4f4f316eb946c97f710e6b2b6ef082d66d70ac8a37 fixtures/00-cs_only/source-file-pins.json
|
||||
d0a74fa23c5d8c8634218ad9124b95d3ec893563bcfc9d283a124c6de4e4d33e fixtures/00-cs_only/stored-update-receipt.json
|
||||
827ea67796351b5056ae332dc6bed2da973c07ad09a44b4566c370b806e7dc19 fixtures/00-cs_only/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/00-cs_only/validation.stderr.log
|
||||
79366a956d3006c4bbb9a48da59e8f79ea207ab6549cb34d715210d5fd92a52c fixtures/00-cs_only/validation.stdout.log
|
||||
5da791ac50bafc884861d137cea12dc8bee0108ada5a9456065ba222ad33bf32 fixtures/01-cs_only/authority.json
|
||||
e70005480e1d88131e9b41c6acda1c5fa0454ec2d9a1c4cdb80c08150cbe89dc fixtures/01-cs_only/command.json
|
||||
8af9cfc908858418e04f88d2206237e4fa6b45353a1f57132a1165c764f7e187 fixtures/01-cs_only/fixture.json
|
||||
d287a9b1e06de8ddf0fb333546061b490151b87dec2b6c51a1789866603036a2 fixtures/01-cs_only/fixture.npz
|
||||
3469c42449c07bdb85beb2ae7cf5546d6d479108f1945909424e59f0c810bbe7 fixtures/01-cs_only/fresh-cpu-validation.json
|
||||
86734415f81985e39d9f4ea17aa6f89f72e28932d9359f4c75562e6264996adc fixtures/01-cs_only/inputs.npz
|
||||
a88decbeaa6f64bd82d13ae7ae79822dd99057f17e3975eca4f7aa600223e203 fixtures/01-cs_only/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/01-cs_only/reference-sources.json
|
||||
816e6d4fa5d3e590f4f8c3b2e40a56f9817a98bc85ca2ea3b0cd36a0d608a121 fixtures/01-cs_only/reference-timing.json
|
||||
9c13fcf9dfded5a222c35abf6550cf4dc47dd1d431cee4332613fd5ec020c1f8 fixtures/01-cs_only/reference-update-receipt.json
|
||||
99fc0c344a075642c0965404dfb950463c3aab00527ad7879b073ac334defe95 fixtures/01-cs_only/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/01-cs_only/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/01-cs_only/reference.stdout.log
|
||||
bfc93d51dedfbd37f522459b043f6469923ed892cdab47c1ee131701218166e3 fixtures/01-cs_only/source-file-pins.json
|
||||
9c13fcf9dfded5a222c35abf6550cf4dc47dd1d431cee4332613fd5ec020c1f8 fixtures/01-cs_only/stored-update-receipt.json
|
||||
e8ed3f58c4d81dcff62a1202ddc8343677680b1116279b5d9e47c5d212ad4249 fixtures/01-cs_only/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/01-cs_only/validation.stderr.log
|
||||
cde3a215d29fcdc0c889deca76866e2973d0012170d58cef67959a547b9444e1 fixtures/01-cs_only/validation.stdout.log
|
||||
718fad35b01ffe406db72247ba747c9f5a9d7abbaab466bb4cbefbd6c934c384 fixtures/02-d_zero/authority.json
|
||||
8109c880fdbfbeda8b696e85fe012afcb1bb05fd4c8feb1b5a142dc98e06c3b9 fixtures/02-d_zero/command.json
|
||||
137bb20671520146709129180fa42858004a576cfe00186b855c1e1cb2e3620c fixtures/02-d_zero/fixture.json
|
||||
d7219694f4b13600509ba76282ef2935ccef2a5bb69516d6322dba719c3681ee fixtures/02-d_zero/fixture.npz
|
||||
4616d9adc5e7050c4b8458a4874df6399874406ab28efccd17fa3476354b3efe fixtures/02-d_zero/fresh-cpu-validation.json
|
||||
e5407ce4f164ab242773f50abaa5434956a7c0e08d5090532bd35bb806754950 fixtures/02-d_zero/inputs.npz
|
||||
c8dd355352a81c870405283b2c9957f138e8c9af738d1cb94cc7ad395bcfd800 fixtures/02-d_zero/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/02-d_zero/reference-sources.json
|
||||
c5f86afa7e42971c033116b61da0719bb5e9cc0cfe7b23d0fcdc331593285648 fixtures/02-d_zero/reference-timing.json
|
||||
dc1a5801b2250c391e5500b211b94538f72e45a1ac7474a368ba5475e976e0c7 fixtures/02-d_zero/reference-update-receipt.json
|
||||
b1fe5cb9af21e4fbc7ed758346342c8122c17422aabc2bc31f185ce45f29a8f9 fixtures/02-d_zero/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/02-d_zero/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/02-d_zero/reference.stdout.log
|
||||
f673086b818779a939b32b841f72055363f257fce66a8c94f660ac7bdc6ef8df fixtures/02-d_zero/source-file-pins.json
|
||||
dc1a5801b2250c391e5500b211b94538f72e45a1ac7474a368ba5475e976e0c7 fixtures/02-d_zero/stored-update-receipt.json
|
||||
f18a2388498445c7f72b7a6ca6ca18bb293fe1f60547e6c97ebd30b60ba829cd fixtures/02-d_zero/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/02-d_zero/validation.stderr.log
|
||||
5081f11464fc48a0c2aac7b71462708a194249d16d4e1ff7d94fd4443ecaba63 fixtures/02-d_zero/validation.stdout.log
|
||||
d62ddd05588f89c9c7e3666d8d1a06653ac6e7301aecdcd4fcbfe026760c1581 fixtures/03-d_zero/authority.json
|
||||
e70005480e1d88131e9b41c6acda1c5fa0454ec2d9a1c4cdb80c08150cbe89dc fixtures/03-d_zero/command.json
|
||||
8cdfd61b466a26c87bebc8b428f2d2c2d216a7d66d99729667b12e60cfa4aca8 fixtures/03-d_zero/fixture.json
|
||||
1e08c6c2ab7fb4ed5464446011c20753326609855661747b4f2e957ea2180a7d fixtures/03-d_zero/fixture.npz
|
||||
294dd3720cc72a4d5744f83dcfe589e0a18ecdd3f1d445ff4dd03088beb0ea5a fixtures/03-d_zero/fresh-cpu-validation.json
|
||||
b381836e7174025d8d3713ef5c9f37e3ffd1c7ec34f4f05c2e7d86257641d796 fixtures/03-d_zero/inputs.npz
|
||||
7566258ccbcaf7080fda56719203b73d015e0df181ccf5b8edfeb073c889009e fixtures/03-d_zero/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/03-d_zero/reference-sources.json
|
||||
8f6a15f0e152e4d16590f7c5da3890a8d4518a4da17c36d8ae9fea0ea3d5a625 fixtures/03-d_zero/reference-timing.json
|
||||
a1bb3e238c5f45cdc9b4d3a812cd5c71ed66fe0172ebb7ac9f6e3dee07ecb340 fixtures/03-d_zero/reference-update-receipt.json
|
||||
14053ba60590e38277a400cc73e12f6e5a78c3db2724052b999b9fa3181e03d5 fixtures/03-d_zero/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/03-d_zero/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/03-d_zero/reference.stdout.log
|
||||
afb38d3677cb67a31e88cbbaa1a00abaaa41a2227720e7f22558a2e8ef1d4fb2 fixtures/03-d_zero/source-file-pins.json
|
||||
a1bb3e238c5f45cdc9b4d3a812cd5c71ed66fe0172ebb7ac9f6e3dee07ecb340 fixtures/03-d_zero/stored-update-receipt.json
|
||||
c4b94d65276d73f45a1e20e89e97f09404ade36cece532d4258fb61c834487df fixtures/03-d_zero/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/03-d_zero/validation.stderr.log
|
||||
e9cb098fe3d6d02d20b3ad02e51f56609fbef2c187aa3c415b854f698c4183ff fixtures/03-d_zero/validation.stdout.log
|
||||
f67885668e1f76c9ce055cf8b9b393af069661e0ffaa17b2b64c31e6b769b8af fixtures/04-dan_only/authority.json
|
||||
5f54ab41b5a3e4bd77808e88b336bf5114653fa89ff7e1b17317f3318029070c fixtures/04-dan_only/command.json
|
||||
92d70150d60543d57d3b0e74c9253c8a5ee8c433172b47eb78119db67381fcc8 fixtures/04-dan_only/fixture.json
|
||||
d3308593b3dd900cd87b3d70f1d763e28915717a1da591d6bb0e18c3ad8418ff fixtures/04-dan_only/fixture.npz
|
||||
57c223e70bc779649ce8d96ef6007168b87037ca50b0dd0ed697d1d5d7bdf84d fixtures/04-dan_only/fresh-cpu-validation.json
|
||||
ee57193b3f6474ad17ec5ac5685521e221f4fb79dbe4c5e8a5efb48ce459f303 fixtures/04-dan_only/inputs.npz
|
||||
15f84dff3673d35cb8940a1a243c13de32f03be36368424cebe8a5b68ef3c83f fixtures/04-dan_only/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/04-dan_only/reference-sources.json
|
||||
34014232cc53e9a7720cd82a6368bb67b881cf50fb688257093b627c29b202e4 fixtures/04-dan_only/reference-timing.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/04-dan_only/reference-update-receipt.json
|
||||
e1e6a5ea847c37973ad7918030ecd24a4c303f3b07c06bd54c6585343514e213 fixtures/04-dan_only/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/04-dan_only/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/04-dan_only/reference.stdout.log
|
||||
9e38d6ddfc2a1021815f8d0d4bc3e27c6e946e28a7ed0a347ed8c9dabb83a076 fixtures/04-dan_only/source-file-pins.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/04-dan_only/stored-update-receipt.json
|
||||
c56b76617f2d5fce49a4a614b73da5e064334f282e139f2be757bff73e64b38c fixtures/04-dan_only/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/04-dan_only/validation.stderr.log
|
||||
5b7daadc46ae9f508c260fcb1310f06ee7e9a4a93a2d10319228192d933f7a24 fixtures/04-dan_only/validation.stdout.log
|
||||
696ba064308fe574821e8a40890528903c0f8db06b87a20820066ab026f63750 fixtures/05-dan_only/authority.json
|
||||
5f54ab41b5a3e4bd77808e88b336bf5114653fa89ff7e1b17317f3318029070c fixtures/05-dan_only/command.json
|
||||
82b493cec2b6f26c93acd1f1341c31b09d91ead227ac71db48367efe56be2863 fixtures/05-dan_only/fixture.json
|
||||
d3308593b3dd900cd87b3d70f1d763e28915717a1da591d6bb0e18c3ad8418ff fixtures/05-dan_only/fixture.npz
|
||||
e83e1fbcc9f9a89135ba803d88b7e435b5899cd36bdeb0099133c8a510314a2e fixtures/05-dan_only/fresh-cpu-validation.json
|
||||
ee57193b3f6474ad17ec5ac5685521e221f4fb79dbe4c5e8a5efb48ce459f303 fixtures/05-dan_only/inputs.npz
|
||||
a9485620b134ca73d1c6b4c46975a477cf32722179576e89caa0eb0648a6046e fixtures/05-dan_only/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/05-dan_only/reference-sources.json
|
||||
fd6699c19db6ca4b27a4cdbb6ee56da53cd0d959bbe33c691b45f8433d590fbb fixtures/05-dan_only/reference-timing.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/05-dan_only/reference-update-receipt.json
|
||||
e1e6a5ea847c37973ad7918030ecd24a4c303f3b07c06bd54c6585343514e213 fixtures/05-dan_only/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/05-dan_only/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/05-dan_only/reference.stdout.log
|
||||
c8932db5e698569c7f503b177e0bcadb7691dbb3a6bb7bf95f5d489457ed43a4 fixtures/05-dan_only/source-file-pins.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/05-dan_only/stored-update-receipt.json
|
||||
58c01661634cf16f9bdf49d6097afa70b70654ff977192e9257e011bebd4c288 fixtures/05-dan_only/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/05-dan_only/validation.stderr.log
|
||||
f2e7bc6dee034c030ec8ae2893bbae152ffc8dca380e32ebea866492990e2669 fixtures/05-dan_only/validation.stdout.log
|
||||
7487ac6f63347e8ce7b196f07101813b2760e6d9f361939ea1e7ddb324b4e4f4 fixtures/06-frozen/authority.json
|
||||
012e31724d4a9dca3f530f279883a2c17a99404587c0584fb35c9eda0c12666f fixtures/06-frozen/command.json
|
||||
af37cec01333aa06f859f190b97ace01063b0ff1a3d9473cc07ab2b747ed33c1 fixtures/06-frozen/fixture.json
|
||||
d7219694f4b13600509ba76282ef2935ccef2a5bb69516d6322dba719c3681ee fixtures/06-frozen/fixture.npz
|
||||
ea0f77c89a347692c8e9c2b3a194a8b908c097721ac22fa6796f5c5e000097e0 fixtures/06-frozen/fresh-cpu-validation.json
|
||||
e5407ce4f164ab242773f50abaa5434956a7c0e08d5090532bd35bb806754950 fixtures/06-frozen/inputs.npz
|
||||
da80362f8972cca5d4b927cbc3ab1251ced691b50e769f310f36e5e99eaf1af8 fixtures/06-frozen/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/06-frozen/reference-sources.json
|
||||
a078623ccc1a0b321744aff5c6f00c574dd3505a90b78d10014e7bda19d2a161 fixtures/06-frozen/reference-timing.json
|
||||
7fcefce05842bd93fa60010f33756f867a6f3bb85cb7d7d62664e57f1643e60b fixtures/06-frozen/reference-update-receipt.json
|
||||
b1fe5cb9af21e4fbc7ed758346342c8122c17422aabc2bc31f185ce45f29a8f9 fixtures/06-frozen/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/06-frozen/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/06-frozen/reference.stdout.log
|
||||
acd0f42558d85dd990d83b53c2f1b610cea6c50c55576587623f64def58024d5 fixtures/06-frozen/source-file-pins.json
|
||||
7fcefce05842bd93fa60010f33756f867a6f3bb85cb7d7d62664e57f1643e60b fixtures/06-frozen/stored-update-receipt.json
|
||||
92b433ca642efc2163a12649a9e02dd6128149d45498630378375d99db3202f0 fixtures/06-frozen/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/06-frozen/validation.stderr.log
|
||||
a110e0445eb65dea2b689f5f275171e28940ecf82cf464421da623050dfb869f fixtures/06-frozen/validation.stdout.log
|
||||
a7855b86c84a2af95aa64069c7f37939a156e294076f28d7afd659368d5ac270 fixtures/07-frozen/authority.json
|
||||
012e31724d4a9dca3f530f279883a2c17a99404587c0584fb35c9eda0c12666f fixtures/07-frozen/command.json
|
||||
923609c1b873fdd8757146c7339512c7fe2c0e39a4b122a63312eccd5e8148e0 fixtures/07-frozen/fixture.json
|
||||
b33364a02b8e517a5616e787dc52fed707c7a02c8e766c8db8bdd5e3519c3afe fixtures/07-frozen/fixture.npz
|
||||
793f5051607d210034579d6c5e8f735d82ef827ad0b4466fb1ba8ab32492fd42 fixtures/07-frozen/fresh-cpu-validation.json
|
||||
21ee0894422caac5a92651b36ca1a41ef7af40ace492dc5fd50a8ace6d409841 fixtures/07-frozen/inputs.npz
|
||||
42d9c3edee3f4e6c92a5cf18c5bc8000d6896a7ad67c05a5a83cf4822f5a930e fixtures/07-frozen/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/07-frozen/reference-sources.json
|
||||
7552171339f179d7d5afd95afa620846955e9c4bf4d7929b76e2122c15f6f0a6 fixtures/07-frozen/reference-timing.json
|
||||
dbc34e8d314e6ccf4d62984fdc50b5f3e86097959b73c24f6051b860508261d7 fixtures/07-frozen/reference-update-receipt.json
|
||||
05d2075865314133458d2960786cd1d8d9056e5cdd808192be9edf580f13655c fixtures/07-frozen/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/07-frozen/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/07-frozen/reference.stdout.log
|
||||
77d8e1d43d886b91d20a7557c0f33c296440ec0847c239eafb3c92a933d81000 fixtures/07-frozen/source-file-pins.json
|
||||
dbc34e8d314e6ccf4d62984fdc50b5f3e86097959b73c24f6051b860508261d7 fixtures/07-frozen/stored-update-receipt.json
|
||||
007d19099619f51a2f21ce2ba0365633b6cb8fc5ee9ad1969e51ae9a2954d890 fixtures/07-frozen/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/07-frozen/validation.stderr.log
|
||||
5db3aa7d39e24ba994f2ddeb018cbeb3e73dce4e62093f0f2ac49d811355840a fixtures/07-frozen/validation.stdout.log
|
||||
057370d91fcd3a596a615aca686801e4ac010e3347c86e0f8625392b3d321ca6 fixtures/08-paired/authority.json
|
||||
5f54ab41b5a3e4bd77808e88b336bf5114653fa89ff7e1b17317f3318029070c fixtures/08-paired/command.json
|
||||
9cc866bda3686db4bbaa777f17adddcb081c809c2fb0cba5e0a837c318583e51 fixtures/08-paired/fixture.json
|
||||
66255125ed61c996339b4ca86262a47144f606f1349ce9fe42ca9b14a599f195 fixtures/08-paired/fixture.npz
|
||||
bd648d6aa9f76215566a0212ff58122bbfd27b3b3a7ccb1001293d11ce7fe26f fixtures/08-paired/fresh-cpu-validation.json
|
||||
e5407ce4f164ab242773f50abaa5434956a7c0e08d5090532bd35bb806754950 fixtures/08-paired/inputs.npz
|
||||
0399337c02a9db5a0328384d46070177a008976b614b12a03d8635966bc7f7d0 fixtures/08-paired/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/08-paired/reference-sources.json
|
||||
cae6d6a80eae901d0b8c9147347f4b8aca59939f3f9cb4328d3958b71aa49825 fixtures/08-paired/reference-timing.json
|
||||
d0a660b4e87a786275852c1d759e2750f42d18b354780a2e4a1036b3b3be5056 fixtures/08-paired/reference-update-receipt.json
|
||||
67c2e3bb5b59ded42969dd1e13fcb9a3d17465a4b15e139bd004ed77587df018 fixtures/08-paired/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/08-paired/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/08-paired/reference.stdout.log
|
||||
6f8448d6f2bccaece46a6ff5e16302b026e1ed87e449168752f82d2b5b44f5db fixtures/08-paired/source-file-pins.json
|
||||
d0a660b4e87a786275852c1d759e2750f42d18b354780a2e4a1036b3b3be5056 fixtures/08-paired/stored-update-receipt.json
|
||||
1b11a6ebde1ec534783f63f1f551726e0ca7dfb381f4603cc38f38aeaf6d695c fixtures/08-paired/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/08-paired/validation.stderr.log
|
||||
bb7f511871ca2d89e632377ebd182996b7e8d11fda563a7bf72009cb0c4a7a55 fixtures/08-paired/validation.stdout.log
|
||||
fa75f7a56761529ea409aad47616384728b1aeff8c007f5d1cf365cb387047fb fixtures/09-paired/authority.json
|
||||
e70005480e1d88131e9b41c6acda1c5fa0454ec2d9a1c4cdb80c08150cbe89dc fixtures/09-paired/command.json
|
||||
8b649bc8271cd89e8e5c549f8f76bad7d2e97129aace586e6bf4dce4d2a49179 fixtures/09-paired/fixture.json
|
||||
291659396044089facc673b23ccacea8905263a3978e5a5af320bf50828e2d07 fixtures/09-paired/fixture.npz
|
||||
a5db3c2e0ebb90c53150226d891618a88b760da928b6273f56fbc4b09755ae38 fixtures/09-paired/fresh-cpu-validation.json
|
||||
7e4690296c8801897084c73b30be490132535abe6f0e1b2d5b140efa99c8bc5d fixtures/09-paired/inputs.npz
|
||||
7d1b54e446799eecbabe55b352b500b5edc2881c1d0399992aafd804d254991d fixtures/09-paired/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/09-paired/reference-sources.json
|
||||
6f9328a89809745eb510096c1fda0242dc6144b909cc9c64a195a9ce460e40b8 fixtures/09-paired/reference-timing.json
|
||||
e3ece81002439b3dae1b921ecebc528db3554bd1cb374e336a9af70c555bc01e fixtures/09-paired/reference-update-receipt.json
|
||||
48ebec28571a205c0f374df12677cb585ae594429ece26e3c4bad6068e017cdd fixtures/09-paired/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/09-paired/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/09-paired/reference.stdout.log
|
||||
a6cfba42d04e28ad99f92cedc60b39cb196be677a10ac30415aa530087f381c6 fixtures/09-paired/source-file-pins.json
|
||||
e3ece81002439b3dae1b921ecebc528db3554bd1cb374e336a9af70c555bc01e fixtures/09-paired/stored-update-receipt.json
|
||||
09bd4c8f83c489dbeb074a57490d368aad3b63347e01f8b84e12a4c11e11c66d fixtures/09-paired/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/09-paired/validation.stderr.log
|
||||
bcdb6d7e895a404daf7ef9815b394ea94e74a2c9f5cfce06c36830a33338476a fixtures/09-paired/validation.stdout.log
|
||||
e179f065522cc30505b7dd5d5d6adc41a10d7b3aa49e48a65afbc620ebf48c3f fixtures/10-random_reward/authority.json
|
||||
5f54ab41b5a3e4bd77808e88b336bf5114653fa89ff7e1b17317f3318029070c fixtures/10-random_reward/command.json
|
||||
0f587ac75a5486250b45e9ab624aa3e71db035a3149c09102e9892ed3f269b82 fixtures/10-random_reward/fixture.json
|
||||
66255125ed61c996339b4ca86262a47144f606f1349ce9fe42ca9b14a599f195 fixtures/10-random_reward/fixture.npz
|
||||
18e1d5c11b07b4f25d8ccc08e0e4928da4f7851dd063645a0cd83e2c91a3e677 fixtures/10-random_reward/fresh-cpu-validation.json
|
||||
e5407ce4f164ab242773f50abaa5434956a7c0e08d5090532bd35bb806754950 fixtures/10-random_reward/inputs.npz
|
||||
58d5571bd571120146d208182eccc564f13979d3f9d07c43c4cc922b54b9ae6d fixtures/10-random_reward/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/10-random_reward/reference-sources.json
|
||||
64b4e11de2bb2225c7f46bdcae32220011896181f19a58ef2dccecd6d70be0bb fixtures/10-random_reward/reference-timing.json
|
||||
d0a660b4e87a786275852c1d759e2750f42d18b354780a2e4a1036b3b3be5056 fixtures/10-random_reward/reference-update-receipt.json
|
||||
67c2e3bb5b59ded42969dd1e13fcb9a3d17465a4b15e139bd004ed77587df018 fixtures/10-random_reward/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/10-random_reward/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/10-random_reward/reference.stdout.log
|
||||
8f3acaa47501dacccc6609bc505ec7e3783ebec729900c217392168bf9c1b079 fixtures/10-random_reward/source-file-pins.json
|
||||
d0a660b4e87a786275852c1d759e2750f42d18b354780a2e4a1036b3b3be5056 fixtures/10-random_reward/stored-update-receipt.json
|
||||
1462b51d4d1503eb3c991a0865b8fb7e54a10587b42f5b506b6b77aa2fd368cb fixtures/10-random_reward/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/10-random_reward/validation.stderr.log
|
||||
c901e914fb8e0ba84a3c491a3128940ef3a0c554243743b70647106fea119e80 fixtures/10-random_reward/validation.stdout.log
|
||||
ce2d98f1c6071b381c92dfb2c50582eea755cdfa794badf5b07f42922304c15d fixtures/11-random_reward/authority.json
|
||||
e70005480e1d88131e9b41c6acda1c5fa0454ec2d9a1c4cdb80c08150cbe89dc fixtures/11-random_reward/command.json
|
||||
b7ac9446d02b8e532997f994a17730f8bb7477bc495b639508bc095cab66b4be fixtures/11-random_reward/fixture.json
|
||||
74175c25f3315988ffec266a865c54793a2f7ce3a0679b9e8544f79c074568cf fixtures/11-random_reward/fixture.npz
|
||||
d02cfb073c2921f246004ca3f7434c2347431533d284ddb2488c551149d6d4f4 fixtures/11-random_reward/fresh-cpu-validation.json
|
||||
62b9ef6e3add910e998d11d4e419eeabf5cc8d3b25cc1a0105ab6ea3784fc4c7 fixtures/11-random_reward/inputs.npz
|
||||
cae2fcf6ff67ffbc5b9ba627160961d5e63f33b1611f3d6759ace9c25233eaa9 fixtures/11-random_reward/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/11-random_reward/reference-sources.json
|
||||
b2eebcbee7bac6b2dd941f55fbe66bb2d5320a2068c7f060990aa2d1ad235b03 fixtures/11-random_reward/reference-timing.json
|
||||
93aaedd62b47bf35bee3e3201c52851fddde077633d630e808acf97bfa995c0b fixtures/11-random_reward/reference-update-receipt.json
|
||||
0878210890008fecf0c355d72d1bb0802cb59582f74d12634f17a7e8b8ec5fd8 fixtures/11-random_reward/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/11-random_reward/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/11-random_reward/reference.stdout.log
|
||||
c40c79d39688c3e4f538d2197f394510b25ef6a318e667fdfae0ece3a45315d2 fixtures/11-random_reward/source-file-pins.json
|
||||
93aaedd62b47bf35bee3e3201c52851fddde077633d630e808acf97bfa995c0b fixtures/11-random_reward/stored-update-receipt.json
|
||||
ab403457fc63c968982a77efd7d6f399753dcccdff6509626af4d97cf07487a6 fixtures/11-random_reward/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/11-random_reward/validation.stderr.log
|
||||
b5f610a73a30b3bd959b540f3f1b5678e20c562b9006dd28d90c46f99be75cab fixtures/11-random_reward/validation.stdout.log
|
||||
8f81bcbfec893382cffb93402ac5322f89f27a0bfe2187cdaf2a02a701f7fb16 fixtures/12-unpaired/authority.json
|
||||
5f54ab41b5a3e4bd77808e88b336bf5114653fa89ff7e1b17317f3318029070c fixtures/12-unpaired/command.json
|
||||
34f7744236017411b411953913b97d2f93cda8e49077eb52489961cb78fb99b6 fixtures/12-unpaired/fixture.json
|
||||
d3308593b3dd900cd87b3d70f1d763e28915717a1da591d6bb0e18c3ad8418ff fixtures/12-unpaired/fixture.npz
|
||||
c96a21414fffb685ad2b2d53d4b8f3e9596e551435d99a3aef075bd608f0cd67 fixtures/12-unpaired/fresh-cpu-validation.json
|
||||
ee57193b3f6474ad17ec5ac5685521e221f4fb79dbe4c5e8a5efb48ce459f303 fixtures/12-unpaired/inputs.npz
|
||||
ad8b8accece3042091dd9857acc8a668188383fc469f5c23060cfb0c93e2a02c fixtures/12-unpaired/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/12-unpaired/reference-sources.json
|
||||
7d5bc3c18d55a0473e0d1440722a649e9fc1d174499960a7488bce2cb9965014 fixtures/12-unpaired/reference-timing.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/12-unpaired/reference-update-receipt.json
|
||||
e1e6a5ea847c37973ad7918030ecd24a4c303f3b07c06bd54c6585343514e213 fixtures/12-unpaired/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/12-unpaired/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/12-unpaired/reference.stdout.log
|
||||
5b487868ddb4e1a9fe8fd341d745664aaf2092a485dc8dde4506938aeb9ab3c7 fixtures/12-unpaired/source-file-pins.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/12-unpaired/stored-update-receipt.json
|
||||
ed46a6b6702b1a618bca80f6045cbd93d25f557ecbf31e97c240d8dd53f95ace fixtures/12-unpaired/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/12-unpaired/validation.stderr.log
|
||||
0db4b969fb0a29e589b28fec3e512ab1392fd5cd8c95b821abe53d55e9b07526 fixtures/12-unpaired/validation.stdout.log
|
||||
01bc256b74fd303427aa06d05fc1750cc5440bb77b3be9e062638910d1f61c4c fixtures/13-unpaired/authority.json
|
||||
5f54ab41b5a3e4bd77808e88b336bf5114653fa89ff7e1b17317f3318029070c fixtures/13-unpaired/command.json
|
||||
2812c35533dc5ce3f7fdb138168635e7ce80b84cfaa8d7cbf9602a435daf4074 fixtures/13-unpaired/fixture.json
|
||||
d3308593b3dd900cd87b3d70f1d763e28915717a1da591d6bb0e18c3ad8418ff fixtures/13-unpaired/fixture.npz
|
||||
12fa68d0ac45173871ffcd5774966c5717f0bfc3e1d7e209f021ff4aa162a648 fixtures/13-unpaired/fresh-cpu-validation.json
|
||||
ee57193b3f6474ad17ec5ac5685521e221f4fb79dbe4c5e8a5efb48ce459f303 fixtures/13-unpaired/inputs.npz
|
||||
24362f7fbada424ebdeaa908cc30699ac63d6acfcece8e43450f7d52217d122b fixtures/13-unpaired/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 fixtures/13-unpaired/reference-sources.json
|
||||
ab5697a371aa02738e3b6742f7dc44ed4f2d4f9062c16074b943f2f792bad155 fixtures/13-unpaired/reference-timing.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/13-unpaired/reference-update-receipt.json
|
||||
e1e6a5ea847c37973ad7918030ecd24a4c303f3b07c06bd54c6585343514e213 fixtures/13-unpaired/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/13-unpaired/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/13-unpaired/reference.stdout.log
|
||||
197659c8588422095e1da0a6c58a642418afcbeb0f853019400bdd5118e6784a fixtures/13-unpaired/source-file-pins.json
|
||||
46dce947920ebca0041fe77929b1d1f24d7ba8f87bdfd89d599204be826760b8 fixtures/13-unpaired/stored-update-receipt.json
|
||||
b524ebb33b92491dd2c1e1d78a758ea45d9f7afdfa36c1d06abece88dd6b0214 fixtures/13-unpaired/validation-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fixtures/13-unpaired/validation.stderr.log
|
||||
012fe210b8db03eb760759af24d05f19ba9fe5a232d47634901f34827e5ff3ec fixtures/13-unpaired/validation.stdout.log
|
||||
481df128d39bf28e5984a6f2e5757f83d45cb7a6136f8d2843ecc0a67eca437b fixtures/manifest.json
|
||||
dda00d3eea57924cfdadf376238d28a07c88f04eb5e9253c44d9217b8a55ce3c fixtures/original-source-pins.json
|
||||
204fd74217e6f498c2f45b228e1162226cf051502429d04f8d2e10a1f309ab11 fixtures/selection.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 install-candidate-attempt-02.stderr.log
|
||||
da70074a63465cbc7f9e8d6e6eaca43b6300f869f63ceea25b1a08251c69b7a4 install-candidate-attempt-02.stdout.log
|
||||
572bfe5d57ec3c97dd6dc9985c4e8116b010fbbeb7dfd5b5fe79e4bc2c80384e install-candidate.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 install-candidate.stdout.log
|
||||
b35dd6c1f26644b688f87ce57ce03c33413d781707978a3979299654361c4fd1 integrity-after-gpu.json
|
||||
e3bb382e3b751e00090aa91d704864ba9cd623fb239f215719ad23680510b713 integrity-before-gpu.json
|
||||
1c22c3f133a18d8d18ed6beefb88f72165593492b886550668a353c753373365 jobs/export-real-01.exit.json
|
||||
138dd4fd23a0d3d0e34594478aa050dd410e18286739297067938895c7b77659 jobs/export-real-01.start.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/export-real-01.stderr.log
|
||||
7d16c3f01af58bded4a2b78d689ba0cc155e676dbd88a32b7e7e8f5dea69c3f6 jobs/export-real-01.stdout.log
|
||||
2eb69ff6a51b724d93fb80f439f31b3a0c84e613dd47082c4489e4ae08629c09 jobs/export-synthetic-01.exit.json
|
||||
338d241f6f21da1c7b9dc7652b258b20494aa87f88a6fe4b2fb30e82026991e1 jobs/export-synthetic-01.start.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/export-synthetic-01.stderr.log
|
||||
8ceb3408d2ddcdde3e007f62d9e13bf98e322d3818eb8f0395f737d2350ffe53 jobs/export-synthetic-01.stdout.log
|
||||
c29eec1b1dc9f798e1bdc466b01f17f790696a3fad1219dc8cebf28205abbff2 jobs/host-tests-01.exit.json
|
||||
236962124fb87c6b8cf871312d04b20d4a8f52ac3b3981c68a7fdace16e3da37 jobs/host-tests-01.start.json
|
||||
14d932e6256e9fbfad47cbbf6aa6479eb986584a7125e8ab21be2719ae7c2496 jobs/host-tests-01.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/host-tests-01.stdout.log
|
||||
94f122d95c52a8b7f9335c865b2c9d37d2be1bf02fde8a303d80d58e5da32def jobs/host-tests-02.exit.json
|
||||
4910b406c26fa43091ee404dd2632a810fd6ab530933e69a17d96fb7b4f57f7d jobs/host-tests-02.start.json
|
||||
0cde35a092720dec38eff7edc0c3b872663c0dd65d11822f3c52a72dcdc1fefc jobs/host-tests-02.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/host-tests-02.stdout.log
|
||||
d46f60ada1c6a869ad7ff79e17f79e1fe01c8398df9cd9dcde5d687515cc7c39 jobs/integrity-after-gpu.exit.json
|
||||
83430c5ef2c5615ce1234dab67bbb17276a75617256b6a716151d3cf8a72c2f3 jobs/integrity-after-gpu.start.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/integrity-after-gpu.stderr.log
|
||||
8a858236678507c28e50c884d177c59fa1a2908665f54992cca183fc86624943 jobs/integrity-after-gpu.stdout.log
|
||||
a43f4de683412d83e20523659045bb17aed3ba43571918d1babedea344da82fb jobs/integrity-before-gpu.exit.json
|
||||
1352324714e5e9cce1202373eedcebbdc4d17ff36b63feb84959312e5d60b0d6 jobs/integrity-before-gpu.start.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/integrity-before-gpu.stderr.log
|
||||
7f8e95d7180bc972443b09a7326088eb72aa73103c3703a463867e0771f9938a jobs/integrity-before-gpu.stdout.log
|
||||
cc3d84f8ec0e6d20fd0a3bc782b2270e84a5872c2ca04064970044ad52ee8482 jobs/rtx4090-01.exit.json
|
||||
18954abcab8bdad71944787684339fce9923f556dbfea091d81b13a3ab942ee3 jobs/rtx4090-01.start.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/rtx4090-01.stderr.log
|
||||
b99c5c217549ae72f2882f46a7205da9007f6541642b7e0e01954e5053372d88 jobs/rtx4090-01.stdout.log
|
||||
47ded46a1fad855509ecf5bff96c98b571611f3e10df4e1df71fa490ada1190c jobs/v100a-01.exit.json
|
||||
d69a93fd7e3aacb5b688237366487d19af64931d1067a2f909c5e87bd73ebc1a jobs/v100a-01.start.json
|
||||
a532b6e3d6e7011e3681588541da75dd0fb2f4913cc2f277e9c88c5c0f0c1fc3 jobs/v100a-01.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/v100a-01.stdout.log
|
||||
824fdba4d8fc4306a8dc48c377c34b2159587d752eebef691956df4823722c18 jobs/v100a-02.exit.json
|
||||
8835334a42e0b7fd305f6b3886d3c0e4f866c81e6377ba5b857d6aed767d0190 jobs/v100a-02.start.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/v100a-02.stderr.log
|
||||
6d598f73d21fef88ff9e58ca3dc85d31f3ebf9bbe33a3aaea4f608a79564f3a6 jobs/v100a-02.stdout.log
|
||||
f015698a70d1b1ba563ac31b25ca2c6d2096773217cd4702b97dcf451031f509 jobs/v100b-01.exit.json
|
||||
737007acddabee4d61626da4f91007a95033c53dde069f33ca363009a203996c jobs/v100b-01.start.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 jobs/v100b-01.stderr.log
|
||||
a74268f5e402ed4874f2b468da84bd45586a8f2931a7bb2eee80678a42c0dd5a jobs/v100b-01.stdout.log
|
||||
666e072ad4592eb528a39bb6933c048c09a6dd47ca58318bfded6a8fb6f69422 pip-install-report.json
|
||||
06c7b73058cb06a976acb62a5e6e88a2479b214e6e28d98bb793ea50197bf2e6 rtx4090-01/authority.json
|
||||
62a173c9891cfbd159d236b54785170b16bf0a4deeae487ee1e04bbbcbb7a546 rtx4090-01/fixtures--00-cs_only.json
|
||||
392cd9b4e8547e8f256e53aedecb7d570c5beff1fb180775233039c1100bfbb1 rtx4090-01/fixtures--01-cs_only.json
|
||||
29d45624a4710b1fac0bf5db3df67e0d8af48567af28d539f8dca45f09b3759f rtx4090-01/fixtures--02-d_zero.json
|
||||
b3915ce2a35795d99ff47824a932ce949ee8ac16f0afde8283c6ef3e293357dd rtx4090-01/fixtures--03-d_zero.json
|
||||
6b1310903f362ed6cef9052e70266b0b47bf8a743bf96a3e1035bacfa921e45f rtx4090-01/fixtures--04-dan_only.json
|
||||
410dfe35a7599460546f7f828b4152b94828bf90c250428ac7d2ec75ac63aa39 rtx4090-01/fixtures--05-dan_only.json
|
||||
ca257675fe44bc8cfb80813c0307b9fa8312c417cf3bbfc5820e27c035fcbcf2 rtx4090-01/fixtures--06-frozen.json
|
||||
8e2a1e17160ec4e98fd7c999487d6af9cb6bd8c0d96dce6852d88a3fe60fe1d9 rtx4090-01/fixtures--07-frozen.json
|
||||
0a5098376d5debb76af8e27d4404816c50545e0c8a158282d1d56465416a4ac2 rtx4090-01/fixtures--08-paired.json
|
||||
19ac2720c3ccac3819eceffae745710c3698ed090a879cd42f59d62471fd5d71 rtx4090-01/fixtures--09-paired.json
|
||||
55dd2071b19e4fd39680d5db2fdba7884033754b054e0a89440e09e346863de0 rtx4090-01/fixtures--10-random_reward.json
|
||||
9f72359d9526047c7842e5428a1092e7bec96905a8b02269490a999add75a296 rtx4090-01/fixtures--11-random_reward.json
|
||||
5bd5e68710774c575fbb2fb9cae6b72faff2c292b198560b1857b3bc36e858a9 rtx4090-01/fixtures--12-unpaired.json
|
||||
03a10ccc4006346b8e7d6404963d26f6eded2af48aa292962c3ef7dccf06d727 rtx4090-01/fixtures--13-unpaired.json
|
||||
d06c602fc1950f1f63f7b79e98e3fbeef2a291811c91fc7ffdaab5acfd9ea3f4 rtx4090-01/invalid-input-rejections.json
|
||||
377cb655e5b6e5816ccca3b5a03c481021afc3da64879af9be72c207e88639c7 rtx4090-01/summary.json
|
||||
810b8abe7145f7dc19bf34707a5169b480a3dfc4cfd02d8f5b3c8bf0c38cad98 rtx4090-01/synthetic--00-empty-us900.json
|
||||
38dca8b89791113c5e9efa7f27e91614bc4894620ae26801c6951a043a0e406a rtx4090-01/synthetic--01-non-kc-only.json
|
||||
213056b418992bf44112b2ebd6ecce755e62923496ad52e69b3d7ff9cbec079b rtx4090-01/synthetic--02-no-us-mixed.json
|
||||
bd7a8c8f9482b29c91a0579c8d2b642e975a1a24b3ad7ad8432ef7c217a83010 rtx4090-01/synthetic--03-us-first-tick.json
|
||||
1eca5ac08300083f71022aaeaf1d1acee8c79481fea0c0a01dd453965f1f7dca rtx4090-01/synthetic--04-us-final-tick.json
|
||||
e18bed6dc301d969b37b15d3478afeb919da7d503373f5010200eecde669c555 rtx4090-01/synthetic--05-before-on-after-us900.json
|
||||
56b3085d4cceaf9dc2ae720f82ba9a63b105c943fc84fd20321bffd9070eee15 rtx4090-01/synthetic--06-d-zero-existing-delta.json
|
||||
7c85511eb4ffd833824a1d8a65f30aa1cd651c247008987d23492e7e5f4be4c7 rtx4090-01/synthetic--07-frozen-existing-delta.json
|
||||
00f7eb4f9857c078e755d88ae7f4ebb067c279ace1fde074f2e30f6cb9d7c24e rtx4090-01/synthetic--08-compartment-0.json
|
||||
be8d410ca8a05661da851e981d5f18d84c09c08cf6d01beaa2cd62ed43805a67 rtx4090-01/synthetic--09-compartment-1.json
|
||||
dfbf57fc6a4259a5a0bd18d33f81d26b91976e39d6960b31be63c0008f008213 rtx4090-01/synthetic--10-compartment-2.json
|
||||
cd145d7bf7ce147043f0b401cdeea67c63a8ae45e130e4c6d71056c0250fbe08 rtx4090-01/synthetic--11-compartment-3.json
|
||||
f14e69b5293cb81cdc2cf6f4d895372acfdee80954c6ff3b29031abb536e00d3 rtx4090-01/synthetic--12-already-at-floor.json
|
||||
779a4d8111fa64524958e923f75c0d6076ccf6262b9ed67e99cedc16c7afd09a rtx4090-01/synthetic--13-one-ulp-above-floor.json
|
||||
71d98467108c65e9e8c4a2fb13a7c755bba733aa346f3fb77eec14ac12ee5c14 rtx4090-01/synthetic--14-seeded-sparse-717.json
|
||||
6f082a0715e8c2af13573b508bb272ac0413c4ccda3b2aa3cb079b1f143b95a8 rtx4090-01/synthetic--15-seeded-sparse-20261001.json
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/00-empty-us900/command.json
|
||||
511508f571c29e01cc9b52b012195aa6b2443854c6edeeb415323d5e28cb17cb synthetic/00-empty-us900/fixture.json
|
||||
9a289591eda1c68ff8ae704b484f2437a7b290dd3f9dc56195b233f00c4e5344 synthetic/00-empty-us900/fixture.npz
|
||||
85e6aa97b72c7a8cfaca125d6772395d9f2d53f8627569c26c5d38fde7d5609d synthetic/00-empty-us900/inputs.npz
|
||||
05957f0944ba8edacbe4335ac2d944a11570adb2eaa26bd81d221bc8a073f964 synthetic/00-empty-us900/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/00-empty-us900/reference-sources.json
|
||||
55e17e61d8c1da77906844dd7a58ac347d91e0420c7388cb1a8e35d3536b1c66 synthetic/00-empty-us900/reference-timing.json
|
||||
51cca308034c90e648311bc449d07210d6cce4c37779219c87571578af9d864a synthetic/00-empty-us900/reference-update-receipt.json
|
||||
e1e6a5ea847c37973ad7918030ecd24a4c303f3b07c06bd54c6585343514e213 synthetic/00-empty-us900/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/00-empty-us900/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/00-empty-us900/reference.stdout.log
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/01-non-kc-only/command.json
|
||||
d39cbc1610bf09a1431c2b59fcae0d271e7c21e8b41f95494d3b15b08dd215e9 synthetic/01-non-kc-only/fixture.json
|
||||
f0cf6ac6a9218d3e470f8f7570214c188eea8d8863461a03e9bb7388791da22d synthetic/01-non-kc-only/fixture.npz
|
||||
5560a2a7382ac6e45de8d129079763cf8f074062e5aae188a5742f5151b6c99e synthetic/01-non-kc-only/inputs.npz
|
||||
9b6b8185a64eaa8fbfd73456479605ae4a1359d9f5dc28d9691eeef3d9f45d8b synthetic/01-non-kc-only/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/01-non-kc-only/reference-sources.json
|
||||
70a43186e9d1c23f0ec76ebadd7c9b3ccbf273c3cf572e65ae3f8e5a568fa7d8 synthetic/01-non-kc-only/reference-timing.json
|
||||
21de55c0c71087fffe5c4f87b20ce5ee1c5119c07f60ddccee1b939ba65a9367 synthetic/01-non-kc-only/reference-update-receipt.json
|
||||
e1e6a5ea847c37973ad7918030ecd24a4c303f3b07c06bd54c6585343514e213 synthetic/01-non-kc-only/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/01-non-kc-only/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/01-non-kc-only/reference.stdout.log
|
||||
eb98ecda2554a459c199b2ca238a79df8e323da37f039f939cfb64c4709cbe91 synthetic/02-no-us-mixed/command.json
|
||||
7fc01d5f06cf3306c828997573fc97e7cfde4959a820d45ec95e13ce8d26a3f0 synthetic/02-no-us-mixed/fixture.json
|
||||
7ba6cba3abaa7c1ce89380722f471bd7516650efd16ee685a199b0dc9a81312d synthetic/02-no-us-mixed/fixture.npz
|
||||
6a0bcfa9cd11236e2cd3160f343e24725b6cdeac1121d8ef119194c24557f031 synthetic/02-no-us-mixed/inputs.npz
|
||||
0b3ab40391034acb03a142a0b731870ac046d1314520a6d6843eaa2794495a9b synthetic/02-no-us-mixed/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/02-no-us-mixed/reference-sources.json
|
||||
c4356ea8a998303b3d1ff02e6e548550f02178d73e254096d03a0a9d69f27ef3 synthetic/02-no-us-mixed/reference-timing.json
|
||||
6fe439df410bc3b43d613b5bf09cc3617ed34e1ab1411e7a26e57a5de5730273 synthetic/02-no-us-mixed/reference-update-receipt.json
|
||||
701ad21f5e762c8c3e619d001b6d1941262441d83e31255e1f7f2bb4a0b6ef30 synthetic/02-no-us-mixed/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/02-no-us-mixed/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/02-no-us-mixed/reference.stdout.log
|
||||
6131b2db05c0e76d7667ec0788c069a307479fa7d64abb4448caa9ab8b26199d synthetic/03-us-first-tick/command.json
|
||||
e3b04e52cbce0182d2adfcd989976cd46fc3942b4aff2b147a1971798f52c788 synthetic/03-us-first-tick/fixture.json
|
||||
e643d7ef1c9dc9177db35aedc254165feb6a0829aafc36858504e290df7182f8 synthetic/03-us-first-tick/fixture.npz
|
||||
677a5b156a06a73c4c165193b601df49c8de3141b2d0727df74ade3aad471ae9 synthetic/03-us-first-tick/inputs.npz
|
||||
c50311e064c535f8c60dcaa92213e5447d5770c6fef199aea43ed0fda59811d0 synthetic/03-us-first-tick/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/03-us-first-tick/reference-sources.json
|
||||
56231139ced0455cb1328973218265980ce82c013a46bf09b24624b97c9d1d25 synthetic/03-us-first-tick/reference-timing.json
|
||||
5520acd45f8d0a1820be7278d10f82bc50650b1b2836bcde7e418037309bc5a9 synthetic/03-us-first-tick/reference-update-receipt.json
|
||||
1c15f393e3791d5f0398af980d5eb447613066ede583bef29ef9a0da90014884 synthetic/03-us-first-tick/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/03-us-first-tick/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/03-us-first-tick/reference.stdout.log
|
||||
6d393eae689c30f60a7ca2acc535662ca0f65622a6bb680e93cfc72a2d86dc20 synthetic/04-us-final-tick/command.json
|
||||
98e785ccbd8fca8c7f62895f6af77200e836e60df0c9a3d8e4006dc99b15f9cd synthetic/04-us-final-tick/fixture.json
|
||||
7aba2418b1fdeab69c5ef40824ae09335308245e7cda15bbe8a54ff27343531d synthetic/04-us-final-tick/fixture.npz
|
||||
677a5b156a06a73c4c165193b601df49c8de3141b2d0727df74ade3aad471ae9 synthetic/04-us-final-tick/inputs.npz
|
||||
b58dc9fe89b8f35fbeb2d0e102ad26ccf03f09d0189ba27a85abd904a070c2b9 synthetic/04-us-final-tick/multiple-reference-process.json
|
||||
4839dadc4e59a259a513b1e4b5ddb7c0592d67431d8d9e55f98ba7b16aecc262 synthetic/04-us-final-tick/multiple-reference.json
|
||||
74ad903e255b1c994b54b9ce40aab028834767f108642fdb79c040b8962c3624 synthetic/04-us-final-tick/multiple-reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/04-us-final-tick/multiple-reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/04-us-final-tick/multiple-reference.stdout.log
|
||||
559e4a243cd5e1733829a1b2856df41c2bdb4365c7b8e077da434ceeee51ab0b synthetic/04-us-final-tick/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/04-us-final-tick/reference-sources.json
|
||||
0418611a857f0574ea38f1560baf98208064b89d3d6ec3a05dfc1b41ff0cf9ed synthetic/04-us-final-tick/reference-timing.json
|
||||
2c5069f28c0b76ea44461bddccdd9f96438ed835d764fece406b576ab0a4cba4 synthetic/04-us-final-tick/reference-update-receipt.json
|
||||
313840cc5c2b254af78dfe6a4adb99966ab7df9def81981325b55b0dc894904f synthetic/04-us-final-tick/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/04-us-final-tick/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/04-us-final-tick/reference.stdout.log
|
||||
e4c982051bb849815a2b83181be97b53e1859907b991b95bfd4690697af39807 synthetic/04-us-final-tick/trace-command-steps.json
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/05-before-on-after-us900/command.json
|
||||
95779e30e1def183be4f5a1d7f5ad5bd9673cf799b00b8c240959f4cea0bee91 synthetic/05-before-on-after-us900/fixture.json
|
||||
fbb07f9350e6c84d994522cc651d20492ec7aca7ce9906821a6964133bd4fdd8 synthetic/05-before-on-after-us900/fixture.npz
|
||||
6a0bcfa9cd11236e2cd3160f343e24725b6cdeac1121d8ef119194c24557f031 synthetic/05-before-on-after-us900/inputs.npz
|
||||
c89ac59e5aebba6052a02660291bb5f549c7ad2b887ce78996839067862a9bf8 synthetic/05-before-on-after-us900/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/05-before-on-after-us900/reference-sources.json
|
||||
a6ecd56b2355683dffc0ce461fd71c5917e8509fa861057fa7023ea56bbbed5c synthetic/05-before-on-after-us900/reference-timing.json
|
||||
6b460f343303a080ff5f93986ec73af67241a0c8a34ce98de2095235885b2acb synthetic/05-before-on-after-us900/reference-update-receipt.json
|
||||
aa7405dfd95c772c2a4c1516e359e44da227cd023cb2c0a7c7bc8c6e94a97f57 synthetic/05-before-on-after-us900/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/05-before-on-after-us900/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/05-before-on-after-us900/reference.stdout.log
|
||||
8d0528b432de998d651df7862a6e7f729c6510326cfe2091dbe2f39b68b6bcd9 synthetic/06-d-zero-existing-delta/command.json
|
||||
508c304d4d9906ae8d86b9fc5999f0a0988eb9f97fe96e2556a788718d27ac85 synthetic/06-d-zero-existing-delta/fixture.json
|
||||
aee196d0f3135489bcdb44fd8038c0db3fa55899e4347ba41aee009364cad09e synthetic/06-d-zero-existing-delta/fixture.npz
|
||||
d7a9d21490ba1d1ab802c7c427d21637e72bd2450e22a91bf67a481af0dde669 synthetic/06-d-zero-existing-delta/inputs.npz
|
||||
9b275e432ca51466d423094a2faf4dcea98e9f33c03debe0720b34b351744590 synthetic/06-d-zero-existing-delta/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/06-d-zero-existing-delta/reference-sources.json
|
||||
dbb3fcf28f9d8761fe94bccd8f4908501fc7bf8baa9b78c1513bcf8be64f967e synthetic/06-d-zero-existing-delta/reference-timing.json
|
||||
8aada5cac82c95961b6d362c5aea987ba759693d7ca27ef211c85160dd8a95cc synthetic/06-d-zero-existing-delta/reference-update-receipt.json
|
||||
8a95cd87fb05348436bf3b95b8487b7b963fd5b849f0467dd61a2efea4ae5ead synthetic/06-d-zero-existing-delta/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/06-d-zero-existing-delta/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/06-d-zero-existing-delta/reference.stdout.log
|
||||
ea2a1c748b5f5494e493135032a13ac76f5827c35903b6c99ea2bdc43edf5591 synthetic/07-frozen-existing-delta/command.json
|
||||
c59e94d8ea6e9beb5a14a1ba71ca5c1a0baed949c049c7d0db3445a1917811e3 synthetic/07-frozen-existing-delta/fixture.json
|
||||
aee196d0f3135489bcdb44fd8038c0db3fa55899e4347ba41aee009364cad09e synthetic/07-frozen-existing-delta/fixture.npz
|
||||
d7a9d21490ba1d1ab802c7c427d21637e72bd2450e22a91bf67a481af0dde669 synthetic/07-frozen-existing-delta/inputs.npz
|
||||
9ed1abb56c1a731ecf7f3c8aeb127d097854826e2630fbc072b07889f557cf35 synthetic/07-frozen-existing-delta/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/07-frozen-existing-delta/reference-sources.json
|
||||
4ea633afbe7358274d22b6ca984914274a70a77f8c96fab4ce840a804f366264 synthetic/07-frozen-existing-delta/reference-timing.json
|
||||
edc7ef799e27f254a0781cdff6062c2900b87618d7d11b3697f5433c0a20b468 synthetic/07-frozen-existing-delta/reference-update-receipt.json
|
||||
8a95cd87fb05348436bf3b95b8487b7b963fd5b849f0467dd61a2efea4ae5ead synthetic/07-frozen-existing-delta/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/07-frozen-existing-delta/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/07-frozen-existing-delta/reference.stdout.log
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/08-compartment-0/command.json
|
||||
acef4efe1569358a4d68859ebe625c76e3490a85f8ae60d32ac9e8e1e9f0b658 synthetic/08-compartment-0/fixture.json
|
||||
13593e4495c227a371255cff31806f3e17e6561fa22d89ba81dcd22963e85648 synthetic/08-compartment-0/fixture.npz
|
||||
9b9298ca0f81f15feebba2773e59cbbdc848d3d41ec8be8bce00dc0856198389 synthetic/08-compartment-0/inputs.npz
|
||||
ba92ef45a2782dd349cc10028fd562038005c9adb9cf1070850584e732d95772 synthetic/08-compartment-0/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/08-compartment-0/reference-sources.json
|
||||
c83aa21eadf447f3e9881d6b387e933151384a4d1c94e9313efd7db7e61e4be5 synthetic/08-compartment-0/reference-timing.json
|
||||
b9c0f63144fc16e292b8cff2ded3bcbcd7893bd387d62aedeeaf37265c8b3cab synthetic/08-compartment-0/reference-update-receipt.json
|
||||
7a4283d73e202db93a145b10c4f34edf62497938ca1044829b9ca0ce0f5d3619 synthetic/08-compartment-0/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/08-compartment-0/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/08-compartment-0/reference.stdout.log
|
||||
29fb25fa7b54889eaf9668bd5ec5313603da1d05e4ac57da30adf110f78ca058 synthetic/09-compartment-1/command.json
|
||||
8117aafd691419706307280f19dde57d6ceff4ab28b2a82141582bc7bc72d382 synthetic/09-compartment-1/fixture.json
|
||||
6a456ba8f13ac8beca8a94ec9de074ad1dbaceeeb483b0da58239006e793ab67 synthetic/09-compartment-1/fixture.npz
|
||||
9b9298ca0f81f15feebba2773e59cbbdc848d3d41ec8be8bce00dc0856198389 synthetic/09-compartment-1/inputs.npz
|
||||
bc2e4d67284c003d12437833a8a28d63d30b5476535ab15e34df2b7572329013 synthetic/09-compartment-1/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/09-compartment-1/reference-sources.json
|
||||
f9b166aa904097a388eb944476a6514dc041e072968ad700fc2de31a407469e0 synthetic/09-compartment-1/reference-timing.json
|
||||
20a7a3a02d9d8055314e65c7f09de488798b394b0033af7e155deb9978316255 synthetic/09-compartment-1/reference-update-receipt.json
|
||||
fdc015e6299bbc718810406b3df7b1fafac8d6eb41acb8e52b0a2fa456da8b5f synthetic/09-compartment-1/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/09-compartment-1/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/09-compartment-1/reference.stdout.log
|
||||
5cb3364f3b8be8aa85a35936296ac74b780002a6ecc9b8e0d73067b0f16a0e1b synthetic/10-compartment-2/command.json
|
||||
957cc144442a06a83500d076643fd51542d33c422384b64c030e16ad712a3d39 synthetic/10-compartment-2/fixture.json
|
||||
3cdf931bdbeec427ca09ab594dd34cdde9c04db6f85b1858c96a71c09f7e8891 synthetic/10-compartment-2/fixture.npz
|
||||
9b9298ca0f81f15feebba2773e59cbbdc848d3d41ec8be8bce00dc0856198389 synthetic/10-compartment-2/inputs.npz
|
||||
3c7b4d64f012d3ea2e3573da375526ff483112c9f10f261830daaa97430f3d51 synthetic/10-compartment-2/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/10-compartment-2/reference-sources.json
|
||||
6aa3d830a790352f12c683e93d53ab3039f53d65758f4766e582b94cbfe9d5c6 synthetic/10-compartment-2/reference-timing.json
|
||||
f9a90882ff074748465e285b13a0a89d1f486bb1a72dac11cfe133915b026915 synthetic/10-compartment-2/reference-update-receipt.json
|
||||
8f32636d547cf8c616778cf7f77387a08f8d8f786b0d402ba70df932779f9451 synthetic/10-compartment-2/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/10-compartment-2/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/10-compartment-2/reference.stdout.log
|
||||
5f54ab41b5a3e4bd77808e88b336bf5114653fa89ff7e1b17317f3318029070c synthetic/11-compartment-3/command.json
|
||||
493b451b25f3a9736cf687b7a10787b2838f52b600e00253e4cd0e573dae2ea5 synthetic/11-compartment-3/fixture.json
|
||||
2604e203e2fdac9a7638a37caa643f2da61a0cc4720a7d521b211bc87d9e8f49 synthetic/11-compartment-3/fixture.npz
|
||||
9b9298ca0f81f15feebba2773e59cbbdc848d3d41ec8be8bce00dc0856198389 synthetic/11-compartment-3/inputs.npz
|
||||
34b48bc690c285b75e6450c259cf4975d1f0981d0cff1197648a0f3ee87f0200 synthetic/11-compartment-3/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/11-compartment-3/reference-sources.json
|
||||
df6ef026e2a89c3a59e1fb1607b6a611277f4b8ebade80d5d7e97de7449ea89a synthetic/11-compartment-3/reference-timing.json
|
||||
6732aa221d4a880f56de1868b7654c884a0d26b908366804116de302192495a8 synthetic/11-compartment-3/reference-update-receipt.json
|
||||
67b25ae8d66f6e395273f5474339aab69269c37261d837a933330f942c6243dd synthetic/11-compartment-3/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/11-compartment-3/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/11-compartment-3/reference.stdout.log
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/12-already-at-floor/command.json
|
||||
e7d09dcf325b47ee08371645941640a2abacad4777591791d3a2cb0dbfd1bae2 synthetic/12-already-at-floor/fixture.json
|
||||
b4c0f8106381eaa83a6042e703be369ba4e1821e9b6ac4053882a1064d3cfcaf synthetic/12-already-at-floor/fixture.npz
|
||||
5a1258fe9844b716f33c4ecdbc595bf4b436956476954ddd4cde8d4310509474 synthetic/12-already-at-floor/inputs.npz
|
||||
854d3eba812535bd0810321329402e178c2abb703b846d94dbeae5dffa793edd synthetic/12-already-at-floor/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/12-already-at-floor/reference-sources.json
|
||||
cd11a55c130b9698553086cf055dab83358bf8ab8f228bd6bec6165954d7cec3 synthetic/12-already-at-floor/reference-timing.json
|
||||
de44bbf4a1337f45f9e4efcd8a273da1a7d0fdcf30b0efdd030d9bfa7e316ef4 synthetic/12-already-at-floor/reference-update-receipt.json
|
||||
8a1db1b6202ab37e493fffd7317d35060e573d69971b1784227b908fed5e2189 synthetic/12-already-at-floor/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/12-already-at-floor/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/12-already-at-floor/reference.stdout.log
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/13-one-ulp-above-floor/command.json
|
||||
eef1d36daabc3c62903a8a37c7d97d9fab151093b0e8ce414657d0025d616d56 synthetic/13-one-ulp-above-floor/fixture.json
|
||||
f026e6530cb4965b1c290f93aeb9448ac25c0b664e26efac150f9123c22d9999 synthetic/13-one-ulp-above-floor/fixture.npz
|
||||
8187c2e9523a02c81e3815e5ab339a69a9f7c5ac5dad94769240d195e99601db synthetic/13-one-ulp-above-floor/inputs.npz
|
||||
44f428a36acc735ff46fcd58ab86bd1fa45202666f10a2e6a55ffbfea91dbec9 synthetic/13-one-ulp-above-floor/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/13-one-ulp-above-floor/reference-sources.json
|
||||
9b82a4656d3fe3d36ce601881ee01ad8138be065c838e049b172a226c9e7811b synthetic/13-one-ulp-above-floor/reference-timing.json
|
||||
3d1ea8d98acacc80c6ab9b060edf6a7e61900e14edeb9f4c2d1ccfb1eedf8677 synthetic/13-one-ulp-above-floor/reference-update-receipt.json
|
||||
2288a2514901e2ba4a40f0e474ba93f6fe0358949eb07b7c192bbd1abf103a9d synthetic/13-one-ulp-above-floor/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/13-one-ulp-above-floor/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/13-one-ulp-above-floor/reference.stdout.log
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/14-seeded-sparse-717/command.json
|
||||
d06599fccf25b62dadaec05439cc371ae879bd863ea65fd0d11f7330b1c14aba synthetic/14-seeded-sparse-717/fixture.json
|
||||
da53fa054834070a2dce17d33589d6affea01a1d14d53734d9022f4dca0e0243 synthetic/14-seeded-sparse-717/fixture.npz
|
||||
61c6cc8e7fe97b845a99665669631a88061087cab107a4b0ed6bdd76ac1b23e6 synthetic/14-seeded-sparse-717/inputs.npz
|
||||
c1d74e401b7cb9c1b69b703e91e7dc1e7902e1d43fe021717aeb2055ea6f4dda synthetic/14-seeded-sparse-717/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/14-seeded-sparse-717/reference-sources.json
|
||||
dc359baaabaaa5b5c3938e382e78b259544fd9fa12023a84d4d40c9f595b5e50 synthetic/14-seeded-sparse-717/reference-timing.json
|
||||
f0d80b1b90dae1eeac376d31e18dee7adf99c77b592f90543e87c80d35d24223 synthetic/14-seeded-sparse-717/reference-update-receipt.json
|
||||
ad0b806eb7af62b97c118bf6d9930d34560b2940a3a8094ca7937628a5450427 synthetic/14-seeded-sparse-717/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/14-seeded-sparse-717/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/14-seeded-sparse-717/reference.stdout.log
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/15-seeded-sparse-20261001/command.json
|
||||
6b8556a227c4d59be17ca5df9452298f83788c0d508683884d8d98d5087c8f07 synthetic/15-seeded-sparse-20261001/fixture.json
|
||||
490f4a9077eb391075d7ab2d815e578b099f5a8dc369cea60b83dceee7a537b9 synthetic/15-seeded-sparse-20261001/fixture.npz
|
||||
12326122901b8c4fe0e3681a60c9bb20547e96df5f194b0aab9b791689547ae4 synthetic/15-seeded-sparse-20261001/inputs.npz
|
||||
7f0272f7ae6991d2e26384b0d0f904a4e0f7c0af6035f856a040451e1fa3a417 synthetic/15-seeded-sparse-20261001/reference-process.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/15-seeded-sparse-20261001/reference-sources.json
|
||||
8bb52188b8ade787d9e6ffd6c431fc195649ee3f3eb82e5b41fe4d7c9d33f744 synthetic/15-seeded-sparse-20261001/reference-timing.json
|
||||
e7c84ab8a4e778c0188b8ce5cfc12e22a31b07ff3e8a2d9e09dc4f53c43eb6f6 synthetic/15-seeded-sparse-20261001/reference-update-receipt.json
|
||||
0f08302f390afa422aedd5a21523782a7e5f81ba3de6f9337335d84b726b4426 synthetic/15-seeded-sparse-20261001/reference.npz
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/15-seeded-sparse-20261001/reference.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/15-seeded-sparse-20261001/reference.stdout.log
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/invalid/00-duplicate-events.json
|
||||
a140bc2aa043601cc23bfee61789612c6d4980ae936e6634bb21fa7240238592 synthetic/invalid/00-duplicate-events.npz
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/invalid/01-unsorted-events.json
|
||||
381b2cb091178ecc04fbdc8d126fb8923af7c9b47c2ce0120f9fd8340529354e synthetic/invalid/01-unsorted-events.npz
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/invalid/02-out-of-range-tick.json
|
||||
4df43f8a5997243dcaa6fcba79232f89d73a8f7b1beabb2c6b0e72d309101280 synthetic/invalid/02-out-of-range-tick.npz
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/invalid/03-negative-zero-delta.json
|
||||
7e703ae325ad566b7587a41f92199dd2ad4259a48445d46dc04a482489666f8d synthetic/invalid/03-negative-zero-delta.npz
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/invalid/04-non-kc-candidate-source.json
|
||||
44ce0f662887c09ea595625d7559b408c46844e9d6831163ce18388a56365651 synthetic/invalid/04-non-kc-candidate-source.npz
|
||||
b35e3641470bbe1d8d208b93bddd9d74ecd2e48e3bd0c73ce53e1a6f2bf32a3e synthetic/invalid/05-unsorted-kc.json
|
||||
969014364818757800193802297221c3ca2769d2abf9617a4cd3da6f6ace3d53 synthetic/invalid/05-unsorted-kc.npz
|
||||
6d7c2dce81d6a4d8382ae846f947d1978a388a277241c29076203f0c92211eb0 synthetic/invalid/invalid-selection.json
|
||||
4542ec5a5ddf28f2c72fbeabf22cbee170fdd4a5a1db886738d5e469c008231a synthetic/invalid/original-rejection-process.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/invalid/original-rejection.stderr.log
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 synthetic/invalid/original-rejection.stdout.log
|
||||
780f4b54868527db6e074f55e6da9fe712c06b03926ab431561db53a513855ed synthetic/invalid/original-rejections.json
|
||||
df5b094bd8d43b0705637dafdc3091b1e98e4c6bc331fed6279b6662e883f157 synthetic/invalid/reference-sources.json
|
||||
8dd58cb8ac90040ef0b9c747b2225fa7c0f905ce6f5dd4042aef457d6b1e213d synthetic/manifest.json
|
||||
6bdd7589b203aaf0ec4e112657f538dd8bfe6b68d0e871af7e44bdaf2ae8e358 synthetic/selection.json
|
||||
5000b9ed536ab7cbed1da8622d728410135d3543faa9ae5f517d348d9dc12774 synthetic/template-binding.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 upgrade-candidate-pip.stderr.log
|
||||
c99ae4b96c48cb984b85f7897c6ff7e5ac9896fbbb62cbab17551254e058c082 upgrade-candidate-pip.stdout.log
|
||||
b966ace3825626c4b7f450f0a8f6489794b67af39c6ce878bb6546da7db45d1a upload-location-copies/export_fixtures.py
|
||||
15c46f3cbd7e4c5cf1b889150c2d142842e867af8a961dce2fe3537207999a99 upload-location-copies/launch_job.py
|
||||
68ea78f61408fc799a8f08fa644120660cac36b9920df1c91a0b6b57692ea58a upload-location-copies/test_export_fixtures.py
|
||||
3fb541a53d69399e03bda0af8e02360f6e1d0471d8fdd35b6473435e0c71e95c v100a-01/authority.json
|
||||
c20f28de4aefb3d08aa9f75699d34d620dd5097fe99c6b1b8297a3359e1e49c6 v100a-01/failure.json
|
||||
88803dac0aba8ae4d190e6582ac142a9eb7499c6f0f6d4794b336f0bcd8732fc v100a-02/authority.json
|
||||
5593a3b06be42553cff08c9c219953efd33cdb6f21ae7c573d592b4d10139635 v100a-02/fixtures--00-cs_only.json
|
||||
ce484754b351f96e453b45f42f2686b7e7165ce7ff5ab9b175dd1120c7264db0 v100a-02/fixtures--01-cs_only.json
|
||||
efe694f3b3f712aa25019b2b5d57f369a684909f0e0e7c14040297362b746aa2 v100a-02/fixtures--02-d_zero.json
|
||||
0513bbc6b466e9bc5b28637e8758f6a74bdb0abb6995f0b258649376a270dba8 v100a-02/fixtures--03-d_zero.json
|
||||
b0c9eeeb6624c815dc44052137eb269389a4d18bdac86bcc52a85347a6398f9a v100a-02/fixtures--04-dan_only.json
|
||||
dec6238ff5936c95208793dfc61cd11ac044db9f99102fcc78b1a9cf27d5a49e v100a-02/fixtures--05-dan_only.json
|
||||
c0508088d8d9a52fb6872f9057315eec312f37631f163917a8aa168847671b43 v100a-02/fixtures--06-frozen.json
|
||||
5eb1b1cd764ab0349d7336f91040878912a8bd7fc01fabfa363fe9a600527fe0 v100a-02/fixtures--07-frozen.json
|
||||
705ae0a21c3f0e364d8e0d4314920becee92524e64ef46bf3e7becf0d5d0d271 v100a-02/fixtures--08-paired.json
|
||||
6035b5551465850eb413a26fd1fc68e5b572b083fe5bb0d5f9f39eaa796a9544 v100a-02/fixtures--09-paired.json
|
||||
85ee73e7d0b15d0f37fd651d3c3cfe683559a4a03ddf4d8f71638dac382d85d4 v100a-02/fixtures--10-random_reward.json
|
||||
a3503de7e99edd5215b241184375748e68f9e62e487c50d97e640ff0b6f272b8 v100a-02/fixtures--11-random_reward.json
|
||||
c3f160b79dbd81e3ef2032ead3075e401769c12940161e5fa077b20a81ab26a2 v100a-02/fixtures--12-unpaired.json
|
||||
4383c2d5fede73b899bf93ea902ba7606b2ae9ac8244554e8feb86e7b51ec797 v100a-02/fixtures--13-unpaired.json
|
||||
d06c602fc1950f1f63f7b79e98e3fbeef2a291811c91fc7ffdaab5acfd9ea3f4 v100a-02/invalid-input-rejections.json
|
||||
221095febd8af92e5aba4663c82da8826578d7480b5bea9e08c008972986b164 v100a-02/summary.json
|
||||
e81efce736479c5c8af66ed284887b6f56f0cbf6e63991be7340406ca27c1d7f v100a-02/synthetic--00-empty-us900.json
|
||||
91e42ae01d7bf35a378418c55c10395b3f1f5dfe6e65f56b5882f19a164bc520 v100a-02/synthetic--01-non-kc-only.json
|
||||
cdcc411aedf73b30bb76425ace04f4cc634f7e60e5284b7e62104bafc3282f5c v100a-02/synthetic--02-no-us-mixed.json
|
||||
696599852b8b06c53614c8bc561bcae1fdcecef3d9f5c1a3702a7065c157db82 v100a-02/synthetic--03-us-first-tick.json
|
||||
cd2e079e7ef0b2e59056f4f57dc0cdaa0e37e969a516e3da5b0774864a6c86bb v100a-02/synthetic--04-us-final-tick.json
|
||||
292a576dab1f516f853cd61401689363688cb19c668ad6de2a8ab2d1a14bc08c v100a-02/synthetic--05-before-on-after-us900.json
|
||||
f377a37d6a92d1d04942eeb7401a186086fa6e83394f291bef13ea8ed43afdd3 v100a-02/synthetic--06-d-zero-existing-delta.json
|
||||
e649e330f5f949466ab100e269f2bc775f20373e711ff0deedf35c3410fda527 v100a-02/synthetic--07-frozen-existing-delta.json
|
||||
2764345af2d74bc4471012595613fc685aaeab206864e92c14273f7b62109a6b v100a-02/synthetic--08-compartment-0.json
|
||||
59fcb0ddc9632392859126c0a32026df8b549c3a0135c38c30749424bf5ac42a v100a-02/synthetic--09-compartment-1.json
|
||||
8fe48a6458c343a484731ac557069d82cdce0658bcfd3fc76ffbbcd2df81fd17 v100a-02/synthetic--10-compartment-2.json
|
||||
4b1667dfd7eece57a98e7217f25837084622d24408c10904044a54c3f3c392c1 v100a-02/synthetic--11-compartment-3.json
|
||||
af893b9f83a29be3481eb37d052d224f1a57a5ab9f1cc5e6b1915f26129b17a6 v100a-02/synthetic--12-already-at-floor.json
|
||||
37c18dbc87865f4e56731298e9c46268f3980f20e6af8a365f5d07ef14e0e1dc v100a-02/synthetic--13-one-ulp-above-floor.json
|
||||
c1df69852fdcb21e06f733b965b0ed810fda06d6500ddb454a0b5e26fab37ba7 v100a-02/synthetic--14-seeded-sparse-717.json
|
||||
b92d52939eb56b79c630af5088990f669422af2f3aaac358ebb66a72336538fd v100a-02/synthetic--15-seeded-sparse-20261001.json
|
||||
64cb0be8d51813d6415fd650936dc4763f408ebe103c0c552b707afbb5e2dc1f v100b-01/authority.json
|
||||
724bcb80d05bca9bc15b42cbaba2838ba5fbb1445400f8c5085febb2d71591a9 v100b-01/fixtures--00-cs_only.json
|
||||
a9f96c0493301d603dbdaab5a52fbe069c9f51f164ee11007db897e2af387ff1 v100b-01/fixtures--01-cs_only.json
|
||||
fe5c0069357004aeb18304b3b4e6e987aaf4e206479cd9f7315829f0ebcf12ef v100b-01/fixtures--02-d_zero.json
|
||||
78fc226e1d4c7baaf3d3fd005344e6d9589df71cfec8e540c0aa2f196e5c0fbc v100b-01/fixtures--03-d_zero.json
|
||||
058b7f31e3c381232cd505bebc4af2d4b3edf6f508172daf32b11f4cb4cbb32e v100b-01/fixtures--04-dan_only.json
|
||||
0098aadabd51941d24383fc28770191709ecf28970b9118b0584d90a8de08e60 v100b-01/fixtures--05-dan_only.json
|
||||
d735f73a811bf2329d89bb5bc9b790d5c97f7fb955d97c5f7cc4583f3da66b62 v100b-01/fixtures--06-frozen.json
|
||||
9ce5dd746d0bce1b76b61254f38a6c11cd142a4e3c5c392a23119923d4d6d405 v100b-01/fixtures--07-frozen.json
|
||||
7d0023c2493cc6237dfe5c4afaf4f09cd599b7d8203506f031a9829cf34f82df v100b-01/fixtures--08-paired.json
|
||||
fc8f9d8b7d65ddf5091a996775750391401e6c39ca0bba1ae72c85d0f93312c2 v100b-01/fixtures--09-paired.json
|
||||
5b94b2a06012f4fe1d8c5a9dc1afa8f84599f437050c90195698b46fe9cbc6ea v100b-01/fixtures--10-random_reward.json
|
||||
49a03a0c4083013a12150a2e5e8183fdd07dc52aa86cebc0202878238723560e v100b-01/fixtures--11-random_reward.json
|
||||
8bb0190a0d8127a98e2a2ab666bd0088d2e980ec551dcada3c19f36c4aef25c7 v100b-01/fixtures--12-unpaired.json
|
||||
62dd935445e76dd74922134633212d035b2f0fc838c63c504e6b54b46d02ed92 v100b-01/fixtures--13-unpaired.json
|
||||
d06c602fc1950f1f63f7b79e98e3fbeef2a291811c91fc7ffdaab5acfd9ea3f4 v100b-01/invalid-input-rejections.json
|
||||
efec9a44ffd1ef441152cc091b3a4801aa0ca11fafd25e8ff41f3a652bad56e7 v100b-01/summary.json
|
||||
ddac272c00c4b59ba1655aebad95a714986447bb600ac71513fed8221bcd098a v100b-01/synthetic--00-empty-us900.json
|
||||
cd1f3f2d2c356e142c84719ceea224e2e7656871fc4640a906d5f899e813e40f v100b-01/synthetic--01-non-kc-only.json
|
||||
8e4bbaaef9c0ed1a2bb15030a9f63cc25b15904a106d1f86d0df67f15855cbe8 v100b-01/synthetic--02-no-us-mixed.json
|
||||
c9cebe2da04e389aa447b9d7a963a41abd00483f0aa3a5ab8056af4ae6d3d811 v100b-01/synthetic--03-us-first-tick.json
|
||||
5abeff90afc27c87f85d614c49a641bb30f43e5baa4ce8af83689113c7cb0d23 v100b-01/synthetic--04-us-final-tick.json
|
||||
4c1e6459fc79173bd1b4632cae85952814a8830bb47b2df1400edc28be7ba2be v100b-01/synthetic--05-before-on-after-us900.json
|
||||
c6d4ad242e5b161d4313e35afc1c6bb43eb7609a5e940cad228c5e9ba767460b v100b-01/synthetic--06-d-zero-existing-delta.json
|
||||
69fa71c05cc8b7225c30a281cfed8d996c0aa936df03f3f2e202906ad96fc3f7 v100b-01/synthetic--07-frozen-existing-delta.json
|
||||
27584931bf81f1f7626315913f3603f65f3312a0261b168df9eea8719cb181db v100b-01/synthetic--08-compartment-0.json
|
||||
1ae17daa8f3972eed7d0a7be0471da24c1068b62187dee0117d1175ca605ccaf v100b-01/synthetic--09-compartment-1.json
|
||||
0392356066c68924c4c06a9b0fac47a7bef87f8feb7a20bb36e55dcd6984e7d0 v100b-01/synthetic--10-compartment-2.json
|
||||
893e197df233d6a14c509d6d76b1d1f22b7c5e0ea5d293e735b7779c8144019e v100b-01/synthetic--11-compartment-3.json
|
||||
cc643dbc8a39fe62f08bd16019036ceeb155b95e08990b5698ea2d60f2c1e42e v100b-01/synthetic--12-already-at-floor.json
|
||||
181b158d1acf072259b4be3a33e61602180193119cd34947919b38d64d0af1c8 v100b-01/synthetic--13-one-ulp-above-floor.json
|
||||
a4b60169a9a2400196207fa3fea8f85ee554725cddaefa7acb23f5bd7b7693ee v100b-01/synthetic--14-seeded-sparse-717.json
|
||||
e144a917aea30f01be01fd623f5437535211d4a4a4fe407f4fa8d17652033963 v100b-01/synthetic--15-seeded-sparse-20261001.json
|
||||
6efdec34c96cdc79f786b91bd7a99b0e8ef64d0c4dcfa525646c82659a77d44f artifact-manifest.json
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"benchmark_candidate_commit": "221e1f13f758ebe8d9f188bab976c361f7cacf45",
|
||||
"created_utc": "2026-10-01T06:43:12.585942+00:00",
|
||||
"devices": [
|
||||
{
|
||||
"benchmark_wall_seconds": 3.823799389999749,
|
||||
"bitwise_exact": true,
|
||||
"context_initialization_seconds": 0.21562433999997666,
|
||||
"cpu_baseline_sample_warning": "One cold plus ONE warm original API sample per fixture; GPU 3 warmups +20 repeats per fixture.",
|
||||
"device": {
|
||||
"compute_capability": "70",
|
||||
"cupy_version": "13.6.0",
|
||||
"driver_version": "580.178.04",
|
||||
"driver_version_runtime": 13000,
|
||||
"initialization_seconds": 0.21562433999997666,
|
||||
"memory_total_mib": "16384",
|
||||
"memory_used_mib": "918",
|
||||
"name": "Tesla V100-SXM2-16GB",
|
||||
"numpy_version": "2.2.6",
|
||||
"pci_bus_id": "00000000:24:00.0",
|
||||
"python_version": "3.10.12 (main, Aug 31 2026, 10:18:17) [GCC 11.4.0]",
|
||||
"runtime_name": "Tesla V100-SXM2-16GB",
|
||||
"runtime_pci_bus_id": "0000:24:00.0",
|
||||
"runtime_version": 12090,
|
||||
"utilization_percent": "0",
|
||||
"uuid": "GPU-a745fd30-4ca8-2370-09f6-2d374ac866dc"
|
||||
},
|
||||
"first_use_compile_seconds": 0.5175303470000472,
|
||||
"invalid_inputs_rejected": 6,
|
||||
"mean_real_fixture_candidate_replay_seconds": 0.0030653400000021846,
|
||||
"median_real_fixture_candidate_replay_seconds": 0.0034301260000120237,
|
||||
"median_real_fixture_cpu_cold_update_api_seconds": 1.3763328334998732,
|
||||
"median_real_fixture_cpu_original_update_api_seconds": 0.10878832900016278,
|
||||
"median_real_fixture_resident_kernel_seconds": 0.00012198399752378464,
|
||||
"observed_cuda_pool_reserved_peak_bytes": 367616,
|
||||
"original_update_api_to_candidate_replay_ratio": 31.81186385112393,
|
||||
"positive_fixtures": 30,
|
||||
"ratio_warning": "Different API overhead boundaries: original U checks/AST every call; candidate authenticates sources/mapping once. NOT pure CPU/GPU hardware ratio.",
|
||||
"real_fixture_count": 14,
|
||||
"result_sha256": "221095febd8af92e5aba4663c82da8826578d7480b5bea9e08c008972986b164",
|
||||
"run": "v100a-02"
|
||||
},
|
||||
{
|
||||
"benchmark_wall_seconds": 3.6053910950004138,
|
||||
"bitwise_exact": true,
|
||||
"context_initialization_seconds": 0.21543903399970077,
|
||||
"cpu_baseline_sample_warning": "One cold plus ONE warm original API sample per fixture; GPU 3 warmups +20 repeats per fixture.",
|
||||
"device": {
|
||||
"compute_capability": "70",
|
||||
"cupy_version": "13.6.0",
|
||||
"driver_version": "580.178.04",
|
||||
"driver_version_runtime": 13000,
|
||||
"initialization_seconds": 0.21543903399970077,
|
||||
"memory_total_mib": "16384",
|
||||
"memory_used_mib": "312",
|
||||
"name": "Tesla V100-SXM2-16GB",
|
||||
"numpy_version": "2.2.6",
|
||||
"pci_bus_id": "00000000:25:00.0",
|
||||
"python_version": "3.10.12 (main, Aug 31 2026, 10:18:17) [GCC 11.4.0]",
|
||||
"runtime_name": "Tesla V100-SXM2-16GB",
|
||||
"runtime_pci_bus_id": "0000:25:00.0",
|
||||
"runtime_version": 12090,
|
||||
"utilization_percent": "0",
|
||||
"uuid": "GPU-0f0ff6ed-bf1f-50ea-c244-b4566eccc66a"
|
||||
},
|
||||
"first_use_compile_seconds": 0.34027977499999906,
|
||||
"invalid_inputs_rejected": 6,
|
||||
"mean_real_fixture_candidate_replay_seconds": 0.002988729749956422,
|
||||
"median_real_fixture_candidate_replay_seconds": 0.0033436992500810447,
|
||||
"median_real_fixture_cpu_cold_update_api_seconds": 1.3763328334998732,
|
||||
"median_real_fixture_cpu_original_update_api_seconds": 0.10878832900016278,
|
||||
"median_real_fixture_resident_kernel_seconds": 0.00012160000205039978,
|
||||
"observed_cuda_pool_reserved_peak_bytes": 367616,
|
||||
"original_update_api_to_candidate_replay_ratio": 32.71325311168391,
|
||||
"positive_fixtures": 30,
|
||||
"ratio_warning": "Different API overhead boundaries: original U checks/AST every call; candidate authenticates sources/mapping once. NOT pure CPU/GPU hardware ratio.",
|
||||
"real_fixture_count": 14,
|
||||
"result_sha256": "efec9a44ffd1ef441152cc091b3a4801aa0ca11fafd25e8ff41f3a652bad56e7",
|
||||
"run": "v100b-01"
|
||||
},
|
||||
{
|
||||
"benchmark_wall_seconds": 3.542117918999793,
|
||||
"bitwise_exact": true,
|
||||
"context_initialization_seconds": 0.24383461099978376,
|
||||
"cpu_baseline_sample_warning": "One cold plus ONE warm original API sample per fixture; GPU 3 warmups +20 repeats per fixture.",
|
||||
"device": {
|
||||
"compute_capability": "89",
|
||||
"cupy_version": "13.6.0",
|
||||
"driver_version": "580.178.04",
|
||||
"driver_version_runtime": 13000,
|
||||
"initialization_seconds": 0.24383461099978376,
|
||||
"memory_total_mib": "49140",
|
||||
"memory_used_mib": "396",
|
||||
"name": "NVIDIA GeForce RTX 4090",
|
||||
"numpy_version": "2.2.6",
|
||||
"pci_bus_id": "00000000:81:00.0",
|
||||
"python_version": "3.10.12 (main, Aug 31 2026, 10:18:17) [GCC 11.4.0]",
|
||||
"runtime_name": "NVIDIA GeForce RTX 4090",
|
||||
"runtime_pci_bus_id": "0000:81:00.0",
|
||||
"runtime_version": 12090,
|
||||
"utilization_percent": "0",
|
||||
"uuid": "GPU-79f3a85d-adce-7833-7003-6488140ca596"
|
||||
},
|
||||
"first_use_compile_seconds": 0.3366978859999108,
|
||||
"invalid_inputs_rejected": 6,
|
||||
"mean_real_fixture_candidate_replay_seconds": 0.002947911642812479,
|
||||
"median_real_fixture_candidate_replay_seconds": 0.00332674724984372,
|
||||
"median_real_fixture_cpu_cold_update_api_seconds": 1.3763328334998732,
|
||||
"median_real_fixture_cpu_original_update_api_seconds": 0.10878832900016278,
|
||||
"median_real_fixture_resident_kernel_seconds": 7.372800260782241e-05,
|
||||
"observed_cuda_pool_reserved_peak_bytes": 367616,
|
||||
"original_update_api_to_candidate_replay_ratio": 32.80226555755503,
|
||||
"positive_fixtures": 30,
|
||||
"ratio_warning": "Different API overhead boundaries: original U checks/AST every call; candidate authenticates sources/mapping once. NOT pure CPU/GPU hardware ratio.",
|
||||
"real_fixture_count": 14,
|
||||
"result_sha256": "377cb655e5b6e5816ccca3b5a03c481021afc3da64879af9be72c207e88639c7",
|
||||
"run": "rtx4090-01"
|
||||
}
|
||||
],
|
||||
"fixes_preserved": [
|
||||
"Initial candidate pip22 lacked--report; upgraded pip only in new venv",
|
||||
"First GPU compile rejected conflictingFTZ options; no kernel executed; explicit nvcc compilation retains original precision"
|
||||
],
|
||||
"frozen_integrity": {
|
||||
"bytes_checked": 3103901058,
|
||||
"created_utc": "2026-10-01T06:43:10.470895+00:00",
|
||||
"file_mismatches": [],
|
||||
"files_checked": 64034,
|
||||
"inventory_sha256": "d7b675b0d0d4647d8fe2fcf9616b9a599e5bc3c15565e604e0d66a046afb835a",
|
||||
"original_experiment_resumed": false,
|
||||
"original_git_head": "09187e4d4d67badf1b418c5f211258ca5d8fb328",
|
||||
"original_git_status": "",
|
||||
"probes_completed_unchanged": 138,
|
||||
"registered_science_commit": "80aeb2093db655329774eff7b32fb6e417b8b40b",
|
||||
"registration_sha256": "b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740",
|
||||
"scope": "Saved Phase4AR experiment/control files and registered source files; NOT a new Phase1-4AQ numerical regression",
|
||||
"source_mismatches": [],
|
||||
"sources_checked": 16,
|
||||
"status": "PASS",
|
||||
"training_epochs_cpu_verified_unchanged": 1033,
|
||||
"wall_seconds": 4.8638160139998945
|
||||
},
|
||||
"full_brain_gpu_event_equivalence_tested": false,
|
||||
"full_training_acceleration_measured": false,
|
||||
"learned_candidate_created": false,
|
||||
"limitations": [
|
||||
"Replay module only, not a production training backend",
|
||||
"The sampled committed prefix covers7arms but only available physiological/PAM15/reinforce_A subset",
|
||||
"Repeated kernel calculations reset state and replay identical saved inputs, not additional learning trials",
|
||||
"Original CPU verification remains independent and required",
|
||||
"No simultaneous two-V100 training/scheduling benchmark; devices tested separately",
|
||||
"Original9.07-day estimate is not replaced by this component benchmark"
|
||||
],
|
||||
"next_work": "Separately validate persistent training/update/verification workers and complete chain timing before authorizing a new scientific execution version",
|
||||
"original_experiment_resumed": false,
|
||||
"report_code_commit": "221e1f13f758ebe8d9f188bab976c361f7cacf45",
|
||||
"scientific_experiment_status": "STOPPED, unchanged:1033/30000 CPU-verified training epochs and138/3920 probes",
|
||||
"status": "PASS-ELIGIBILITY-UPDATE-REPLAY-EQUIVALENCE",
|
||||
"weights_installed": false
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"catalog_sha256": "28071f276848ea60149f21a9794653486b404670a58b34d97b1aaae742095245",
|
||||
"groups": {
|
||||
"gpu": {
|
||||
"archive_bytes": 1679158,
|
||||
"files": 614,
|
||||
"original_bytes": 13242628,
|
||||
"sha256": "50acdc85342a2c79c3516e50ee4542b909813d179518451edaaf2d94150c534b",
|
||||
"verified": true
|
||||
},
|
||||
"pipeline": {
|
||||
"archive_bytes": 74767927,
|
||||
"files": 1066,
|
||||
"original_bytes": 103062185,
|
||||
"sha256": "fdc39013d71fb7d14313d8249c929601a8a7050cc2eac88b733d692bbe1b6b42",
|
||||
"verified": true
|
||||
}
|
||||
},
|
||||
"pass_all": true,
|
||||
"verification": "Full streamed members, no extraction or model execution"
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
# 常驻进程工程回放结果
|
||||
|
||||
状态:`PASS-PERSISTENT-REPLAY-EQUIVALENCE`。仅限这次固定回放,不代表学习成功或正式运行时升级。
|
||||
|
||||
## 实测
|
||||
|
||||
| 测量范围 | 新进程 | 常驻进程 | 说明 |
|
||||
|---|---:|---:|---|
|
||||
| 原始 CPU 更新 API | 1.3480 s | 0.1182 s | 新进程首次 API 包含导入等开销 |
|
||||
| 完整更新 API,同一固定案例 | 3.7089 s | 2.3424 s | 仅一组冷启动对照 |
|
||||
| 全脑原始运行函数,13 组配对中位数 | 5.9825 s | 3.7222 s | 含原有输出;排除固定首例的初始化 |
|
||||
|
||||
完整更新常驻 14 组中位耗时:2.3483 s。
|
||||
完整独立验证仍需:3.6435 s(14 组中位数)。
|
||||
全脑运行函数同案例配对倍率中位数:1.620×,不是整轮训练加速倍率。
|
||||
|
||||
## 一致性与保护
|
||||
|
||||
- 17 项主机测试通过。
|
||||
- CPU:14 次冷启动更新、42 次独立双进程更新/重算、29 次完整更新、14 次完整独立验证通过。
|
||||
- 全脑:14 次新进程、正序 14 次与逆序 14 次常驻回放;所有脉冲、状态、延迟队列和请求等一致,10 个数组逐位相同。
|
||||
- 64,034 个原实验文件与 16 个注册源码重新校验通过;之前 659 个加速产物和 13 个源码保持不变。
|
||||
- 原 Phase4AR 仍停止于 1,033 轮 CPU 校验训练与 138 次 probe,没有新增训练或安装新权重。
|
||||
|
||||
## 边界与下一步
|
||||
|
||||
本次全脑测试使用原 RTX 4090 环境,没有证明全脑已能迁移到 V100。此前 V100 约 3.4 ms 的成绩仅属于 eligibility/update 模块。
|
||||
常驻进程复用的是解释器、模块和 CUDA 上下文;每轮神经状态仍由原始函数重新分配。
|
||||
当前仍保留完整验证、图和权重上传、记录写盘。下一步应在新的可审计流水线中验证整轮开销,不能把本报告的独立阶段相加当作实测训练速度。
|
||||
|
||||
源码提交:`018f038c7857c7e0236dd7408a680458520d92ce`。完整逐例耗时、实际进程退出、来源校验见 `final-summary.json` 和各 lane 报告。
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,532 @@
|
||||
{
|
||||
"brain_matched_pairs": [
|
||||
{
|
||||
"first_fixture_cold_build_and_context": true,
|
||||
"fixed_index": 0,
|
||||
"fixture_id": "00-cs_only",
|
||||
"fresh_runtime_seconds": 65.35286720699969,
|
||||
"fresh_simulation_seconds": 2.614504967999892,
|
||||
"fresh_trial_wall_seconds": 67.3396666159997,
|
||||
"resident_runtime_seconds": 4.829426256000261,
|
||||
"resident_simulation_seconds": 2.4258526345001883,
|
||||
"resident_trial_wall_seconds": 7.01521050700012,
|
||||
"runtime_ratio": 13.532221788416964,
|
||||
"trial_wall_ratio": 9.599094218028796
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 1,
|
||||
"fixture_id": "01-cs_only",
|
||||
"fresh_runtime_seconds": 5.984003917999871,
|
||||
"fresh_simulation_seconds": 2.593902593999701,
|
||||
"fresh_trial_wall_seconds": 8.017140279999694,
|
||||
"resident_runtime_seconds": 3.7571635549998064,
|
||||
"resident_simulation_seconds": 2.295868848999362,
|
||||
"resident_trial_wall_seconds": 5.915995811999892,
|
||||
"runtime_ratio": 1.5926918885489347,
|
||||
"trial_wall_ratio": 1.355163278469177
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 2,
|
||||
"fixture_id": "02-d_zero",
|
||||
"fresh_runtime_seconds": 5.9979634660003285,
|
||||
"fresh_simulation_seconds": 2.5769733950000955,
|
||||
"fresh_trial_wall_seconds": 8.022121797000182,
|
||||
"resident_runtime_seconds": 3.751296795000144,
|
||||
"resident_simulation_seconds": 2.2797322554997663,
|
||||
"resident_trial_wall_seconds": 5.890771792999658,
|
||||
"runtime_ratio": 1.5989040040752356,
|
||||
"trial_wall_ratio": 1.3618116740718642
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 3,
|
||||
"fixture_id": "03-d_zero",
|
||||
"fresh_runtime_seconds": 5.982476725000197,
|
||||
"fresh_simulation_seconds": 2.5773725859999104,
|
||||
"fresh_trial_wall_seconds": 8.00832260900006,
|
||||
"resident_runtime_seconds": 3.7547762260001036,
|
||||
"resident_simulation_seconds": 2.319585893000294,
|
||||
"resident_trial_wall_seconds": 5.895358800500162,
|
||||
"runtime_ratio": 1.5932978065574956,
|
||||
"trial_wall_ratio": 1.358411401240012
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 4,
|
||||
"fixture_id": "04-dan_only",
|
||||
"fresh_runtime_seconds": 4.749538970000685,
|
||||
"fresh_simulation_seconds": 1.3650442850002946,
|
||||
"fresh_trial_wall_seconds": 6.727319513999646,
|
||||
"resident_runtime_seconds": 2.529837508000128,
|
||||
"resident_simulation_seconds": 1.1021227920000456,
|
||||
"resident_trial_wall_seconds": 4.626612702999864,
|
||||
"runtime_ratio": 1.877408709049959,
|
||||
"trial_wall_ratio": 1.4540485547099495
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 5,
|
||||
"fixture_id": "05-dan_only",
|
||||
"fresh_runtime_seconds": 4.794270962000155,
|
||||
"fresh_simulation_seconds": 1.3635098229997311,
|
||||
"fresh_trial_wall_seconds": 6.785381824000069,
|
||||
"resident_runtime_seconds": 2.5495016239997312,
|
||||
"resident_simulation_seconds": 1.0964573165001639,
|
||||
"resident_trial_wall_seconds": 4.630903192000005,
|
||||
"runtime_ratio": 1.8804737823538882,
|
||||
"trial_wall_ratio": 1.4652394020505497
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 6,
|
||||
"fixture_id": "06-frozen",
|
||||
"fresh_runtime_seconds": 5.943664408000586,
|
||||
"fresh_simulation_seconds": 2.537586863000797,
|
||||
"fresh_trial_wall_seconds": 7.968554020000738,
|
||||
"resident_runtime_seconds": 3.739337917499597,
|
||||
"resident_simulation_seconds": 2.274588298999788,
|
||||
"resident_trial_wall_seconds": 5.863817397000275,
|
||||
"runtime_ratio": 1.5894964667902942,
|
||||
"trial_wall_ratio": 1.3589362492899544
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 7,
|
||||
"fixture_id": "07-frozen",
|
||||
"fresh_runtime_seconds": 6.110534065999673,
|
||||
"fresh_simulation_seconds": 2.582069095999941,
|
||||
"fresh_trial_wall_seconds": 8.228193209999517,
|
||||
"resident_runtime_seconds": 3.7222462010004165,
|
||||
"resident_simulation_seconds": 2.302735479000148,
|
||||
"resident_trial_wall_seconds": 5.8500312219998705,
|
||||
"runtime_ratio": 1.641625442281965,
|
||||
"trial_wall_ratio": 1.4065212471099697
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 8,
|
||||
"fixture_id": "08-paired",
|
||||
"fresh_runtime_seconds": 6.045053863999783,
|
||||
"fresh_simulation_seconds": 2.56315154099957,
|
||||
"fresh_trial_wall_seconds": 8.07308078099959,
|
||||
"resident_runtime_seconds": 3.7187771884996437,
|
||||
"resident_simulation_seconds": 2.292921604500407,
|
||||
"resident_trial_wall_seconds": 5.844987367499925,
|
||||
"runtime_ratio": 1.6255488182228754,
|
||||
"trial_wall_ratio": 1.381197301792063
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 9,
|
||||
"fixture_id": "09-paired",
|
||||
"fresh_runtime_seconds": 6.0329436539996095,
|
||||
"fresh_simulation_seconds": 2.578432846999931,
|
||||
"fresh_trial_wall_seconds": 8.06702318600037,
|
||||
"resident_runtime_seconds": 3.752024064000125,
|
||||
"resident_simulation_seconds": 2.3125394145004066,
|
||||
"resident_trial_wall_seconds": 5.875522780999745,
|
||||
"runtime_ratio": 1.6079171005016797,
|
||||
"trial_wall_ratio": 1.3729881555540036
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 10,
|
||||
"fixture_id": "10-random_reward",
|
||||
"fresh_runtime_seconds": 5.9459936279999965,
|
||||
"fresh_simulation_seconds": 2.5486168549996364,
|
||||
"fresh_trial_wall_seconds": 7.969415038999614,
|
||||
"resident_runtime_seconds": 3.741656974500529,
|
||||
"resident_simulation_seconds": 2.2819819735000237,
|
||||
"resident_trial_wall_seconds": 5.869267663999835,
|
||||
"runtime_ratio": 1.5891338165208806,
|
||||
"trial_wall_ratio": 1.3578210255908747
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 11,
|
||||
"fixture_id": "11-random_reward",
|
||||
"fresh_runtime_seconds": 6.022653824999907,
|
||||
"fresh_simulation_seconds": 2.577513352999631,
|
||||
"fresh_trial_wall_seconds": 8.047795367000617,
|
||||
"resident_runtime_seconds": 3.7174769284997637,
|
||||
"resident_simulation_seconds": 2.3056816289999915,
|
||||
"resident_trial_wall_seconds": 5.856069947500146,
|
||||
"runtime_ratio": 1.6200917829046022,
|
||||
"trial_wall_ratio": 1.3742655806965012
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 12,
|
||||
"fixture_id": "12-unpaired",
|
||||
"fresh_runtime_seconds": 4.770189471999402,
|
||||
"fresh_simulation_seconds": 1.3640906330001599,
|
||||
"fresh_trial_wall_seconds": 6.746124274999602,
|
||||
"resident_runtime_seconds": 2.5186805469998035,
|
||||
"resident_simulation_seconds": 1.1082154464997984,
|
||||
"resident_trial_wall_seconds": 4.599120383999889,
|
||||
"runtime_ratio": 1.8939239744720884,
|
||||
"trial_wall_ratio": 1.4668292437982342
|
||||
},
|
||||
{
|
||||
"first_fixture_cold_build_and_context": false,
|
||||
"fixed_index": 13,
|
||||
"fixture_id": "13-unpaired",
|
||||
"fresh_runtime_seconds": 4.788546644000235,
|
||||
"fresh_simulation_seconds": 1.3511515399995915,
|
||||
"fresh_trial_wall_seconds": 6.774379648000831,
|
||||
"resident_runtime_seconds": 2.5566162760001134,
|
||||
"resident_simulation_seconds": 1.1084074525001597,
|
||||
"resident_trial_wall_seconds": 4.625984206500107,
|
||||
"runtime_ratio": 1.8730017050083203,
|
||||
"trial_wall_ratio": 1.4644191042593597
|
||||
}
|
||||
],
|
||||
"brain_steady_13_fixture_summary": {
|
||||
"fresh_runtime_seconds": {
|
||||
"count": 13,
|
||||
"maximum": 6.110534065999673,
|
||||
"mean": 5.628294892461572,
|
||||
"median": 5.982476725000197,
|
||||
"minimum": 4.749538970000685,
|
||||
"total": 73.16783360200043
|
||||
},
|
||||
"fresh_simulation_seconds": {
|
||||
"count": 13,
|
||||
"maximum": 2.593902593999701,
|
||||
"mean": 2.198416570076845,
|
||||
"median": 2.56315154099957,
|
||||
"minimum": 1.3511515399995915,
|
||||
"total": 28.57941541099899
|
||||
},
|
||||
"fresh_trial_wall_seconds": {
|
||||
"count": 13,
|
||||
"maximum": 8.228193209999517,
|
||||
"mean": 7.648834734615425,
|
||||
"median": 8.00832260900006,
|
||||
"minimum": 6.727319513999646,
|
||||
"total": 99.43485155000053
|
||||
},
|
||||
"resident_runtime_seconds": {
|
||||
"count": 13,
|
||||
"maximum": 3.7571635549998064,
|
||||
"mean": 3.3699532157692236,
|
||||
"median": 3.7222462010004165,
|
||||
"minimum": 2.5186805469998035,
|
||||
"total": 43.809391804999905
|
||||
},
|
||||
"resident_simulation_seconds": {
|
||||
"count": 13,
|
||||
"maximum": 2.319585893000294,
|
||||
"mean": 1.9292952618846426,
|
||||
"median": 2.2819819735000237,
|
||||
"minimum": 1.0964573165001639,
|
||||
"total": 25.080838404500355
|
||||
},
|
||||
"resident_trial_wall_seconds": {
|
||||
"count": 13,
|
||||
"maximum": 5.915995811999892,
|
||||
"mean": 5.4880340976922595,
|
||||
"median": 5.856069947500146,
|
||||
"minimum": 4.599120383999889,
|
||||
"total": 71.34444326999937
|
||||
},
|
||||
"runtime_ratio": {
|
||||
"count": 13,
|
||||
"maximum": 1.8939239744720884,
|
||||
"mean": 1.69103963825294,
|
||||
"median": 1.6200917829046022,
|
||||
"minimum": 1.5891338165208806,
|
||||
"total": 21.98351529728822
|
||||
},
|
||||
"trial_wall_ratio": {
|
||||
"count": 13,
|
||||
"maximum": 1.4668292437982342,
|
||||
"mean": 1.3982809398948086,
|
||||
"median": 1.3742655806965012,
|
||||
"minimum": 1.355163278469177,
|
||||
"total": 18.177652218632513
|
||||
}
|
||||
},
|
||||
"cpu_regression": {
|
||||
"cold_U": 14,
|
||||
"full_AQ_on_new_E_outputs": 14,
|
||||
"full_E_cold": 1,
|
||||
"full_E_resident": 28,
|
||||
"host_tests": 17,
|
||||
"resident_update_plus_independent_verification": 42
|
||||
},
|
||||
"cpu_summary": {
|
||||
"cold_U_API_seconds": {
|
||||
"count": 14,
|
||||
"maximum": 1.3637360310003714,
|
||||
"mean": 1.349338465785747,
|
||||
"median": 1.3479703455000163,
|
||||
"minimum": 1.3283745310000086,
|
||||
"sum": 18.890738521000458
|
||||
},
|
||||
"cold_U_subprocess_wall_seconds": {
|
||||
"count": 14,
|
||||
"maximum": 1.8981196659997295,
|
||||
"mean": 1.885562129142792,
|
||||
"median": 1.8844832749996385,
|
||||
"minimum": 1.8637141089993747,
|
||||
"sum": 26.397869807999086
|
||||
},
|
||||
"cold_input_load_verify_seconds": {
|
||||
"count": 14,
|
||||
"maximum": 0.010746739999376587,
|
||||
"mean": 0.009368129571612371,
|
||||
"median": 0.00954562650031221,
|
||||
"minimum": 0.008100717999695917,
|
||||
"sum": 0.1311538140025732
|
||||
},
|
||||
"cold_worker_startup_wall_seconds": {
|
||||
"count": 14,
|
||||
"maximum": 0.10847249400012515,
|
||||
"mean": 0.10693613914281741,
|
||||
"median": 0.10691448550051064,
|
||||
"minimum": 0.10573622599986265,
|
||||
"sum": 1.4971059479994437
|
||||
},
|
||||
"original_full_AQ_subprocess_wall_seconds": {
|
||||
"count": 14,
|
||||
"maximum": 3.668942025999968,
|
||||
"mean": 3.643564634214207,
|
||||
"median": 3.6435176954996678,
|
||||
"minimum": 3.618401282999912,
|
||||
"sum": 51.009904878998896
|
||||
},
|
||||
"original_full_E_cold_first_API_seconds": 3.7089290359999723,
|
||||
"original_full_E_cold_first_process_wall_seconds": 4.24782893199972,
|
||||
"original_full_E_warm_API_seconds": {
|
||||
"count": 14,
|
||||
"maximum": 2.4132408899995426,
|
||||
"mean": 2.3535953922856345,
|
||||
"median": 2.3438503964998745,
|
||||
"minimum": 2.2940232779992584,
|
||||
"sum": 32.950335491998885
|
||||
},
|
||||
"original_full_E_warm_roundtrip_seconds": {
|
||||
"count": 14,
|
||||
"maximum": 2.4179386750001868,
|
||||
"mean": 2.358171566214488,
|
||||
"median": 2.348314214000311,
|
||||
"minimum": 2.2985241940004926,
|
||||
"sum": 33.01440192700284
|
||||
},
|
||||
"resident_warm_U_API_seconds": {
|
||||
"count": 28,
|
||||
"maximum": 0.17676272300013807,
|
||||
"mean": 0.13507185135706226,
|
||||
"median": 0.11820473399984621,
|
||||
"minimum": 0.11332106000008935,
|
||||
"sum": 3.782011837997743
|
||||
},
|
||||
"resident_warm_pair_roundtrip_seconds": {
|
||||
"count": 28,
|
||||
"maximum": 0.3602939359998345,
|
||||
"mean": 0.27662439482141316,
|
||||
"median": 0.24055810749996454,
|
||||
"minimum": 0.22945901599996432,
|
||||
"sum": 7.745483054999568
|
||||
},
|
||||
"resident_warm_verify_API_seconds": {
|
||||
"count": 28,
|
||||
"maximum": 0.17938798499926634,
|
||||
"mean": 0.13211264517862478,
|
||||
"median": 0.1128409300004023,
|
||||
"minimum": 0.10732271400047466,
|
||||
"sum": 3.699154065001494
|
||||
}
|
||||
},
|
||||
"created_utc": "2026-10-01T07:19:11.514183+00:00",
|
||||
"first_brain_fixture": {
|
||||
"first_fixture_cold_build_and_context": true,
|
||||
"fixed_index": 0,
|
||||
"fixture_id": "00-cs_only",
|
||||
"fresh_runtime_seconds": 65.35286720699969,
|
||||
"fresh_simulation_seconds": 2.614504967999892,
|
||||
"fresh_trial_wall_seconds": 67.3396666159997,
|
||||
"resident_runtime_seconds": 4.829426256000261,
|
||||
"resident_simulation_seconds": 2.4258526345001883,
|
||||
"resident_trial_wall_seconds": 7.01521050700012,
|
||||
"runtime_ratio": 13.532221788416964,
|
||||
"trial_wall_ratio": 9.599094218028796
|
||||
},
|
||||
"fixture_manifest_sha256": "481df128d39bf28e5984a6f2e5757f83d45cb7a6136f8d2843ecc0a67eca437b",
|
||||
"full_E_same_fixture_API_comparison": {
|
||||
"API_ratio": 1.5833984849811464,
|
||||
"cold_API_seconds": 3.7089290359999723,
|
||||
"fixture_id": "00-cs_only",
|
||||
"sample_warning": "One fixed-first cold sample; not a 14-fixture matched cold E study",
|
||||
"warm_API_seconds": 2.3423851110001124
|
||||
},
|
||||
"full_brain_regression": {
|
||||
"actual_child_exits_observed_zero": 15,
|
||||
"all_bitwise_exact": true,
|
||||
"arrays_per_trial": 10,
|
||||
"fresh": 14,
|
||||
"resident_forward": 14,
|
||||
"resident_reverse": 14
|
||||
},
|
||||
"integrity": {
|
||||
"fixture_manifest_sha256": "481df128d39bf28e5984a6f2e5757f83d45cb7a6136f8d2843ecc0a67eca437b",
|
||||
"old_artifacts_modified": false,
|
||||
"original": {
|
||||
"bytes_checked": 3103901058,
|
||||
"created_utc": "2026-10-01T07:17:32.838570+00:00",
|
||||
"file_mismatches": [],
|
||||
"files_checked": 64034,
|
||||
"inventory_sha256": "d7b675b0d0d4647d8fe2fcf9616b9a599e5bc3c15565e604e0d66a046afb835a",
|
||||
"original_experiment_resumed": false,
|
||||
"original_git_head": "09187e4d4d67badf1b418c5f211258ca5d8fb328",
|
||||
"original_git_status": "",
|
||||
"probes_completed_unchanged": 138,
|
||||
"registered_science_commit": "80aeb2093db655329774eff7b32fb6e417b8b40b",
|
||||
"registration_sha256": "b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740",
|
||||
"scope": "Saved Phase4AR experiment/control files and registered source files; NOT a new Phase1-4AQ numerical regression",
|
||||
"source_mismatches": [],
|
||||
"sources_checked": 16,
|
||||
"status": "PASS",
|
||||
"training_epochs_cpu_verified_unchanged": 1033,
|
||||
"wall_seconds": 5.062658503000421
|
||||
},
|
||||
"original_AR_resumed": false,
|
||||
"previous_engineering_files_checked": 659,
|
||||
"previous_engineering_sources_checked": 13,
|
||||
"previous_manifest_sha256": "6efdec34c96cdc79f786b91bd7a99b0e8ef64d0c4dcfa525646c82659a77d44f",
|
||||
"status": "PASS",
|
||||
"wall_seconds": 5.197849371999837
|
||||
},
|
||||
"jobs": {
|
||||
"brain-replay-01": {
|
||||
"command": [
|
||||
"/data/digital-drosophila/models/male-cns-lif/.venv/bin/python",
|
||||
"-B",
|
||||
"/home/qishizhe/digital-drosophila-v100-acceleration/models/male-cns-lif/conditioning-pipeline-acceleration-v1/brain_replay.py",
|
||||
"--fixtures",
|
||||
"/home/qishizhe/phase4ar-v100-acceleration-20261001/fixtures",
|
||||
"--fixture-manifest-sha256",
|
||||
"481df128d39bf28e5984a6f2e5757f83d45cb7a6136f8d2843ecc0a67eca437b",
|
||||
"--output",
|
||||
"/home/qishizhe/phase4ar-pipeline-acceleration-20261001/brain-replay"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"finished_utc": "2026-10-01T07:17:05.441907+00:00",
|
||||
"label": "brain-replay-01",
|
||||
"observed_exit": true,
|
||||
"pid": 35046,
|
||||
"process_group": 35046,
|
||||
"scientific_AR_resumed": false,
|
||||
"scope": "independent engineering replay only",
|
||||
"started_utc": "2026-10-01T07:11:17.781251+00:00",
|
||||
"stop_reason": null,
|
||||
"timed_out": false,
|
||||
"wall_seconds": 347.66065984800025
|
||||
},
|
||||
"brain-unit-tests": {
|
||||
"command": [
|
||||
"/data/digital-drosophila/models/male-cns-lif/.venv/bin/python",
|
||||
"-B",
|
||||
"-m",
|
||||
"unittest",
|
||||
"discover",
|
||||
"-s",
|
||||
"/home/qishizhe/digital-drosophila-v100-acceleration/models/male-cns-lif/conditioning-pipeline-acceleration-v1",
|
||||
"-p",
|
||||
"test_brain_replay.py",
|
||||
"-v"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"finished_utc": "2026-10-01T07:08:49.205842+00:00",
|
||||
"label": "brain-unit-tests",
|
||||
"observed_exit": true,
|
||||
"pid": 34762,
|
||||
"process_group": 34762,
|
||||
"scientific_AR_resumed": false,
|
||||
"scope": "independent engineering replay only",
|
||||
"started_utc": "2026-10-01T07:08:49.035004+00:00",
|
||||
"stop_reason": null,
|
||||
"timed_out": false,
|
||||
"wall_seconds": 0.17084325300038472
|
||||
},
|
||||
"cpu-profile-01": {
|
||||
"command": [
|
||||
"/data/digital-drosophila/models/male-cns-lif/.venv/bin/python",
|
||||
"-B",
|
||||
"/home/qishizhe/digital-drosophila-v100-acceleration/models/male-cns-lif/conditioning-pipeline-acceleration-v1/profile_original.py",
|
||||
"--fixtures",
|
||||
"/home/qishizhe/phase4ar-v100-acceleration-20261001/fixtures",
|
||||
"--fixture-manifest-sha256",
|
||||
"481df128d39bf28e5984a6f2e5757f83d45cb7a6136f8d2843ecc0a67eca437b",
|
||||
"--output",
|
||||
"/home/qishizhe/phase4ar-pipeline-acceleration-20261001/cpu-profile",
|
||||
"--repeats",
|
||||
"3"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"finished_utc": "2026-10-01T07:08:22.538896+00:00",
|
||||
"label": "cpu-profile-01",
|
||||
"observed_exit": true,
|
||||
"pid": 27868,
|
||||
"process_group": 27868,
|
||||
"scientific_AR_resumed": false,
|
||||
"scope": "independent engineering replay only",
|
||||
"started_utc": "2026-10-01T07:05:31.857063+00:00",
|
||||
"stop_reason": null,
|
||||
"timed_out": false,
|
||||
"wall_seconds": 170.68183461700028
|
||||
},
|
||||
"cpu-unit-tests": {
|
||||
"command": [
|
||||
"/data/digital-drosophila/models/male-cns-lif/.venv/bin/python",
|
||||
"-B",
|
||||
"-m",
|
||||
"unittest",
|
||||
"discover",
|
||||
"-s",
|
||||
"/home/qishizhe/digital-drosophila-v100-acceleration/models/male-cns-lif/conditioning-pipeline-acceleration-v1",
|
||||
"-p",
|
||||
"test_profile_original.py",
|
||||
"-v"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"finished_utc": "2026-10-01T07:01:44.742692+00:00",
|
||||
"label": "cpu-unit-tests",
|
||||
"observed_exit": true,
|
||||
"pid": 27719,
|
||||
"process_group": 27719,
|
||||
"scientific_AR_resumed": false,
|
||||
"scope": "independent engineering replay only",
|
||||
"started_utc": "2026-10-01T07:01:44.577624+00:00",
|
||||
"stop_reason": null,
|
||||
"timed_out": false,
|
||||
"wall_seconds": 0.165072402000078
|
||||
}
|
||||
},
|
||||
"limitations": [
|
||||
"Fixed 14 real committed-prefix fixtures only; not the full scientific design.",
|
||||
"Fresh means fresh interpreter, not flushed filesystem caches.",
|
||||
"Brain uses unchanged original 4090 runtime; whole-brain V100 compatibility remains unestablished.",
|
||||
"Original GPU tensors/graph are still allocated and uploaded each trial; no numerical loop rewrite.",
|
||||
"Brain runtime timings include its original output I/O. Trial wall also includes extra audit checks.",
|
||||
"Resident trial audit additionally checks the current fresh reference, making trial-wall boundaries unequal.",
|
||||
"Paired steady timing excludes fixed fixture 0 cold initialization in both lanes; correctness excludes none.",
|
||||
"Independent measured stages are not a combined training pipeline; no end-to-end speedup or revised full-run ETA.",
|
||||
"Full independent AQ still uses a fresh subprocess and all original checks.",
|
||||
"The original stopped scientific run remains at 1033 CPU-verified epochs and 138 probes.",
|
||||
"Integrity covers saved Phase4AR files/sources and previous acceleration files; not a new Phase1-4AQ numerical regression.",
|
||||
"Expected timeout self-test intentionally exits nonzero; it is not a scientific-run failure."
|
||||
],
|
||||
"original_source_commit": "80aeb2093db655329774eff7b32fb6e417b8b40b",
|
||||
"probes_added": 0,
|
||||
"production_runtime_promoted": false,
|
||||
"registration_sha256": "b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740",
|
||||
"scientific_AR_resumed": false,
|
||||
"scientific_learning_success_claimed": false,
|
||||
"source_commit": "018f038c7857c7e0236dd7408a680458520d92ce",
|
||||
"status": "PASS-PERSISTENT-REPLAY-EQUIVALENCE",
|
||||
"training_epochs_added": 0
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"status": "PASS",
|
||||
"created_utc": "2026-10-01T07:46:35.326466+00:00",
|
||||
"files_checked": 64034,
|
||||
"bytes_checked": 3103901058,
|
||||
"inventory_sha256": "d7b675b0d0d4647d8fe2fcf9616b9a599e5bc3c15565e604e0d66a046afb835a",
|
||||
"registration_sha256": "b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740",
|
||||
"registered_science_commit": "80aeb2093db655329774eff7b32fb6e417b8b40b",
|
||||
"sources_checked": 16,
|
||||
"file_mismatches": [],
|
||||
"source_mismatches": [],
|
||||
"original_git_head": "09187e4d4d67badf1b418c5f211258ca5d8fb328",
|
||||
"original_git_status": "",
|
||||
"wall_seconds": 5.024687475000064,
|
||||
"scope": "Saved Phase4AR experiment/control files and registered source files; NOT a new Phase1-4AQ numerical regression",
|
||||
"training_epochs_cpu_verified_unchanged": 1033,
|
||||
"probes_completed_unchanged": 138,
|
||||
"original_experiment_resumed": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fresh_E_seconds": 4.8041809019996435,
|
||||
"fresh_V_seconds": 4.153049107000697,
|
||||
"label": "M",
|
||||
"original_fresh_validator_actual_exit": 0,
|
||||
"position": 0,
|
||||
"resident_E_seconds": 4.331270731003315,
|
||||
"resident_V_seconds": 3.5904566640019766,
|
||||
"update_comparison": {
|
||||
"all_four_files_SHA_identical": true,
|
||||
"arrays_bitwise_identical": true,
|
||||
"full_update_receipt_and_trace_digests_identical": true
|
||||
},
|
||||
"validator_comparison": {
|
||||
"all_scientific_fields_identical": true,
|
||||
"explicit_differing_fields": [
|
||||
"schema",
|
||||
"validator_source",
|
||||
"original_validator_source",
|
||||
"resident_prototype",
|
||||
"resident_cache_scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fresh_E_seconds": 4.551296638994245,
|
||||
"fresh_V_seconds": 3.902626559000055,
|
||||
"label": "N",
|
||||
"original_fresh_validator_actual_exit": 0,
|
||||
"position": 1,
|
||||
"resident_E_seconds": 2.678891448005743,
|
||||
"resident_V_seconds": 2.062450468001771,
|
||||
"update_comparison": {
|
||||
"all_four_files_SHA_identical": true,
|
||||
"arrays_bitwise_identical": true,
|
||||
"full_update_receipt_and_trace_digests_identical": true
|
||||
},
|
||||
"validator_comparison": {
|
||||
"all_scientific_fields_identical": true,
|
||||
"explicit_differing_fields": [
|
||||
"schema",
|
||||
"validator_source",
|
||||
"original_validator_source",
|
||||
"resident_prototype",
|
||||
"resident_cache_scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fresh_E_seconds": 4.735514142004831,
|
||||
"fresh_V_seconds": 4.103694833996997,
|
||||
"label": "M",
|
||||
"original_fresh_validator_actual_exit": 0,
|
||||
"position": 2,
|
||||
"resident_E_seconds": 2.857203049999953,
|
||||
"resident_V_seconds": 2.14666489699448,
|
||||
"update_comparison": {
|
||||
"all_four_files_SHA_identical": true,
|
||||
"arrays_bitwise_identical": true,
|
||||
"full_update_receipt_and_trace_digests_identical": true
|
||||
},
|
||||
"validator_comparison": {
|
||||
"all_scientific_fields_identical": true,
|
||||
"explicit_differing_fields": [
|
||||
"schema",
|
||||
"validator_source",
|
||||
"original_validator_source",
|
||||
"resident_prototype",
|
||||
"resident_cache_scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fresh_E_seconds": 4.5949991710003815,
|
||||
"fresh_V_seconds": 3.924993649998214,
|
||||
"label": "N_D0",
|
||||
"original_fresh_validator_actual_exit": 0,
|
||||
"position": 3,
|
||||
"resident_E_seconds": 2.6922046239997144,
|
||||
"resident_V_seconds": 1.9751014260036754,
|
||||
"update_comparison": {
|
||||
"all_four_files_SHA_identical": true,
|
||||
"arrays_bitwise_identical": true,
|
||||
"full_update_receipt_and_trace_digests_identical": true
|
||||
},
|
||||
"validator_comparison": {
|
||||
"all_scientific_fields_identical": true,
|
||||
"explicit_differing_fields": [
|
||||
"schema",
|
||||
"validator_source",
|
||||
"original_validator_source",
|
||||
"resident_prototype",
|
||||
"resident_cache_scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fresh_E_seconds": 4.620397169004718,
|
||||
"fresh_V_seconds": 3.9045120619994123,
|
||||
"label": "N_frozen",
|
||||
"original_fresh_validator_actual_exit": 0,
|
||||
"position": 4,
|
||||
"resident_E_seconds": 2.7464958280033898,
|
||||
"resident_V_seconds": 2.027457176001917,
|
||||
"update_comparison": {
|
||||
"all_four_files_SHA_identical": true,
|
||||
"arrays_bitwise_identical": true,
|
||||
"full_update_receipt_and_trace_digests_identical": true
|
||||
},
|
||||
"validator_comparison": {
|
||||
"all_scientific_fields_identical": true,
|
||||
"explicit_differing_fields": [
|
||||
"schema",
|
||||
"validator_source",
|
||||
"original_validator_source",
|
||||
"resident_prototype",
|
||||
"resident_cache_scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fresh_E_seconds": 4.764637047999713,
|
||||
"fresh_V_seconds": 4.06785895700159,
|
||||
"label": "M_D0",
|
||||
"original_fresh_validator_actual_exit": 0,
|
||||
"position": 5,
|
||||
"resident_E_seconds": 2.7973176640007296,
|
||||
"resident_V_seconds": 2.0859955760024604,
|
||||
"update_comparison": {
|
||||
"all_four_files_SHA_identical": true,
|
||||
"arrays_bitwise_identical": true,
|
||||
"full_update_receipt_and_trace_digests_identical": true
|
||||
},
|
||||
"validator_comparison": {
|
||||
"all_scientific_fields_identical": true,
|
||||
"explicit_differing_fields": [
|
||||
"schema",
|
||||
"validator_source",
|
||||
"original_validator_source",
|
||||
"resident_prototype",
|
||||
"resident_cache_scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fresh_E_seconds": 4.7666301089993794,
|
||||
"fresh_V_seconds": 4.0638777050044155,
|
||||
"label": "M",
|
||||
"original_fresh_validator_actual_exit": 0,
|
||||
"position": 6,
|
||||
"resident_E_seconds": 2.8035546359969885,
|
||||
"resident_V_seconds": 2.0804165529989405,
|
||||
"update_comparison": {
|
||||
"all_four_files_SHA_identical": true,
|
||||
"arrays_bitwise_identical": true,
|
||||
"full_update_receipt_and_trace_digests_identical": true
|
||||
},
|
||||
"validator_comparison": {
|
||||
"all_scientific_fields_identical": true,
|
||||
"explicit_differing_fields": [
|
||||
"schema",
|
||||
"validator_source",
|
||||
"original_validator_source",
|
||||
"resident_prototype",
|
||||
"resident_cache_scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user