diff --git a/harness/STATE.md b/harness/STATE.md index 6aef787f..885b6e9a 100644 --- a/harness/STATE.md +++ b/harness/STATE.md @@ -115,6 +115,18 @@ failures and corrections. Earlier authoring and allocation checkpoints remain in ## Isolated contributions and material limitations +Combined peer candidate **f82e29d6b8ed2b5fd23ac806675d3eafe851d104**, published on +`codex/peer-union-956atf-20260923`, composes current Text/Tab with saved Scenario, +final inspector actions, attachments, State bends and the transition footer. +Strict Windows workspace/all-target lint passes on 760 unchanged inputs after +repairing an example constructor and restoring the exact peer compile-time +fixture. Earlier combined core checks pass 27 Scenario and 22 source-default +cases at source-identical crate revision015273a. The +[partial gate archive](experiments/peer-union-windows-20260923/README.md) retains +the original seven Scenario failures, both lint failures, source boundaries and +helper/clock capture limits. Full workspace, desktop/native, public format and +release acceptance are not established; accepted root production remains4ffff0d. + Analysis/core source checkpoint **a2a28f8d23a46ba1696b6a8410d4d3b5c1808f49**, publication branch `codex/analysis-core-956atf-20260911`, is not integrated into production. Its private staged typed parser/lowerer has142 listed tests, diff --git a/harness/experiments/peer-union-windows-20260923/.gitattributes b/harness/experiments/peer-union-windows-20260923/.gitattributes new file mode 100644 index 00000000..9224073d --- /dev/null +++ b/harness/experiments/peer-union-windows-20260923/.gitattributes @@ -0,0 +1,6 @@ +evidence.zip -text +manifest.json -text +verify.py -text +README.md -text +negative-controls-original.py -text +negative-controls-result.json -text whitespace=cr-at-eol diff --git a/harness/experiments/peer-union-windows-20260923/README.md b/harness/experiments/peer-union-windows-20260923/README.md new file mode 100644 index 00000000..f30f9253 --- /dev/null +++ b/harness/experiments/peer-union-windows-20260923/README.md @@ -0,0 +1,99 @@ +# Combined peer candidate — partial Windows verification + +This checkpoint records completed gates through strict workspace lint at source +`f82e29d6b8ed2b5fd23ac806675d3eafe851d104`, published and ref-verified on +`codex/peer-union-956atf-20260923`. It is not full workspace, desktop/native, +public source8 or release acceptance. The live integration task is Gitea issue27; +the source provenance and reviewed seams are in +`f82e29d:harness/peer-union-20260923.md`. + +## What ran + +Windows Rust/Cargo 1.98.1 gnullvm, LLVM-MinGW 20260908 UCRT, offline locked +dependencies, one compiler at a time. Each receipt records command, environment, +source HEAD before/after, input hashes, original log and test executable hashes. +The final strict gate uses `CARGO_BUILD_JOBS=1` and `CARGO_INCREMENTAL=0`. + +| Source | Gate | Observed result | Captured inputs | +| --- | --- | --- | --- | +| `0b61771` | Core inventory / Scenario layout | 129 listed; 20 pass / 7 fail | 742 | +| `2a0579d` | Core inventory / Scenario layout / source defaults | 129 listed; 27 / 22 pass | 742 | +| `2a0579d` | Default omission integration target | 11 listed / 11 pass | 742 | +| `015273a` | Combined core inventory / Scenario layout / source defaults | 129 listed; 27 / 22 pass | 758 | +| `015273a` | Strict workspace all-target Clippy | Failed: example Diagram constructor missing layout | 758 | +| `c489748` | Strict workspace all-target Clippy | Failed: missing attachment compile-time fixture | 758 | +| `f82e29d` | Strict workspace all-target Clippy | Exit 0, no diagnostics | 760 | + +These are 13 completed gate receipts. Passing scoped runs are matched to their +actual same-source, same-executable inventories, with exact selected membership +and outcomes. No historical counts are added into a combined total. The first +seven failures are all source-lifecycle cases: parser field admission omitted +`layout`. Fix `2a0579d` (combined cherry-pick `846cae8`) admits the field without +adding synthetic layout-null editor defaults. Original failing logs remain. + +The example fix `c4897485b7058570a563707c4f5840f500a6c265` adds only +`layout: None` to `examples/release1/model.rs`. The fixture restoration +`f82e29d6b8ed2b5fd23ac806675d3eafe851d104` imports exact peer `b8685416` bytes at +`harness/experiments/edge-attachments-20260922/native-fixture.arcadia` (Git blob +`f6419892143c9c08c22780de6060a7315be17930`). Neither changes crate implementation. +An include-file audit also identified the existing textual-authoring +`alarm-response.arcadia` fixture outside the previous manifest roots. The final +760-input scope explicitly includes both compile-time fixtures; historical +742/758-input receipts are not retrospectively expanded. + +## Reproduce the evidence audit + +Fetch the source commits named in `manifest.json`, then run from any directory: + +```powershell +python path/to/this/folder/verify.py --repo path/to/ARCADIA-Studio +``` + +The standard-library verifier reads the ZIP in memory without extraction or +executing archived code. It checks every payload hash, receipt/log/manifest +binding, frozen source, unchanged inputs, recorded command/exit, exact test +membership/outcomes (including the seven failures), helper hashes and 3,760 +distinct source-commit/input pairs against Git blobs. Executable bytes are not +distributed in this archive; their recorded identity binds each scoped run to +its listing but is not a substitute for rerunning the build. + +The positive audit passes. Four falsification trials reject a corrupt payload, +wrong outcome count, removed selected test outcome (with renewed wrapper hashes), +and forged source input hash (also with renewed wrappers). The original local +driver and hash-bound result are retained beside this report. The driver uses +the original workspace paths; it is a record of these trials, not a second +portable entrypoint. + +To repeat the final strict gate from the identified source with the documented +Windows toolchain and cached dependencies: + +```powershell +cargo clippy --locked --offline --workspace --all-targets -- -D warnings +``` + +Focused test commands, filters and tool environment are preserved verbatim in +the receipts. The archived launchers document capture behavior; they reference +the original local layout and are evidence rather than portable build setup. + +## Capture limits and pending acceptance + +- Earlier helper `596dd821...` was reconstructed by reversing the known scope + extension and package selection change; its exact hash matches the historical + receipts. Helper `ddb37f5c...` was copied after its last run. Neither is claimed + to be a launch-time copy. `launchers/capture-provenance.json` preserves this. + Later gates retain immutable hash-keyed helper bytes before launch. +- The final strict receipt's raw UTC span is 08:29:41–11:35:25, while Cargo reports + 5m42s. The clock discontinuity is retained; that span is not a duration claim. +- The input inventory is a declared source scope, not a complete compiler file + access trace. The discovered fixture omission and subsequent repair remain + explicit. All recorded included inputs match their identified Git blobs. +- Desktop discovery/execution, remaining integration targets, full workspace + tests, matching GUI build and a combined native save/reopen workflow remain + pending at this checkpoint. No running gate is included in the archive. +- Public format adoption and normative Scenario language/API/OpenAPI coverage + remain unresolved. The private analysis parser is a separate branch and is + not part of this combined candidate. Linux remains user-deferred. + +The source reviews retain their original pins and pre-execution dispositions. +Passing these gates does not retroactively make a source review a runtime or +native observation. Existing peer native evidence remains tied to its own source. diff --git a/harness/experiments/peer-union-windows-20260923/evidence.zip b/harness/experiments/peer-union-windows-20260923/evidence.zip new file mode 100644 index 00000000..9e6bc74e Binary files /dev/null and b/harness/experiments/peer-union-windows-20260923/evidence.zip differ diff --git a/harness/experiments/peer-union-windows-20260923/manifest.json b/harness/experiments/peer-union-windows-20260923/manifest.json new file mode 100644 index 00000000..1749fa95 --- /dev/null +++ b/harness/experiments/peer-union-windows-20260923/manifest.json @@ -0,0 +1,512 @@ +{ + "archive_bytes": 580378, + "archive_sha256": "4f4ef08a718296b7991908bfe7fd9ac02c0187eaeace0f2bdb77102d49eb9032", + "payloads": { + "gates/combined-core-defaults-1.admission.json": { + "bytes": 2386, + "sha256": "65bcad22c89ad57288d9dc350ecbfa8ee4eeb39cb9baa61255dc6cbac8872db5" + }, + "gates/combined-core-defaults-1.inputs.json": { + "bytes": 140816, + "sha256": "418819b2c6e3032839cb70a8f8f49c7e8a7175a63be7463198f5be01be151e7f" + }, + "gates/combined-core-defaults-1.log": { + "bytes": 2402, + "sha256": "ddd5f659e3dd728af38e317b5e893502cd43dc8e9520ce2be31ecf32f3243dd4" + }, + "gates/combined-core-defaults-1.result.json": { + "bytes": 1732, + "sha256": "47768d9f82ce95596dc7ebc2517ab7120dace3a97f8153b393f267e70dc1c160" + }, + "gates/combined-core-list-1.inputs.json": { + "bytes": 140816, + "sha256": "418819b2c6e3032839cb70a8f8f49c7e8a7175a63be7463198f5be01be151e7f" + }, + "gates/combined-core-list-1.log": { + "bytes": 13051, + "sha256": "fd260e2847b22d569569828874849019579a06c66cea1197d8210ff1b2920030" + }, + "gates/combined-core-list-1.result.json": { + "bytes": 14548, + "sha256": "a277ffe7c07c8897bb3d53d526e1d16d2b419f5d98037b8701d64b3d6f1cea6a" + }, + "gates/combined-core-scenario-1.admission.json": { + "bytes": 3369, + "sha256": "b9669acff9abd0f129059aada8737c4c8f4ccc1ad7c92a5df10caa8110059ca2" + }, + "gates/combined-core-scenario-1.inputs.json": { + "bytes": 140816, + "sha256": "418819b2c6e3032839cb70a8f8f49c7e8a7175a63be7463198f5be01be151e7f" + }, + "gates/combined-core-scenario-1.log": { + "bytes": 3405, + "sha256": "1204984d0c27cfb2d4ebd950dd22a44b7d07e8244a486e034ae270050d86f640" + }, + "gates/combined-core-scenario-1.result.json": { + "bytes": 1732, + "sha256": "bfe54a0f93444247a87ecdd0ffab722dec423daeb7f3e23bff9b4e92d00974ec" + }, + "gates/combined-strict-1.inputs.json": { + "bytes": 140816, + "sha256": "418819b2c6e3032839cb70a8f8f49c7e8a7175a63be7463198f5be01be151e7f" + }, + "gates/combined-strict-1.log": { + "bytes": 1083, + "sha256": "5e02d1cb074aad07aef432ec3c03628557152d4a9fb2b8dfb345515e0bdb75ee" + }, + "gates/combined-strict-1.result.json": { + "bytes": 1463, + "sha256": "a76b065c39e89a88f23066d5a612c44561f36b648297058e53ef8319e0ccadaf" + }, + "gates/combined-strict-2.inputs.json": { + "bytes": 140816, + "sha256": "2fde588400f967f7c5cef510cc38261fd1e5f46cba6e14915be83c9efe3a9654" + }, + "gates/combined-strict-2.log": { + "bytes": 633, + "sha256": "c14924f72d19daa9cc50b1a73049bba93220354ab89da6c395071e7bc588adbf" + }, + "gates/combined-strict-2.result.json": { + "bytes": 1652, + "sha256": "2fa1e8323385f45a796a1e07519b19980448e4cda065d0e92c0bfb795ca464ef" + }, + "gates/combined-strict-3.inputs.json": { + "bytes": 141223, + "sha256": "91d917e0c329f74223eef11f02b25ecbd2b69ce7cc6482eede0a65548fd95255" + }, + "gates/combined-strict-3.log": { + "bytes": 265, + "sha256": "b94556ab2b7c78e5375750201716449b58beb33782d470778d6eaf5789b9e909" + }, + "gates/combined-strict-3.result.json": { + "bytes": 1650, + "sha256": "7e255308cc8f4fd077aada293d638badeef67faa1b7b56ecf597d2241193499c" + }, + "gates/core-defaults-2.admission.json": { + "bytes": 2368, + "sha256": "750dc34cbfbc0f8ff2392f97de5161bf4216aa50a1c09c12b3ee5587c870d162" + }, + "gates/core-defaults-2.inputs.json": { + "bytes": 137890, + "sha256": "8478620ab2deeef2625b9b3a485e2a2d39c9a958cbc8bbbcd1466e977aac57b7" + }, + "gates/core-defaults-2.log": { + "bytes": 2402, + "sha256": "21c020d7a2131502c67c94db8781bb7905066661e6ee468112d138c1272ef026" + }, + "gates/core-defaults-2.result.json": { + "bytes": 1723, + "sha256": "45f368f909bd94a0604cb51a7c13b752a72167d3ab779474ab87d7264ad9cd1d" + }, + "gates/core-list-1.inputs.json": { + "bytes": 137890, + "sha256": "0bb00e62be1453a0a7cda619eae38d7014b95484f846e2242d36e940f9720a46" + }, + "gates/core-list-1.log": { + "bytes": 13051, + "sha256": "0441f20249b8aa3a72a37e32fc692c4a132fc22847f4cdc5a4c5b34267f18c7d" + }, + "gates/core-list-1.result.json": { + "bytes": 14539, + "sha256": "0a3697f101aeeb518381a885256df329471701fd5ab14a127324fe5e8e870e5a" + }, + "gates/core-list-2.inputs.json": { + "bytes": 137890, + "sha256": "8478620ab2deeef2625b9b3a485e2a2d39c9a958cbc8bbbcd1466e977aac57b7" + }, + "gates/core-list-2.log": { + "bytes": 13051, + "sha256": "74c0eebab60b4c832f402e5e7ddf9d71660f21153beb605b11b5c7baad2885de" + }, + "gates/core-list-2.result.json": { + "bytes": 14539, + "sha256": "e12415ae2e5cf186990c977c933de7a35e7c7e9bf88e94980f089ef808d6c405" + }, + "gates/core-scenario-1.inputs.json": { + "bytes": 137890, + "sha256": "0bb00e62be1453a0a7cda619eae38d7014b95484f846e2242d36e940f9720a46" + }, + "gates/core-scenario-1.log": { + "bytes": 9188, + "sha256": "f91242c9be5b54163bb6b6f91d6057d9f525e8b21554c1e4ee782f67dc7eb3df" + }, + "gates/core-scenario-1.result.json": { + "bytes": 1725, + "sha256": "60801831493c6dd1b714b3ed34b10a51b17e74e18489fa9270c4da8492d429d3" + }, + "gates/core-scenario-2.admission.json": { + "bytes": 3351, + "sha256": "99c7636e643fb751f9655538f7320bd2f29e545127add3a7d60bf3bedb08f66c" + }, + "gates/core-scenario-2.inputs.json": { + "bytes": 137890, + "sha256": "8478620ab2deeef2625b9b3a485e2a2d39c9a958cbc8bbbcd1466e977aac57b7" + }, + "gates/core-scenario-2.log": { + "bytes": 3405, + "sha256": "3c9431f0eb0e156f227302012a4fd563378100615b192a84dd2ceedb41773d40" + }, + "gates/core-scenario-2.result.json": { + "bytes": 1723, + "sha256": "c325748e5bf63ec4715f11e42135b20c9676884d9d310970dbde684ae52f183d" + }, + "gates/defaults-list-2.inputs.json": { + "bytes": 137890, + "sha256": "8478620ab2deeef2625b9b3a485e2a2d39c9a958cbc8bbbcd1466e977aac57b7" + }, + "gates/defaults-list-2.log": { + "bytes": 1049, + "sha256": "26f07434fce51f6607aef43832345c0be7dd28c173d7efccae8b0e981d99ea09" + }, + "gates/defaults-list-2.result.json": { + "bytes": 2447, + "sha256": "1f7617e6cea7e89be6db15b59f66a18d5f5f9b1764a4e947a4294204915b6057" + }, + "gates/defaults-run-2.admission.json": { + "bytes": 1080, + "sha256": "4b9b7924b93fedce7dbea9fac55bfc9a3c51cdb8237192c13f4733eb1b6e0326" + }, + "gates/defaults-run-2.inputs.json": { + "bytes": 137890, + "sha256": "8478620ab2deeef2625b9b3a485e2a2d39c9a958cbc8bbbcd1466e977aac57b7" + }, + "gates/defaults-run-2.log": { + "bytes": 1102, + "sha256": "fd14010517c7af06147efac854d888272021590fa49e7510ab510eb16b31417e" + }, + "gates/defaults-run-2.result.json": { + "bytes": 1748, + "sha256": "e529b4bcd8aecbcbb1100c90a91777ea306b1813bf180d8ad3647d706d6e912d" + }, + "launchers/0b14e2e80e4c02ecd31f6dfa5fdfaf1594a6bc3ac319530eca1a3c81505a478e.py": { + "bytes": 7475, + "sha256": "0b14e2e80e4c02ecd31f6dfa5fdfaf1594a6bc3ac319530eca1a3c81505a478e" + }, + "launchers/596dd8212886096eb629cc690efa788ed72a1c2b44e40f8a0c2b691a1c13f7b5.py": { + "bytes": 6532, + "sha256": "596dd8212886096eb629cc690efa788ed72a1c2b44e40f8a0c2b691a1c13f7b5" + }, + "launchers/capture-provenance.json": { + "bytes": 966, + "sha256": "a13d0b82f3b78604fa2a086cb16a7ae7df05592ed4dc3d4e0d0e6dd06d341936" + }, + "launchers/ddb37f5c1ac03403b1f4d01fd04e1207e6f718c5b02401b885d78db7e1a89b20.py": { + "bytes": 6802, + "sha256": "ddb37f5c1ac03403b1f4d01fd04e1207e6f718c5b02401b885d78db7e1a89b20" + }, + "launchers/df812935028c17145a72650c5e083c8609398e903139907d5d76db817b1524f6.py": { + "bytes": 7314, + "sha256": "df812935028c17145a72650c5e083c8609398e903139907d5d76db817b1524f6" + }, + "reviews/composition-review.md": { + "bytes": 13847, + "sha256": "cb2391e8d4d84690b2852cca83f8c14aceb155ad363a257295063038a3e68d50" + }, + "tools/admit-scenario-union-gate.py": { + "bytes": 2887, + "sha256": "15b248da53caadc3961650d5855d557dd41e72f35f055c323059684faf138816" + } + }, + "gates": [ + { + "source": "015273ac8a7ce97d4aee678d653256abde222695", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "source_defaults", + "--", + "--test-threads=1" + ], + "mode": "test", + "scope": "core", + "name": "combined-core-defaults-1", + "inputs": 758, + "listing": "combined-core-list-1", + "outcomes": [ + 22, + 0, + 0 + ], + "ignored": [] + }, + { + "source": "015273ac8a7ce97d4aee678d653256abde222695", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "--", + "--list" + ], + "mode": "list", + "scope": "core", + "name": "combined-core-list-1", + "inputs": 758, + "listed": 129 + }, + { + "source": "015273ac8a7ce97d4aee678d653256abde222695", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "scenario_layout", + "--", + "--test-threads=1" + ], + "mode": "test", + "scope": "core", + "name": "combined-core-scenario-1", + "inputs": 758, + "listing": "combined-core-list-1", + "outcomes": [ + 27, + 0, + 0 + ], + "ignored": [] + }, + { + "source": "015273ac8a7ce97d4aee678d653256abde222695", + "exit": 101, + "command": [ + "cargo", + "clippy", + "--locked", + "--offline", + "--workspace", + "--all-targets", + "--", + "-D", + "warnings" + ], + "mode": "clippy", + "scope": "workspace", + "name": "combined-strict-1", + "inputs": 758 + }, + { + "source": "c4897485b7058570a563707c4f5840f500a6c265", + "exit": 101, + "command": [ + "cargo", + "clippy", + "--locked", + "--offline", + "--workspace", + "--all-targets", + "--", + "-D", + "warnings" + ], + "mode": "clippy", + "scope": "workspace", + "name": "combined-strict-2", + "inputs": 758 + }, + { + "source": "f82e29d6b8ed2b5fd23ac806675d3eafe851d104", + "exit": 0, + "command": [ + "cargo", + "clippy", + "--locked", + "--offline", + "--workspace", + "--all-targets", + "--", + "-D", + "warnings" + ], + "mode": "clippy", + "scope": "workspace", + "name": "combined-strict-3", + "inputs": 760 + }, + { + "source": "2a0579daafb89994730284c108f460782e5e6650", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "source_defaults", + "--", + "--test-threads=1" + ], + "mode": "test", + "scope": "core", + "name": "core-defaults-2", + "inputs": 742, + "listing": "core-list-2", + "outcomes": [ + 22, + 0, + 0 + ], + "ignored": [] + }, + { + "source": "0b61771d079cae4a513958fad04e6c3e785d458f", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "--", + "--list" + ], + "mode": "list", + "scope": "core", + "name": "core-list-1", + "inputs": 742, + "listed": 129 + }, + { + "source": "2a0579daafb89994730284c108f460782e5e6650", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "--", + "--list" + ], + "mode": "list", + "scope": "core", + "name": "core-list-2", + "inputs": 742, + "listed": 129 + }, + { + "source": "0b61771d079cae4a513958fad04e6c3e785d458f", + "exit": 101, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "scenario_layout", + "--", + "--test-threads=1" + ], + "mode": "test", + "scope": "core", + "name": "core-scenario-1", + "inputs": 742, + "listing": "core-list-1", + "outcomes": [ + 20, + 7, + 0 + ], + "ignored": [] + }, + { + "source": "2a0579daafb89994730284c108f460782e5e6650", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--lib", + "scenario_layout", + "--", + "--test-threads=1" + ], + "mode": "test", + "scope": "core", + "name": "core-scenario-2", + "inputs": 742, + "listing": "core-list-2", + "outcomes": [ + 27, + 0, + 0 + ], + "ignored": [] + }, + { + "source": "2a0579daafb89994730284c108f460782e5e6650", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--test", + "default_omission_preservation", + "--", + "--list" + ], + "mode": "list", + "scope": "defaults", + "name": "defaults-list-2", + "inputs": 742, + "listed": 11 + }, + { + "source": "2a0579daafb89994730284c108f460782e5e6650", + "exit": 0, + "command": [ + "cargo", + "test", + "--locked", + "--offline", + "-p", + "oa-core", + "--test", + "default_omission_preservation", + "--", + "--test-threads=1" + ], + "mode": "test", + "scope": "defaults", + "name": "defaults-run-2", + "inputs": 742, + "listing": "defaults-list-2", + "outcomes": [ + 11, + 0, + 0 + ], + "ignored": [] + } + ] +} diff --git a/harness/experiments/peer-union-windows-20260923/negative-controls-original.py b/harness/experiments/peer-union-windows-20260923/negative-controls-original.py new file mode 100644 index 00000000..3c885bb0 --- /dev/null +++ b/harness/experiments/peer-union-windows-20260923/negative-controls-original.py @@ -0,0 +1,73 @@ +from pathlib import Path +import copy +import hashlib +import importlib.util +import json +import zipfile + +root = Path(__file__).resolve().parent.parent +original = root / 'harness/experiments/peer-union-windows-20260923' +scratch = root / '.local/peer-union-verifier-controls-20260923' +scratch.mkdir(exist_ok=True) +spec = importlib.util.spec_from_file_location('peer_verify', original / 'verify.py') +module = importlib.util.module_from_spec(spec) +spec.loader.exec_module(module) +manifest = json.loads((original / 'manifest.json').read_bytes()) +with zipfile.ZipFile(original / 'evidence.zip') as z: + data = {name: z.read(name) for name in z.namelist()} + + +def sha(raw): + return hashlib.sha256(raw).hexdigest() + + +def refresh(payloads, claim, name, raw): + payloads[name] = raw + claim['payloads'][name] = {'bytes': len(raw), 'sha256': sha(raw)} + + +reports = [] +for case in ('payload-corruption', 'outcome-count', 'missing-selected-outcome', 'git-input-binding'): + payloads, claim = dict(data), copy.deepcopy(manifest) + folder = scratch / case + folder.mkdir(exist_ok=True) + if case == 'payload-corruption': + payloads['gates/combined-strict-3.log'] += b'corruption' + elif case == 'outcome-count': + next(g for g in claim['gates'] if g['name'] == 'combined-core-scenario-1')['outcomes'] = [26, 0, 0] + elif case == 'missing-selected-outcome': + name = 'gates/combined-core-scenario-1.log' + lines = payloads[name].splitlines(keepends=True) + removed = next(i for i, line in enumerate(lines) if line.startswith(b'test ') and b' ... ok' in line) + del lines[removed] + changed = b''.join(lines) + refresh(payloads, claim, name, changed) + receipt_name = 'gates/combined-core-scenario-1.result.json' + receipt = json.loads(payloads[receipt_name]) + receipt['log_sha256'] = sha(changed) + refresh(payloads, claim, receipt_name, json.dumps(receipt).encode()) + else: + input_name = 'gates/combined-strict-3.inputs.json' + inputs = json.loads(payloads[input_name]) + inputs['inputs'][0]['sha256'] = '0' * 64 + changed = json.dumps(inputs).encode() + refresh(payloads, claim, input_name, changed) + receipt_name = 'gates/combined-strict-3.result.json' + receipt = json.loads(payloads[receipt_name]) + receipt['inputs_sha256'] = sha(changed) + refresh(payloads, claim, receipt_name, json.dumps(receipt).encode()) + with zipfile.ZipFile(folder / 'evidence.zip', 'w', compression=zipfile.ZIP_DEFLATED) as z: + for name, raw in payloads.items(): + z.writestr(name, raw) + archive = (folder / 'evidence.zip').read_bytes() + claim['archive_bytes'], claim['archive_sha256'] = len(archive), sha(archive) + (folder / 'manifest.json').write_text(json.dumps(claim), encoding='utf-8') + try: + module.verify(folder, root) + except AssertionError: + reports.append({'case': case, 'result': 'REJECTED_AS_EXPECTED'}) + else: + raise AssertionError('Corrupted evidence accepted: ' + case) +report = {'source_archive_sha256': manifest['archive_sha256'], 'verifier_sha256': sha((original / 'verify.py').read_bytes()), 'controls': reports} +(scratch / 'result.json').write_text(json.dumps(report, indent=2), encoding='utf-8') +print(json.dumps(report, indent=2)) diff --git a/harness/experiments/peer-union-windows-20260923/negative-controls-result.json b/harness/experiments/peer-union-windows-20260923/negative-controls-result.json new file mode 100644 index 00000000..4a5b2c94 --- /dev/null +++ b/harness/experiments/peer-union-windows-20260923/negative-controls-result.json @@ -0,0 +1,22 @@ +{ + "source_archive_sha256": "4f4ef08a718296b7991908bfe7fd9ac02c0187eaeace0f2bdb77102d49eb9032", + "verifier_sha256": "d0d85cef3beaa41b1e03110d566043f1dee91d82d27fe6075f776a612962cab6", + "controls": [ + { + "case": "payload-corruption", + "result": "REJECTED_AS_EXPECTED" + }, + { + "case": "outcome-count", + "result": "REJECTED_AS_EXPECTED" + }, + { + "case": "missing-selected-outcome", + "result": "REJECTED_AS_EXPECTED" + }, + { + "case": "git-input-binding", + "result": "REJECTED_AS_EXPECTED" + } + ] +} \ No newline at end of file diff --git a/harness/experiments/peer-union-windows-20260923/verify.py b/harness/experiments/peer-union-windows-20260923/verify.py new file mode 100644 index 00000000..c3b3957e --- /dev/null +++ b/harness/experiments/peer-union-windows-20260923/verify.py @@ -0,0 +1,113 @@ +"""Audit the accompanying frozen-source gate archive without running its commands.""" +from pathlib import Path +import argparse +import hashlib +import json +import re +import subprocess +import zipfile + + +def sha(raw): + return hashlib.sha256(raw).hexdigest() + + +def verify(folder, repo): + manifest = json.loads((folder / 'manifest.json').read_bytes()) + archive = (folder / 'evidence.zip').read_bytes() + assert len(archive) == manifest['archive_bytes'] + assert sha(archive) == manifest['archive_sha256'] + with zipfile.ZipFile(folder / 'evidence.zip') as z: + assert len(z.namelist()) == len(set(z.namelist())) + assert set(z.namelist()) == set(manifest['payloads']) + data = {name: z.read(name) for name in z.namelist()} + for name, raw in data.items(): + expected = manifest['payloads'][name] + assert len(raw) == expected['bytes'] and sha(raw) == expected['sha256'], name + + source_inputs = {} + gates = {} + for claim in manifest['gates']: + name = claim['name'] + r = json.loads(data[f'gates/{name}.result.json']) + raw = data[f'gates/{name}.log'] + input_raw = data['gates/' + r['inputs']] + inputs = json.loads(input_raw) + assert sha(raw) == r['log_sha256'] + assert sha(input_raw) == r['inputs_sha256'] + assert r['source'] == r['head_after'] == claim['source'] == inputs['source'] + assert r['changed_inputs'] == [] + assert r['exit'] == claim['exit'] + assert r['command'] == claim['command'] + assert r['mode'] == claim['mode'] and r['scope'] == claim['scope'] + assert r['launcher_sha256'] == r['launcher_sha256_after'] + launcher = data['launchers/' + r['launcher_sha256'] + '.py'] + assert sha(launcher) == r['launcher_sha256'] + assert len(inputs['inputs']) == claim['inputs'] + paths = [item['path'] for item in inputs['inputs']] + assert len(paths) == len(set(paths)) + for item in inputs['inputs']: + key = (r['source'], item['path']) + assert key not in source_inputs or source_inputs[key] == item + source_inputs[key] = item + output = raw.decode('utf-8', errors='strict') + if r['mode'] == 'list' and r['exit'] == 0: + names = re.findall(r'^([^\r\n]+): test\r?$', output, re.M) + assert names and len(names) == len(set(names)) + assert names == r['listing_members'] + assert len(names) == r['listing_count'] == claim['listed'] + assert len(r['artifacts']) == 1 + if r['mode'] == 'clippy' and r['exit'] == 0: + assert re.search(r'Finished `dev` profile', output) + assert not re.search(r'^error(?:\[|:)', output, re.M) + gates[name] = (r, output, input_raw) + + tests = [] + for claim in manifest['gates']: + if 'listing' not in claim: + continue + r, output, input_raw = gates[claim['name']] + listing, _, listed_inputs = gates[claim['listing']] + assert r['mode'] == 'test' and listing['mode'] == 'list' + assert r['source'] == listing['source'] and r['scope'] == listing['scope'] + assert input_raw == listed_inputs and r['artifacts'] == listing['artifacts'] + selected = {name for name in listing['listing_members'] if r['filter'] in name} + assert selected + outcomes = re.findall(r'^test ([^\r\n]+) \.\.\. (ok|FAILED|ignored)(?:, ([^\r\n]*))?\r?$', output, re.M) + assert len(outcomes) == len({name for name, _, _ in outcomes}) == len(selected) + assert {name for name, _, _ in outcomes} == selected + counts = [sum(status == wanted for _, status, _ in outcomes) for wanted in ('ok', 'FAILED', 'ignored')] + assert counts == claim['outcomes'] + summaries = re.findall(r'^test result: (?:ok|FAILED)\. (\d+) passed; (\d+) failed; (\d+) ignored; (\d+) measured; (\d+) filtered out;', output, re.M) + assert summaries == [tuple(map(str, [*counts, 0, len(listing['listing_members']) - len(selected)]))] + ignores = [{'name': name, 'reason': reason} for name, status, reason in outcomes if status == 'ignored'] + assert ignores == claim.get('ignored', []) + tests.append({'name': claim['name'], 'outcomes': counts, 'selected': len(selected)}) + + keys = sorted(source_inputs) + run = subprocess.run(['git', 'cat-file', '--batch'], cwd=repo, + input=''.join(f'{commit}:{path}\n' for commit, path in keys).encode(), + capture_output=True, check=True) + offset = 0 + for key in keys: + end = run.stdout.index(b'\n', offset) + fields = run.stdout[offset:end].split() + assert len(fields) == 3 and fields[1] == b'blob', key + size = int(fields[2]) + blob = run.stdout[end + 1:end + 1 + size] + expected = source_inputs[key] + assert size == expected['bytes'] and sha(blob) == expected['sha256'], key + offset = end + 2 + size + assert offset == len(run.stdout) + return {'payloads': len(data), 'gates': len(gates), 'source_inputs': len(keys), 'tests': tests, + 'status': 'ARCHIVE_AND_RECORDED_SCOPE_VERIFIED', + 'limitation': 'Does not rerun commands, reconstruct executable bytes, establish native behavior, or accept a release. Historical failures and launcher-capture limits remain in README.'} + + +if __name__ == '__main__': + if not __debug__: + raise SystemExit('Optimized Python is not supported') + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--repo', type=Path, required=True) + args = parser.parse_args() + print(json.dumps(verify(Path(__file__).resolve().parent, args.repo), indent=2))