From 3f21415bd54bfc7028c3d92f047cac876bc95a91 Mon Sep 17 00:00:00 2001 From: josie Date: Wed, 14 Oct 2026 01:03:52 -0400 Subject: [PATCH] Check exact phase fast paths on the frontier1042 phases steps Opt-in package research/frontier1042-phase-fastpath: the merged sparse compiler (PR1029) reproduces the three pinned k8 clifford_recipes_sha256 digests byte for byte from the archived canonical words; same-host timings for pinned serial, dense, sparse and parallel engines. No pinned file changes; no new kappa. Co-Authored-By: Claude Opus 5.5 --- .../BENCHMARK-macos-arm64.json | 123 ++++++++++++++ .../frontier1042-phase-fastpath/README.md | 154 ++++++++++++++++++ .../frontier1042-phase-fastpath/SOURCES.json | 84 ++++++++++ .../frontier1042-phase-fastpath/TASK.json | 67 ++++++++ .../frontier1042-phase-fastpath/VERIFY.json | 30 ++++ research/frontier1042-phase-fastpath/bench.py | 71 ++++++++ .../frontier1042-phase-fastpath/verify.py | 151 +++++++++++++++++ 7 files changed, 680 insertions(+) create mode 100644 research/frontier1042-phase-fastpath/BENCHMARK-macos-arm64.json create mode 100644 research/frontier1042-phase-fastpath/README.md create mode 100644 research/frontier1042-phase-fastpath/SOURCES.json create mode 100644 research/frontier1042-phase-fastpath/TASK.json create mode 100644 research/frontier1042-phase-fastpath/VERIFY.json create mode 100644 research/frontier1042-phase-fastpath/bench.py create mode 100644 research/frontier1042-phase-fastpath/verify.py diff --git a/research/frontier1042-phase-fastpath/BENCHMARK-macos-arm64.json b/research/frontier1042-phase-fastpath/BENCHMARK-macos-arm64.json new file mode 100644 index 0000000000..4e901fa21c --- /dev/null +++ b/research/frontier1042-phase-fastpath/BENCHMARK-macos-arm64.json @@ -0,0 +1,123 @@ +{ + "python": "3.14.7", + "platform": "macOS-26.6.2-arm64-arm-64bit-Mach-O", + "machine": "arm64", + "cpu_count": 10, + "jobs": 10, + "archive": "research/community-frontier1042-audit/selected-replay.tar.gz", + "note": "Shared host (another research session running), not isolated; descriptive timings only. Wall and child CPU seconds per complete command, including source admission and output writing.", + "results": [ + { + "engine": "sparse", + "stage": "cells", + "exit_code": 0, + "wall_seconds": 7.92, + "cpu_seconds": 7.09, + "recipe_sha256": "aab63b0a825fdf0ca504038a78b7371310eaef2748fbf80af74f7e4e47abce76", + "equals_pin": true + }, + { + "engine": "sparse", + "stage": "chain", + "exit_code": 0, + "wall_seconds": 7.85, + "cpu_seconds": 6.83, + "recipe_sha256": "e3bfdfa2c044f14c00a8706950c8ae838ceeedd9ca78a83bffefe7886219516a", + "equals_pin": true + }, + { + "engine": "sparse", + "stage": "slots", + "exit_code": 0, + "wall_seconds": 4.97, + "cpu_seconds": 4.92, + "recipe_sha256": "d0768f2164d5f64a2fdbec422f1cfde4e400818792f1904ca541958377243731", + "equals_pin": true + }, + { + "engine": "dense", + "stage": "cells", + "exit_code": 0, + "wall_seconds": 11.72, + "cpu_seconds": 11.67, + "recipe_sha256": "aab63b0a825fdf0ca504038a78b7371310eaef2748fbf80af74f7e4e47abce76", + "equals_pin": true + }, + { + "engine": "dense", + "stage": "chain", + "exit_code": 0, + "wall_seconds": 14.24, + "cpu_seconds": 13.61, + "recipe_sha256": "e3bfdfa2c044f14c00a8706950c8ae838ceeedd9ca78a83bffefe7886219516a", + "equals_pin": true + }, + { + "engine": "dense", + "stage": "slots", + "exit_code": 0, + "wall_seconds": 13.83, + "cpu_seconds": 13.38, + "recipe_sha256": "d0768f2164d5f64a2fdbec422f1cfde4e400818792f1904ca541958377243731", + "equals_pin": true + }, + { + "engine": "par-dense662", + "stage": "cells", + "exit_code": 0, + "wall_seconds": 2.79, + "cpu_seconds": 23.34, + "recipe_sha256": "aab63b0a825fdf0ca504038a78b7371310eaef2748fbf80af74f7e4e47abce76", + "equals_pin": true + }, + { + "engine": "par-dense662", + "stage": "chain", + "exit_code": 0, + "wall_seconds": 2.9, + "cpu_seconds": 22.88, + "recipe_sha256": "e3bfdfa2c044f14c00a8706950c8ae838ceeedd9ca78a83bffefe7886219516a", + "equals_pin": true + }, + { + "engine": "par-dense662", + "stage": "slots", + "exit_code": 0, + "wall_seconds": 3.1, + "cpu_seconds": 23.46, + "recipe_sha256": "d0768f2164d5f64a2fdbec422f1cfde4e400818792f1904ca541958377243731", + "equals_pin": true + }, + { + "engine": "pinned", + "stage": "cells", + "exit_code": 0, + "wall_seconds": 80.28, + "cpu_seconds": 79.98, + "recipe_sha256": "aab63b0a825fdf0ca504038a78b7371310eaef2748fbf80af74f7e4e47abce76", + "equals_pin": true + }, + { + "engine": "pinned", + "stage": "chain", + "exit_code": 0, + "wall_seconds": 82.38, + "cpu_seconds": 82.19, + "recipe_sha256": "e3bfdfa2c044f14c00a8706950c8ae838ceeedd9ca78a83bffefe7886219516a", + "equals_pin": true + }, + { + "engine": "pinned", + "stage": "slots", + "exit_code": 0, + "wall_seconds": 88.15, + "cpu_seconds": 87.54, + "recipe_sha256": "d0768f2164d5f64a2fdbec422f1cfde4e400818792f1904ca541958377243731", + "equals_pin": true + } + ], + "host_load_average_1min": { + "before": 28.88, + "after": 10.38 + } +} diff --git a/research/frontier1042-phase-fastpath/README.md b/research/frontier1042-phase-fastpath/README.md new file mode 100644 index 0000000000..45c91cecb1 --- /dev/null +++ b/research/frontier1042-phase-fastpath/README.md @@ -0,0 +1,154 @@ +# Exact sparse phase compilation on the selected frontier1042 `phases` steps + +**Status: verification engineering, opt-in, not wired. No new κ. No pinned file changes and no +check is weakened.** + +## What this measures + +A cold `make frontier1094-verify` runs `scripts/verify_frontier1042.py` as its `baseline1042-cold` +stage. That replay calls the pinned serial `phases_full.py` three times, once in each of the cells, +chain and slots stages. In the maintainer's recorded run +(`research/community-frontier1042-audit/selected-replay.tar.gz`) those three steps took 199.4 s, +134.4 s and 135.3 s: **469 s of the 1162 s run**. PR1151 parallelised the run's five layer-end-control +steps and explicitly left these three unmeasured. + +Two merged tools already compile exact phase recipes faster: Ali Romman's sparse evaluator (PR1029, +`research/selected-replay-fastpath/`) and thakrarsagar's process-parallel runner (PR1041, +`research/phase-recipes-parallel/`). Both were measured only on the PR942 U8 word. This package +checks them on the three k8 words of the selected chain. + +## Result + +For each stage, the archived `local/CANONICAL-WORD.json.gz` has the decompressed SHA256 that the k8 +pins file records as `canonical_sha256`. Compiling it gives output that matches the pinned serial +step, as follows: + +- **Recipes.** The sparse compiler (`run.py --engine sparse`) writes a `CLIFFORD-RECIPES.json` that is + **byte-identical** to the archived maintainer recipes. Its digest is the pinned + `clifford_recipes_sha256`. +- **Review.** `CLIFFORD-REVIEW.json` has the same keys as the archived review, and the same values + except elapsed seconds. + +| Stage | Pins file | `clifford_recipes_sha256` | Frames | Edges | Adapters | +|---|---|---|---:|---:|---:| +| cells | `gauge44-leaver8/.../LEAVER-PINS-k8.json` | `aab63b0a…` | 1036 | 2958 | 224 | +| chain | `gauge44-leaver8/.../CHAIN-PINS-k8.json` | `e3bfdfa2…` | 1004 | 2896 | 224 | +| slots | `gauge44-slots/.../SLOT-PINS-k8.json` | `d0768f21…` | 1004 | 2896 | 224 | + +Same-machine wall times are below. The machine is macOS arm64 with 10 cores, running Python 3.14.7. +The host was shared with another research job, so treat these numbers as descriptive. The raw +receipt is [`BENCHMARK-macos-arm64.json`](BENCHMARK-macos-arm64.json). + +| Command | cells | chain | slots | Total wall (CPU) | +|---|---:|---:|---:|---:| +| maintainer recording, pinned serial (other host) | 199.4 | 134.4 | 135.3 | 469.1 | +| pinned serial `phases_full.py` via `run_portable.py` | 80.3 | 82.4 | 88.2 | 250.8 (250) | +| `run.py --engine dense` (PR662) | 11.7 | 14.2 | 13.8 | 39.8 (39) | +| `run.py --engine sparse` (PR1029) | 7.9 | 7.8 | 5.0 | 20.7 (19) | +| `phases_parallel.py --jobs 10 --engine dense662` (PR1041) | 2.8 | 2.9 | 3.1 | 8.8 (70) | + +All times are in seconds. On this host the sparse compiler is 12× faster than the pinned serial step in wall time, and uses one core. The parallel dense runner is 29× faster but uses about 10 cores. + +An earlier scratch run on a less loaded host gave 4.1–4.4 s per word for the sparse compiler and 11 s for the dense one. + +Every run in the table produced the pinned bytes. + +## Controls + +`verify.py` runs two controls on a corrupted cells word. Neither may reproduce the pin. + +- **C1.** One one-dimensional frame `` is changed to a different line. `run.py` must reject it + with an `AssertionError` and write no recipes. +- **C2.** One directed edge is redirected to a frame of a different dimension. It must compile, but + to different recipes. + +Both expected behaviours are asserted exactly, so a change in how the compiler treats either +corruption shows up as a failure. + +A bit flip inside a full-rank frame leaves the span unchanged. Its canonical frame and recipes are +then identical, so it is not a corruption. An earlier draft control did exactly that and was replaced. + +PR1029's own package covers the remaining controls: + +- the four corrupted-word classes; +- source-pin refusal; +- optimized Python; +- output reuse; +- the gate-level tests and `PROOF.md`. + +This package does not repeat them. + +## Wiring (left to the maintainers) + +The three steps feed later stages: + +- `verify_slots.py` asserts both the chain and the slots recipe digests. +- `verify_t16.py` copies `CLIFFORD-RECIPES.json` and `CLIFFORD-REVIEW.json` forward and binds their + content. +- T16's `bind_providers_portable.py` asserts the review's `status`, `canonical_word_sha256`, + `recipe_sha256`, global-phase flag and `endpoint_adapters == 224`. + +`run.py` writes a review that `verify.py` checks equal on all those fields, so the files are drop-in. +The pinned scripts do not accept a substitute today: + +- **cells.** `reproduce_leaver.py --skip-phases` works. Its pins are checked key by key, and the + switch skips the recipe-pin check, so a wrapper must run + `research/selected-replay-fastpath/run.py --word local/CANONICAL-WORD.json.gz` into `local/` and + assert `clifford_recipes_sha256` itself. +- **chain.** `reproduce_leaver_chain.py --skip-phases` would **fail**. It ends with + `assert got == pins` over the whole CHAIN-PINS dictionary, and the recipe key would be missing. +- **slots.** `verify_slots.py` has no switch. + +The chain and slots steps, and `verify_frontier1042.py` itself, therefore need changes to +manifest-pinned scripts. That is a maintainer decision. The serial path stays the reference. + +## Reproduce + +```sh +python3 -B research/frontier1042-phase-fastpath/verify.py # ~20 s, sparse +python3 -B research/frontier1042-phase-fastpath/verify.py --engine dense # ~45 s +python3 scripts/research_package.py --package research/frontier1042-phase-fastpath --check-only +``` + +The expected last line is `PASS_FRONTIER1042_PHASE_FASTPATH`. The verifier is standard-library +only and reads nothing but committed files. The benchmark harness that produced the receipt is +[`bench.py`](bench.py); it takes `python3 -B research/frontier1042-phase-fastpath/bench.py OUT_DIR +ENGINES` and runs the pinned serial step through the pinned `run_portable.py`, as the replay does. + +## Limits + +- This package checks recipes compiled from the **archived** canonical words. A cold replay that + rebuilds those words is checked by the existing pins: equal canonical digests imply equal input + to the lowering. +- It does not establish anything about the scalar-interface integration or the global emitted + program. Those obligations are unchanged, as `run.py`'s own review states. + +## Open next questions + +These are structured in [TASK.json](TASK.json). + +1. **Should the cold frontier1042 replay call the sparse compiler for its three phases steps?** On + Scaling the measured ratio to the recorded machine, it would save about 430 s, about 37% of the + run; with PR1151 the run would drop to roughly 300 s. First step: an engine option on the three + phases calls that keeps every pin assertion. Blocker: maintainer decision, since the scripts are + pinned, chain `--skip-phases` fails its whole-dictionary pin check, and `verify_slots.py` has no + switch. +2. **Do other cold replays spend comparable time in the 23 byte-identical `phases_full.py` copies?** + First step: scan archived `STEPS.json` receipts for `phases` steps over 30 s and rerun this + pattern. Blocker: some archives may not keep the canonical word. + +## Credit + +- Ali Romman (PR1029): the sparse evaluator. +- thakrarsagar (PR1041): the parallel runner. +- Charles Bethin (PR662): the exact gate tables and the dense evaluator. +- icekylinx: `phases_full.py`, adapted from PR425 (jacklightChen's mutable-basis interface). +- PR558 (eumemic) and its PR552 lineage: `clifford_exact.py`. +- Jeremy Kothe: the construction, with Rohan Arun's slot search and Hao Yan's T16 controller. +- LeaverSAT and LeaverSAT2: the k8 cells and chain recipes. +- Douglas Colkitt: the maintainer replay and its archive. +- PR1151: identifying this gap. + +Prepared by Josie Elliston with Claude Code (Claude Opus); no subagents. A Codex read-only review +corrected the wiring section, tightened the controls and the credit. That is separate AI review, +not independent human review. Apache-2.0. diff --git a/research/frontier1042-phase-fastpath/SOURCES.json b/research/frontier1042-phase-fastpath/SOURCES.json new file mode 100644 index 0000000000..d059d470b0 --- /dev/null +++ b/research/frontier1042-phase-fastpath/SOURCES.json @@ -0,0 +1,84 @@ +{ + "schema_version": 1, + "base_commit": "858771bcca3b8dd5d4ef4aa682a13cc9b7e23920", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "ae6a99f28aa468649eb66a361e764d769363bf11", + "sha256": "10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "06c96f5579bb67ed1b86d334e78fbed7da6945f1", + "sha256": "6686ad58f1fbdbc87134a78901b60fd53a20d3984355e91defbbebc9e9fa8075" + }, + { + "path": "research/clifford-state-performance/fast_state.py", + "usage": "input", + "git_blob": "5d546d8a05f6025d58a5133fa0d67ce134993013", + "sha256": "2fe087ba4558bd21ca49945dbedaa4047e4170e8fd4e2280701bb2f0481811b5" + }, + { + "path": "research/community-frontier1042-audit/selected-replay.tar.gz", + "usage": "input", + "git_blob": "6f4dc6fe7631d8aacf8081fcaecf32197181685b", + "sha256": "22c3f4dce4b897a1d423d1388801933e288b6a6b1906cb15e1b16a5eb68db754" + }, + { + "path": "research/complex-k492-owner-repair/vendor/multicold/vendor/pr558/vendor/pr552/complex-global/vendor531/vendor/clifford/clifford_exact.py", + "usage": "input", + "git_blob": "166841a037f069249f6f7f6dedb89248812f59e2", + "sha256": "2982ead07721e83358dc67c6f49c2b4c16a236a6bebdfd72f58221be1f5d0962" + }, + { + "path": "research/gauge44-leaver8/construction/leaver/CHAIN-PINS-k8.json", + "usage": "input", + "git_blob": "afd0467911a2994c1d1df7bff61d9bed2ddfca36", + "sha256": "9dfcecf963d8fa6d1cf5ba212336437a51f03c1444a1c6d33e54d2bf762970a9" + }, + { + "path": "research/gauge44-leaver8/construction/leaver/LEAVER-PINS-k8.json", + "usage": "input", + "git_blob": "b22678629c226d523b37d0157f941ba616b32164", + "sha256": "ab6ce39246d102f55d63c819c4cded2450c515b0e99afe5023f726054afc73f6" + }, + { + "path": "research/gauge44-slots/construction/slots/SLOT-PINS-k8.json", + "usage": "input", + "git_blob": "2702c368f4de0b671577aee9a0e2df41c1b27658", + "sha256": "55dd229684febecb80638eff9c6b3986623e8539c6c956753b350209c3e0efe2" + }, + { + "path": "research/selected-replay-fastpath/SOURCES.json", + "usage": "input", + "git_blob": "d0f8d1929de4a76410df18536407cccfa5550fd7", + "sha256": "2c6f7e8adbe8a894963ef18b8344df561fb210c99395e211a1e2752add2470b7" + }, + { + "path": "research/selected-replay-fastpath/lowering.py", + "usage": "input", + "git_blob": "75232da3800f97562e933d6cfb81553e5555854a", + "sha256": "ba42903b841722b872f98f3afa77d47976ca66a0cb4c0dd6b8de04462d4baa2b" + }, + { + "path": "research/selected-replay-fastpath/run.py", + "usage": "input", + "git_blob": "becb4cf8f7724e4fb8c26191aef80d425220526e", + "sha256": "e81ec5ff96b45621b80f93767619edbc6174c3726502a2acf34e2467481a6aed" + }, + { + "path": "research/selected-replay-fastpath/sources.py", + "usage": "input", + "git_blob": "516877d2e6241ade366a0bbaf367f10b00c4ba72", + "sha256": "e559cb55389798f8e5c00c6bf83e0c867334a21df08580cb368e63bf8d8d9ff7" + }, + { + "path": "research/selected-replay-fastpath/sparse_state.py", + "usage": "input", + "git_blob": "ca39f73494e11bf0a860c51b8d711bec48ec0842", + "sha256": "e91210ecd5085cf9add872f40bb434806838da488e12152c63c86e51fb5a7a37" + } + ] +} diff --git a/research/frontier1042-phase-fastpath/TASK.json b/research/frontier1042-phase-fastpath/TASK.json new file mode 100644 index 0000000000..c28a746689 --- /dev/null +++ b/research/frontier1042-phase-fastpath/TASK.json @@ -0,0 +1,67 @@ +{ + "schema_version": 1, + "task_id": "replay-runtime", + "priority_revision": 3, + "base_commit": "858771bcca3b8dd5d4ef4aa682a13cc9b7e23920", + "original_card": { + "id": "replay-runtime", + "question": "Can one measured replay bottleneck be sped up without dropping coverage?", + "starting_points": [ + "scripts/run_isolated_tests.py", + "scripts/verify_replay_coverage.py", + "certificates/selected-result.json" + ], + "methods": [ + "Profile one isolated replay and optimize the measured bottleneck.", + "Design source-bound reuse with explicit dependency invalidation and negative controls." + ], + "acceptance_gate": "Report before/after wall time on the same fixture, retained checks and invalidation behavior.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read the selected reproduction command and choose a single replay stage for profiling.", + "scope": "Positive control / source-bound orientation only; this is not a new construction or full cold replay." + }, + "first_experiment": "Measure one unchanged fixture, preserve check coverage, and test one optimization with invalidation controls.", + "bottleneck_link": "Faster trustworthy replays increase review throughput and let mechanism candidates be checked sooner.", + "allowed_variations": [ + "Profile one stage or design one source-bound cache boundary." + ], + "scope_change_triggers": [ + "Skipping coverage or comparing different fixtures to claim speedup." + ], + "overlap_terms": [ + "replay runtime", + "cache invalidation", + "isolated tests" + ] + }, + "scope_status": "refined", + "actual_scope": "The three `phases` steps (cells, chain, slots) of the cold frontier1042 replay that `make frontier1094-verify` runs as `baseline1042-cold`: does the merged exact sparse phase compiler (research/selected-replay-fastpath, previously measured only on the PR942 U8 word) reproduce their pinned CLIFFORD-RECIPES bytes from the archived canonical words, and how much faster is it than the pinned serial phases_full.py on the same machine?", + "scope_change_reason": "The card asks for one measured replay bottleneck. The phases steps are 469 s of the recorded 1162 s frontier1042 run; PR1151 sped up the layer-end controls and explicitly left these steps unmeasured. This is the card's allowed variation (one stage), applied to existing merged tools rather than a new evaluator.", + "bottleneck_link": "Side result for review throughput: a cold selected replay is the acceptance test for any new complex supplier built on the k8 chain; shortening it lets candidates be checked sooner. No mathematical claim.", + "budget_minutes": 60, + "stop_rule": "Stop after byte-identity on all three pinned digests, a same-machine timing against the pinned serial step, and two corruption controls; do not edit or wire any manifest-pinned replay script.", + "outcome": "completed", + "evidence": "verify.py: all three recipe files byte-identical to the k8 pins and the archived maintainer recipes, review fields (including the status, digests and adapter count the T16 binder asserts) equal; two corrupted words do not reproduce the pin. BENCHMARK-macos-arm64.json: same-machine wall times for pinned serial phases_full.py, the dense PR662 evaluator, the sparse evaluator and phases_parallel.py.", + "author": "Josie Elliston (Claude Code research session)", + "ai_assistance": "Prepared with Claude Code (Claude Opus); a Codex read-only review corrected the wiring notes, controls and credit. No subagents.", + "open_questions": [ + { + "question": "Should the cold frontier1042 replay call the sparse compiler for its three phases steps?", + "why_it_matters": "The three steps are 469 s of the recorded 1162 s cold frontier1042 run; scaling the measured 12x sparse ratio, the run would lose about 430 s, and with PR1151 fall to roughly 300 s on the recorded machine.", + "first_step": "Give the three phases calls (reproduce_leaver.py, reproduce_leaver_chain.py, verify_slots.py) an engine option that runs research/selected-replay-fastpath/run.py into local/ and keeps every clifford_recipes_sha256 pin assertion.", + "blocked_by": "Maintainer decision: the scripts are manifest-pinned; reproduce_leaver_chain.py --skip-phases fails its whole-dictionary CHAIN-PINS check; verify_slots.py has no switch. Only the cells step can use --skip-phases plus an external pin check unchanged." + }, + { + "question": "Is the phase lowering still a bottleneck in other cold replays that call phases_full.py (23 byte-identical copies on main)?", + "why_it_matters": "Every chain rebuild for a pending k8-based claim reruns the same lowering.", + "first_step": "Grep STAGES/STEPS receipts in research/*-audit archives for phases steps over 30 s and run this verifier pattern on their archived canonical words.", + "blocked_by": "Some archives may not retain the canonical word." + } + ] +} diff --git a/research/frontier1042-phase-fastpath/VERIFY.json b/research/frontier1042-phase-fastpath/VERIFY.json new file mode 100644 index 0000000000..32e6c9c9f4 --- /dev/null +++ b/research/frontier1042-phase-fastpath/VERIFY.json @@ -0,0 +1,30 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/clifford-state-performance/fast_state.py", + "research/community-frontier1042-audit/selected-replay.tar.gz", + "research/complex-k492-owner-repair/vendor/multicold/vendor/pr558/vendor/pr552/complex-global/vendor531/vendor/clifford/clifford_exact.py", + "research/gauge44-leaver8/construction/leaver/CHAIN-PINS-k8.json", + "research/gauge44-leaver8/construction/leaver/LEAVER-PINS-k8.json", + "research/gauge44-slots/construction/slots/SLOT-PINS-k8.json", + "research/selected-replay-fastpath/SOURCES.json", + "research/selected-replay-fastpath/lowering.py", + "research/selected-replay-fastpath/run.py", + "research/selected-replay-fastpath/sources.py", + "research/selected-replay-fastpath/sparse_state.py" + ], + "commands": [ + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 180, + "checks": "Identity: three archived canonical words match the k8 canonical_sha256 pins; positive fixture: sparse recipes byte-identical to the pinned and archived CLIFFORD-RECIPES for cells, chain and slots; failure controls: a changed one-dimensional frame and a redirected edge must not reproduce the pin." + } + ] +} diff --git a/research/frontier1042-phase-fastpath/bench.py b/research/frontier1042-phase-fastpath/bench.py new file mode 100644 index 0000000000..7786b6b815 --- /dev/null +++ b/research/frontier1042-phase-fastpath/bench.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Time phase-recipe engines on the three archived frontier1042 canonical words (descriptive only). + +Usage: bench.py OUT_DIR ENGINES, with OUT_DIR fresh and ENGINES a comma list of +sparse, dense, reference (selected-replay-fastpath/run.py), pinned (the pinned phases_full.py via the +pinned run_portable.py, as the replay runs it) and par-reference / par-dense662 +(phase-recipes-parallel/phases_parallel.py --jobs N). Every run must reproduce the pinned bytes. +""" +import hashlib, json, os, platform, resource, shutil, subprocess, sys, tarfile, time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +ARCHIVE = ROOT / 'research/community-frontier1042-audit/selected-replay.tar.gz' +PINS = dict(cells='research/gauge44-leaver8/construction/leaver/LEAVER-PINS-k8.json', + chain='research/gauge44-leaver8/construction/leaver/CHAIN-PINS-k8.json', + slots='research/gauge44-slots/construction/slots/SLOT-PINS-k8.json') +SRC = ROOT / 'research/complex-k492-owner-repair/vendor/multicold' +P = SRC / 'vendor/pr558' +CLIF = P / 'vendor/pr552/complex-global/vendor531/vendor/clifford' + + +def main(): + out, engines = Path(sys.argv[1]).resolve(), sys.argv[2].split(',') + jobs = sys.argv[3] if len(sys.argv) > 3 else str(os.cpu_count() or 1) + assert not out.exists() and not sys.flags.optimize + env = dict(os.environ, PYTHONDONTWRITEBYTECODE='1', PYTHONUTF8='1', PYTHONINTMAXSTRDIGITS='0', + MULTICOLD_SOURCE=str(SRC), GAIN_PR564_SOURCE=str(SRC)) + with tarfile.open(ARCHIVE) as tar: + words = {} + for st in PINS: + words[st] = out / 'words' / st / 'CANONICAL-WORD.json.gz' + words[st].parent.mkdir(parents=True) + words[st].write_bytes(tar.extractfile(st + '/local/CANONICAL-WORD.json.gz').read()) + res = [] + for eng in engines: + for st, word in words.items(): + pin = json.loads((ROOT / PINS[st]).read_text())['clifford_recipes_sha256'] + d = out / 'runs' / eng / st + if eng in ('sparse', 'dense', 'reference'): + cmd = [sys.executable, '-B', str(ROOT / 'research/selected-replay-fastpath/run.py'), + '--word', str(word), '--out', str(d), '--engine', eng] + else: + d.mkdir(parents=True) + shutil.copy(word, d / 'CANONICAL-WORD.json.gz') + if eng == 'pinned': + cmd = [sys.executable, '-B', str(SRC / 'code/run_portable.py'), str(P / 'code/phases_full.py'), + str(d), str(CLIF)] + else: + cmd = [sys.executable, '-B', str(ROOT / 'research/phase-recipes-parallel/phases_parallel.py'), + str(d), str(CLIF), '--jobs', jobs, '--engine', eng.split('-', 1)[1]] + ru = resource.getrusage(resource.RUSAGE_CHILDREN) + t = time.monotonic() + p = subprocess.run(cmd, env=env, capture_output=True, text=True) + dt = time.monotonic() - t + ru2 = resource.getrusage(resource.RUSAGE_CHILDREN) + cpu = ru2.ru_utime - ru.ru_utime + ru2.ru_stime - ru.ru_stime + rp = d / 'CLIFFORD-RECIPES.json' + got = hashlib.sha256(rp.read_bytes()).hexdigest() if rp.exists() else None + r = dict(engine=eng, stage=st, exit_code=p.returncode, wall_seconds=round(dt, 2), cpu_seconds=round(cpu, 2), + recipe_sha256=got, equals_pin=got == pin) + print(json.dumps(r), flush=True) + res.append(r) + assert p.returncode == 0 and got == pin, (eng, st, p.stderr[-500:]) + (out / 'BENCHMARK.json').write_text(json.dumps(dict( + python=sys.version.split()[0], platform=platform.platform(), machine=platform.machine(), + cpu_count=os.cpu_count(), jobs=int(jobs), archive=str(ARCHIVE.relative_to(ROOT)), + note='Shared host, not isolated; descriptive timings only.', results=res), indent=1) + '\n') + + +if __name__ == '__main__': + main() diff --git a/research/frontier1042-phase-fastpath/verify.py b/research/frontier1042-phase-fastpath/verify.py new file mode 100644 index 0000000000..771359f224 --- /dev/null +++ b/research/frontier1042-phase-fastpath/verify.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +"""Check the merged exact phase fast path on the three frontier1042 `phases` steps. + +The cold frontier1042 replay (the `baseline1042-cold` stage of `make frontier1094-verify`) runs the +pinned serial `phases_full.py` three times: in the cells, chain and slots stages. This verifier takes +the three canonical words from the maintainer's archived replay, checks them against the k8 pins, +compiles each with `research/selected-replay-fastpath/run.py` (unchanged; it checks its own source +pins), and requires the recipe bytes to equal both the pinned `clifford_recipes_sha256` and the +archived recipes. Two corrupted words must fail. Nothing is wired into the pinned replay. + +Josie Elliston with Claude Code. Apache-2.0. +""" +import argparse +import gzip +import hashlib +import json +from pathlib import Path +import subprocess +import sys +import tarfile +import tempfile +import time + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +ARCHIVE = ROOT / 'research/community-frontier1042-audit/selected-replay.tar.gz' +RUN = ROOT / 'research/selected-replay-fastpath/run.py' +PINS = { + 'cells': ROOT / 'research/gauge44-leaver8/construction/leaver/LEAVER-PINS-k8.json', + 'chain': ROOT / 'research/gauge44-leaver8/construction/leaver/CHAIN-PINS-k8.json', + 'slots': ROOT / 'research/gauge44-slots/construction/slots/SLOT-PINS-k8.json', +} +# Review fields that describe the computation (everything except scope prose and seconds). The T16 provider +# binder asserts status, both digests, the global-phase flag and the adapter count of this file. +REVIEW_FIELDS = ('status', 'canonical_word_sha256', 'frames', 'directed_edges', 'ranks', 'endpoint_adapters', + 'all_child_equalities_include_global_phase', 'recipe_sha256') + + +def sha(b): + return hashlib.sha256(b).hexdigest() + + +def require(ok, msg): + if not ok: + raise SystemExit('FAIL: ' + msg) + + +def member(tar, name): + f = tar.extractfile(name) + require(f is not None, 'missing archive member ' + name) + return f.read() + + +def compile_word(word, out, engine): + t = time.monotonic() + p = subprocess.run([sys.executable, '-B', str(RUN), '--word', str(word), '--out', str(out), + '--engine', engine], capture_output=True, text=True) + return p, time.monotonic() - t + + +def canonical_gz(obj): + return gzip.compress(json.dumps(obj, sort_keys=True, separators=(',', ':')).encode(), mtime=0) + + +def main(): + require(not sys.flags.optimize, 'assertions must stay enabled') + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument('--engine', choices=('sparse', 'dense', 'reference'), default='sparse', + help='evaluator inside run.py (reference = the retained original lowering, slow)') + ap.add_argument('--skip-controls', action='store_true') + a = ap.parse_args() + report = dict(engine=a.engine, python=sys.version.split()[0], archive_sha256=sha(ARCHIVE.read_bytes()), + stages={}, controls={}) + with tempfile.TemporaryDirectory(prefix='f1042-phases-') as tmp, tarfile.open(ARCHIVE) as tar: + tmp = Path(tmp) + words = {} + for stage, pin_file in PINS.items(): + pins = json.loads(pin_file.read_text()) + raw = member(tar, stage + '/local/CANONICAL-WORD.json.gz') + recipes = member(tar, stage + '/local/CLIFFORD-RECIPES.json') + review = json.loads(member(tar, stage + '/local/CLIFFORD-REVIEW.json')) + # The archived word is the one the pinned replay checked (payload pin), and the archived + # recipes are the ones the pinned serial phases_full.py wrote (recipe pin). + require(sha(gzip.decompress(raw)) == pins['canonical_sha256'], stage + ': canonical word pin') + require(sha(recipes) == pins['clifford_recipes_sha256'], stage + ': archived recipes pin') + require(review['recipe_sha256'] == pins['clifford_recipes_sha256'] and + review['canonical_word_sha256'] == sha(raw), stage + ': archived review binding') + word = tmp / stage / 'CANONICAL-WORD.json.gz' + word.parent.mkdir() + word.write_bytes(raw) + words[stage] = word + out = tmp / stage / 'out' + p, dt = compile_word(word, out, a.engine) + require(p.returncode == 0, stage + ': run.py failed\n' + p.stdout[-400:] + p.stderr[-800:]) + got = (out / 'CLIFFORD-RECIPES.json').read_bytes() + mine = json.loads((out / 'CLIFFORD-REVIEW.json').read_text()) + require(got == recipes, stage + ': recipe bytes differ from the archived pinned recipes') + require(sha(got) == pins['clifford_recipes_sha256'], stage + ': recipe pin') + for k in REVIEW_FIELDS: + require(mine[k] == review[k], stage + ': review field ' + k) + report['stages'][stage] = dict( + recipe_sha256=sha(got), canonical_sha256=pins['canonical_sha256'], + frames=mine['frames'], directed_edges=mine['directed_edges'], + endpoint_adapters=mine['endpoint_adapters'], wall_seconds=round(dt, 2), + archived_serial_seconds=round(review['seconds'], 2)) + print('PASS', stage, a.engine, 'byte-identical', '%.1fs' % dt, + '(archived serial %.1fs)' % review['seconds'], flush=True) + + if not a.skip_controls: + base = json.loads(gzip.decompress(words['cells'].read_bytes())) + # C1: a one-dimensional frame becomes a different line . (A bit flip inside a + # full-rank frame leaves its span, hence its canonical frame and recipes, unchanged, so it + # is not a corruption.) Either an assertion fires or the recipes change. + c1 = json.loads(json.dumps(base)) + i = next(i for i, U in enumerate(c1['frames']) if len(U) == 1) + u = c1['frames'][i][0] + c1['frames'][i][0] = u ^ (2 if u & 1 and u != 2 else 1) + require(c1['frames'][i][0] not in (0, u), 'C1 setup') + # C2: one directed edge is redirected to a frame of a different dimension. The per-edge + # rank assertion may or may not fire; either way the pinned recipes must not come back. + c2 = json.loads(json.dumps(base)) + a0, b0 = c2['edges'][0] + other = next(f for f in range(len(c2['frames'])) + if f not in (a0, b0) and len(c2['frames'][f]) != len(c2['frames'][b0])) + c2['edges'][0] = [a0, other] + pin = json.loads(PINS['cells'].read_text())['clifford_recipes_sha256'] + for name, obj in (('C1_frame_bit', c1), ('C2_edge_redirect', c2)): + w = tmp / name / 'CANONICAL-WORD.json.gz' + w.parent.mkdir() + w.write_bytes(canonical_gz(obj)) + p, _ = compile_word(w, tmp / name / 'out', a.engine) + rp = tmp / name / 'out' / 'CLIFFORD-RECIPES.json' + reproduced = p.returncode == 0 and rp.exists() and sha(rp.read_bytes()) == pin + require(not reproduced, name + ': corrupted word reproduced the pinned recipes') + # Pin the observed behaviour exactly, so a change in how the compiler treats either + # corruption is noticed rather than absorbed by "any failure counts". + if name == 'C1_frame_bit': + require(p.returncode != 0 and 'AssertionError' in p.stderr and not rp.exists(), + name + ': expected an assertion and no recipes') + outcome = 'rejected by AssertionError, no recipes written' + else: + require(p.returncode == 0 and rp.exists(), name + ': expected a compiled, different word') + outcome = 'compiled to different recipes ' + sha(rp.read_bytes())[:16] + report['controls'][name] = outcome + print('PASS control', name, '-', outcome, flush=True) + print(json.dumps(report, indent=1)) + print('PASS_FRONTIER1042_PHASE_FASTPATH') + + +if __name__ == '__main__': + main()