From 8b55835a7d5232fa3b711ec611085c3353fb7086 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:06:04 +0000 Subject: [PATCH 1/6] The 2.0.1 pair recorded (7cfa422a + 38351afd), F0 re-pinned with the founder's two rulings, and four gate tools from Review B's night Batch 201-7cfa422a-38351afd: node 7cfa422a (the miner base-unit fix, amended after 777214af's self-recursive connect failed to compile under the steward's read) green on the kaspad check and five suites on build-4 over the key-succession pairing; miner cut tip 38351afd (crate identical to 3c13a71c) green on pow and app on build-2. F0 names those pins and records the founder's 19:57 rulings on F04 (the recovery lock kept and always labelled recovery) and F14 (the public miner from 2.0.2 without remote jobs; the lab build for our fleet) as resolved. Tools: proof-rule-bypass-check.sh (F02: the test bypass cannot reach a release build; a cell of the node matrix from now, red until the proving lane's change lands); test-map-merge.py and the page regeneration at the merge (two lanes' cells no longer collide as text); push_race in merge-to-master.sh (a push that lost master's compare-and-swap retries without re-running the hook; twelve tries); review-suite.mjs (the REV suite generated from a review's findings and dispatch, written in the next commit once Review B is on master); test-record.mjs --note (a dated note on a suite, never an accept text). Co-Authored-By: Claude Fable 5.1 --- docs/plans/igneum-2.0-f0-manifest.md | 11 +- docs/plans/igneum-2.0-test-registry.json | 414 ++++++++++---------- tools/ci/README.md | 4 + tools/ci/batches/201-7cfa422a-aa0e0f45.json | 52 +++ tools/ci/checks.txt | 2 + tools/ci/merge-to-master.sh | 60 ++- tools/ci/pre-push.sh | 2 + tools/ci/proof-rule-bypass-check.sh | 65 +++ tools/ci/review-suite.mjs | 62 +++ tools/ci/test-map-merge.py | 44 +++ tools/ci/test-record.mjs | 17 +- 11 files changed, 516 insertions(+), 217 deletions(-) create mode 100644 tools/ci/batches/201-7cfa422a-aa0e0f45.json create mode 100755 tools/ci/proof-rule-bypass-check.sh create mode 100644 tools/ci/review-suite.mjs create mode 100755 tools/ci/test-map-merge.py diff --git a/docs/plans/igneum-2.0-f0-manifest.md b/docs/plans/igneum-2.0-f0-manifest.md index f8ad6d1b3..0c8a05d3e 100644 --- a/docs/plans/igneum-2.0-f0-manifest.md +++ b/docs/plans/igneum-2.0-f0-manifest.md @@ -6,8 +6,8 @@ The fixture every case of the Test and Acceptance Standard (docs/plans/igneum-2. | Field | Value | Read from | Owner | |---|---|---|---| -| Miner cut tip (release-2.0.1) | 2826f37e (2ea7b43f + the DMG README line + the node pin ef0f2ed8 + elf/prior from key-succession-pin; the app crate byte-identical to 2ea7b43f's, so the pow and app cells read on 2ea7b43f cover it by content; a re-run on 2826f37e records the literal) | the shipper's line 19:3x | shipper (ae892a8b0f78fe31c) | -| Node sha for the roll | ef0f2ed8 = 291ee6ae (key succession over 417c4a57) + the workspace version 2.0.1 | the node lane's line 19:0x | node lane (a283f5f0d364ceef0) | +| Miner cut tip (release-2.0.1) | aa0e0f45 (9c844503 + the pin file; 9c844503 = 2826f37e + the six-target packaged peer list; the app crate byte-identical to 2ea7b43f's throughout, so the pow and app cells read on 9c844503 cover it by content) | the shipper's line 19:5x | shipper (ae892a8b0f78fe31c) | +| Node sha for the roll | 7cfa422a = ef0f2ed8 (291ee6ae + the 2.0.1 version) + the miner base-unit fix, amended (777214af did not compile: a self-recursive connect, caught by the steward's read at 19:50) | the node lane's and shipper's lines 19:5x | node lane (a283f5f0d364ceef0) | | Node line read green tonight | 4cdcc488, d5981514, bee41b5e, 9fc9f42a, 5713d547, 417c4a57, 291ee6ae (ef0f2ed8 = 291ee6ae + the version bump, its own read on build-4 recorded as the literal) | the steward's matrices on build-2 and build-4 | CI steward | | Network | igneum-devnet-4, a fresh genesis; EVM chain id 4465 (0x1171), set in devnet4_params, read by the canaries as eth_chainId on every candidate tonight, pinned by the digest be5f4068; every 2.0 devnet node, pool and reference app signs with it; mainnet's and the testnet's ids unchanged from the 0.3 line | the node lane's line 19:3x | node lane | | Object digest | be5f406802cec1227a5ef50d42181ab42444f79af170775b22c85cb9a917273b (4cdcc488 and every sha after it; no live digest move since) | the node lane's lines | node lane | @@ -37,6 +37,13 @@ The fixture every case of the Test and Acceptance Standard (docs/plans/igneum-2. | Trust anchors (light client, oracle) | BLOCKED | reference-apps lane | VER-01 and VER-04 read BLOCKED | | The class v6 freeze line in packaging/pow-freeze.txt | open: three D1 candidates on the node mirrors (class-v6-node 3af510ec on c245d50b9 fingerprint a65e4c5a; class-v6-node-b 46e7ac18 with the acceptance fix, fingerprint 6cdd922a; class-v6-node-review 2f6eb9e9 on 04442d9ca, fingerprint 7a1dec1c, six suites green on build-1 at 19:3x) | hash lane, node lane | class v5 stays the mining class | +## Resolved by the founder (8 October 2026, 19:57 UK, through the coordinator) + +| Field | Ruling | +|---|---| +| F04 (Review B), the recovery lock | kept, and always labelled "recovery", never "final", on every surface (the checkpoint field, the explorer, receipts, the light client, the oracle, the site) | +| F14 (Review B), fleet control and the public client | the public miner ships from 2.0.2 without remote jobs; our own fleet runs the lab build with its own signing root | + ## Signatures (by 23:30 UK, 8 October 2026) | Role | Name or lane | Commit signed | Time | diff --git a/docs/plans/igneum-2.0-test-registry.json b/docs/plans/igneum-2.0-test-registry.json index e21c357f4..04c544497 100644 --- a/docs/plans/igneum-2.0-test-registry.json +++ b/docs/plans/igneum-2.0-test-registry.json @@ -50,16 +50,16 @@ "manual_page": 18, "owner_lane": "node lane (a283f5f0d364ceef0)", "run_status": "RUNNING", - "evidence_path": "docs/plans/igneum-2.0-f0-manifest.md; packaging/pow-freeze.txt; build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-kaspad-check.log", - "run_id": "f0-manifest-20261008-b", - "updated": "2026-10-08T18:51:08.834Z", + "evidence_path": "docs/plans/igneum-2.0-f0-manifest.md; packaging/pow-freeze.txt; build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-kaspad-check.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "check:freeze", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "GOV-01": "partial: the linked igneum-pow tree's fingerprint must match a listed freeze or the build fails, the binary prints which; the manifest (igneum_getManifest) names the object digest; the signed F0 manifest is the node lane's row tonight" }, - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -165,10 +165,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "the evidence vault F9 (raw and negative evidence preserved) is the gate rule landing by 21:00: a PASS must carry its evidence file", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -321,10 +321,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "the stale-evidence rule (evidence older than the manifest sha reads NOT RUN) is the gate rule landing by 21:00", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } } ] @@ -587,10 +587,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "accepted work under ordinary connectivity needs the fault network F4", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -708,18 +708,18 @@ "manual_page": 24, "owner_lane": "hash lane (a690540514aa453d7)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-miner.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-miner.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:miner", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "UX-06": "partial: the miner's own template selection tests", "UX-04": "partial: payout label and share accounting tests; custody is the pool lane's row", "POW-01": "partial: the pack re-check seam against the pack's 96 vectors (recheck_pack); the million-vector campaign is harness:p01-vectors" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -749,18 +749,18 @@ "manual_page": 24, "owner_lane": "hash lane (a690540514aa453d7)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/miner-2826f37e/box2-pow.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-pow.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:pow", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "POW-02": "partial: program derivation, ds55 geometry, the v6 fold, the packs and the spec read-back tests; the independent re-implementation and the index-fold census are the hash lane's harnesses", "POW-08": "partial: the freeze list and the generator version pin; the public-claim scrub is the site gate's", "POW-07": "the mixed FP32 branch is excluded and unreachable: no class flag reaches an FP op in igneum-pow on master (the mixedfp lane's branch is not on master); evidence the grep of the emitters on master, recorded by the hash lane" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -940,18 +940,18 @@ "manual_page": 26, "owner_lane": "hash lane (a690540514aa453d7)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/miner-2826f37e/box2-pow.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-pow.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:pow", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "POW-02": "partial: program derivation, ds55 geometry, the v6 fold, the packs and the spec read-back tests; the independent re-implementation and the index-fold census are the hash lane's harnesses", "POW-08": "partial: the freeze list and the generator version pin; the public-claim scrub is the site gate's", "POW-07": "the mixed FP32 branch is excluded and unreachable: no class flag reaches an FP op in igneum-pow on master (the mixedfp lane's branch is not on master); evidence the grep of the emitters on master, recorded by the hash lane" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -981,18 +981,18 @@ "manual_page": 26, "owner_lane": "hash lane (a690540514aa453d7)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/miner-2826f37e/box2-pow.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-pow.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:pow", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "POW-02": "partial: program derivation, ds55 geometry, the v6 fold, the packs and the spec read-back tests; the independent re-implementation and the index-fold census are the hash lane's harnesses", "POW-08": "partial: the freeze list and the generator version pin; the public-claim scrub is the site gate's", "POW-07": "the mixed FP32 branch is excluded and unreachable: no class flag reaches an FP op in igneum-pow on master (the mixedfp lane's branch is not on master); evidence the grep of the emitters on master, recorded by the hash lane" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } } ] @@ -1466,10 +1466,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "seed-selection resistance is the census harness (the class v6 invention lane), not yet in the matrix", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -1499,12 +1499,12 @@ "manual_page": 31, "owner_lane": "finality lane (aca0f5ed924a2a99b)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-consensus.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:consensus", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality processes' agreement tests", "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", @@ -1514,7 +1514,7 @@ "ROT-05": "partial: the finality-stopped pause tests", "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -1544,18 +1544,18 @@ "manual_page": 31, "owner_lane": "hash lane (a690540514aa453d7)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-core.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-core.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:core", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality field and checkpoint tests on the object; ordering under load is the consensus suite and the sim", "INC-01": "partial: emission, fee and payout arithmetic tests; the reconciliation over a live chain is the economics lane's", "ROT-06": "partial: the dataset activation and digest tests; a live activation is the fast-time harness" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -1624,10 +1624,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "the no-new-rules counterfactual is a research harness", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } } ] @@ -2045,19 +2045,19 @@ "manual_page": 36, "owner_lane": "reference-apps lane (a2060899d2a27d31c)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-exec.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-exec.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:exec", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "ZKP-01": "partial: a real proof verifies, a wrong statement and garbage are refused (nativeverify)", "ZKP-03": "partial: a snapshot under another digest refused, the epoch streams bound to the digest", "OPS-04": "partial: snapshot install, replay and genesis recapture after a crash", "EVM-02": "partial: the replay tests on the day stream; the signature and chain-id binding vectors are an EVM harness still to map" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2247,10 +2247,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "execution DoS workloads need the workload catalogue F3", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2340,19 +2340,19 @@ "manual_page": 39, "owner_lane": "enforced-proving lane (a6e8f84588b809d62)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-exec.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-exec.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:exec", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "ZKP-01": "partial: a real proof verifies, a wrong statement and garbage are refused (nativeverify)", "ZKP-03": "partial: a snapshot under another digest refused, the epoch streams bound to the digest", "OPS-04": "partial: snapshot install, replay and genesis recapture after a crash", "EVM-02": "partial: the replay tests on the day stream; the signature and chain-id binding vectors are an EVM harness still to map" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2424,19 +2424,19 @@ "manual_page": 39, "owner_lane": "enforced-proving lane (a6e8f84588b809d62)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-exec.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-exec.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:exec", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "ZKP-01": "partial: a real proof verifies, a wrong statement and garbage are refused (nativeverify)", "ZKP-03": "partial: a snapshot under another digest refused, the epoch streams bound to the digest", "OPS-04": "partial: snapshot install, replay and genesis recapture after a crash", "EVM-02": "partial: the replay tests on the day stream; the signature and chain-id binding vectors are an EVM harness still to map" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2547,17 +2547,17 @@ "manual_page": 40, "owner_lane": "enforced-proving lane (a6e8f84588b809d62)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-p2p-flows.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-p2p-flows.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:p2p-flows", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "OPS-06": "partial: malformed relay messages refused; traffic containment under load is an OPS harness", "ZKP-06": "partial: proof relay coverage tests; aggregation completeness is the proving lane's test set" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2678,10 +2678,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "the consumer-shard reproduction is the fleet lane's pods", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2713,10 +2713,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "proving on the mining configuration is the fleet lane's", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2748,10 +2748,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "the request-to-payment path is the proving fleet's measurement", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2783,10 +2783,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "sustained load is the proving fleet's", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2818,10 +2818,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "overload and recovery is the proving fleet's", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2853,10 +2853,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "assignment windows are the proving fleet's", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2888,10 +2888,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "reassignment is the proving fleet's", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -2923,10 +2923,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "customer-verifiable output is the reference apps plus the fleet", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } } ] @@ -2976,18 +2976,18 @@ "manual_page": 45, "owner_lane": "enforced-proving lane (a6e8f84588b809d62)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-core.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-core.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:core", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality field and checkpoint tests on the object; ordering under load is the consensus suite and the sim", "INC-01": "partial: emission, fee and payout arithmetic tests; the reconciliation over a live chain is the economics lane's", "ROT-06": "partial: the dataset activation and digest tests; a live activation is the fast-time harness" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3021,10 +3021,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "revenue separation is the economics lane's model", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3058,10 +3058,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "the modified-client task choice needs an adversarial client harness", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3095,10 +3095,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "demand spikes are the economic model", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3132,10 +3132,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "reservation abuse needs the capacity harness", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3169,10 +3169,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "difficulty and timestamp manipulation needs the fault network F4", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3206,10 +3206,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "self-dealing fees need the economic model and a live window", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3243,10 +3243,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "failure concentration is a live-window measurement", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } } ] @@ -3292,12 +3292,12 @@ "manual_page": 48, "owner_lane": "fast-time lane (a8be71a0db962911c)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-consensus.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:consensus", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality processes' agreement tests", "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", @@ -3307,7 +3307,7 @@ "ROT-05": "partial: the finality-stopped pause tests", "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3377,12 +3377,12 @@ "manual_page": 48, "owner_lane": "finality lane (aca0f5ed924a2a99b)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-consensus.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:consensus", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality processes' agreement tests", "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", @@ -3392,7 +3392,7 @@ "ROT-05": "partial: the finality-stopped pause tests", "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3422,12 +3422,12 @@ "manual_page": 49, "owner_lane": "finality lane (aca0f5ed924a2a99b)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-consensus.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:consensus", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality processes' agreement tests", "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", @@ -3437,7 +3437,7 @@ "ROT-05": "partial: the finality-stopped pause tests", "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3467,12 +3467,12 @@ "manual_page": 49, "owner_lane": "finality lane (aca0f5ed924a2a99b)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-consensus.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:consensus", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality processes' agreement tests", "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", @@ -3482,7 +3482,7 @@ "ROT-05": "partial: the finality-stopped pause tests", "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3549,12 +3549,12 @@ "manual_page": 50, "owner_lane": "finality lane (aca0f5ed924a2a99b)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-consensus.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:consensus", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "FIN-01": "partial: the finality processes' agreement tests", "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", @@ -3564,7 +3564,7 @@ "ROT-05": "partial: the finality-stopped pause tests", "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3800,10 +3800,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "state reconstruction without founder storage is the OPS no-founder exercise", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3835,10 +3835,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "withholding and corruption detection needs the fault network F4", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3870,10 +3870,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "wallet key protection is the wallet lane's security row", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3903,19 +3903,19 @@ "manual_page": 53, "owner_lane": "reference-apps lane (a2060899d2a27d31c)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/miner-2826f37e/box2-app.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:app", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "UX-02": "partial: the engine state machine's pause, stop and knob tests; the operator study is UX-01's", "UX-03": "partial: the card and earnings rendering tests; the net-earnings model against real bills is COM/ECO evidence", "UX-07": "partial: the refused-update and manifest tests; the update-return lane's install classes are its own rows", "VER-08": "partial: the app's own state-word tests; the wallet and light client rows are VER-01 to VER-03" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } } ] @@ -3963,10 +3963,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "the no-founder exercise is an operations run, not a suite", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -3998,10 +3998,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "bootstrap diversity needs the fault network F4", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4068,19 +4068,19 @@ "manual_page": 55, "owner_lane": "node lane (a283f5f0d364ceef0)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-exec.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-exec.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:exec", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "ZKP-01": "partial: a real proof verifies, a wrong statement and garbage are refused (nativeverify)", "ZKP-03": "partial: a snapshot under another digest refused, the epoch streams bound to the digest", "OPS-04": "partial: snapshot install, replay and genesis recapture after a crash", "EVM-02": "partial: the replay tests on the day stream; the signature and chain-id binding vectors are an EVM harness still to map" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4112,10 +4112,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "proving workload isolation is the fleet's pod row", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4145,17 +4145,17 @@ "manual_page": 55, "owner_lane": "build-server lane (a352e49ff4613df86)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-p2p-flows.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-p2p-flows.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:p2p-flows", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "OPS-06": "partial: malformed relay messages refused; traffic containment under load is an OPS harness", "ZKP-06": "partial: proof relay coverage tests; aggregation completeness is the proving lane's test set" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4187,10 +4187,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "runbook detection is an operations run", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4222,10 +4222,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "repeat independent operation is a cross-release observation", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } } ] @@ -4302,19 +4302,19 @@ "manual_page": 57, "owner_lane": "shipper (ae892a8b0f78fe31c)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/miner-2826f37e/box2-app.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:app", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "UX-02": "partial: the engine state machine's pause, stop and knob tests; the operator study is UX-01's", "UX-03": "partial: the card and earnings rendering tests; the net-earnings model against real bills is COM/ECO evidence", "UX-07": "partial: the refused-update and manifest tests; the update-return lane's install classes are its own rows", "VER-08": "partial: the app's own state-word tests; the wallet and light client rows are VER-01 to VER-03" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4344,19 +4344,19 @@ "manual_page": 57, "owner_lane": "shipper (ae892a8b0f78fe31c)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/miner-2826f37e/box2-app.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:app", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "UX-02": "partial: the engine state machine's pause, stop and knob tests; the operator study is UX-01's", "UX-03": "partial: the card and earnings rendering tests; the net-earnings model against real bills is COM/ECO evidence", "UX-07": "partial: the refused-update and manifest tests; the update-return lane's install classes are its own rows", "VER-08": "partial: the app's own state-word tests; the wallet and light client rows are VER-01 to VER-03" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4386,18 +4386,18 @@ "manual_page": 58, "owner_lane": "pool design seat (a3832b1c3b274b310)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-miner.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-miner.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:miner", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "UX-06": "partial: the miner's own template selection tests", "UX-04": "partial: payout label and share accounting tests; custody is the pool lane's row", "POW-01": "partial: the pack re-check seam against the pack's 96 vectors (recheck_pack); the million-vector campaign is harness:p01-vectors" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4464,18 +4464,18 @@ "manual_page": 58, "owner_lane": "shipper (ae892a8b0f78fe31c)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/node-ef0f2ed8/box4-miner.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-miner.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:miner", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "UX-06": "partial: the miner's own template selection tests", "UX-04": "partial: payout label and share accounting tests; custody is the pool lane's row", "POW-01": "partial: the pack re-check seam against the pack's 96 vectors (recheck_pack); the million-vector campaign is harness:p01-vectors" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4505,19 +4505,19 @@ "manual_page": 59, "owner_lane": "shipper (ae892a8b0f78fe31c)", "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-ef0f2ed8-2826f37e/miner-2826f37e/box2-app.log", - "run_id": "201-ef0f2ed8-2826f37e", - "updated": "2026-10-08T18:51:08.658Z", + "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log", + "run_id": "201-7cfa422a-aa0e0f45", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "cell": "suite:app", - "manifest_sha": "ef0f2ed8", + "manifest_sha": "7cfa422a", "coverage": { "UX-02": "partial: the engine state machine's pause, stop and knob tests; the operator study is UX-01's", "UX-03": "partial: the card and earnings rendering tests; the net-earnings model against real bills is COM/ECO evidence", "UX-07": "partial: the refused-update and manifest tests; the update-return lane's install classes are its own rows", "VER-08": "partial: the app's own state-word tests; the wallet and light client rows are VER-01 to VER-03" }, - "at": "2026-10-08T18:51:08.658Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4616,10 +4616,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "commercial evidence, no automated harness", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4656,10 +4656,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "commercial evidence", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4696,10 +4696,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "commercial evidence", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4736,10 +4736,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "commercial evidence", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4776,10 +4776,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "commercial evidence", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4816,10 +4816,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "commercial evidence", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -4979,10 +4979,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "leadership comparison, an observation window", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -5017,10 +5017,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "observation window", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -5055,10 +5055,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "observation window", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -5093,10 +5093,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "observation window", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -5131,10 +5131,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "observation window", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } }, { @@ -5203,10 +5203,10 @@ "run_status": "NOT RUN", "evidence_path": "", "run_id": "", - "updated": "2026-10-08T18:51:08.834Z", + "updated": "2026-10-08T19:06:03.708Z", "evidence_record": { "reason": "observation window", - "at": "2026-10-08T18:51:08.834Z" + "at": "2026-10-08T19:06:03.708Z" } } ] diff --git a/tools/ci/README.md b/tools/ci/README.md index 9a9ea9fd9..a9a204fee 100644 --- a/tools/ci/README.md +++ b/tools/ci/README.md @@ -10,6 +10,10 @@ | the red watcher fires on cancelled and timed-out runs too (`ci-red.yml`, `red-watch.mjs`) | The watcher's `if` missing any of failure, cancelled, timed_out, or the conclusion not handed to the record step (the self-test reads the workflow file); the line names the kind: CI red, CI cancelled, CI timed out. | 7 October 2026 | | gh's active account is the stored Igneum entry (`gh-account-check.sh`, in Igneum's own gh directory `~/.config/gh-igneum` through `gh-env.sh`, never the founder's) | A push or a landing from this Mac while Igneum's gh directory names any other account as active, or none (the refusal names the one step: the founder or main stores the Igneum token there with `GH_CONFIG_DIR=~/.config/gh-igneum gh auth login --with-token`; no lane does); skipped with a line while `github-suspended` stands. RULE: no lane switches gh accounts on this Mac, ever; the second owner's login belongs to other projects and must never touch Igneum; the stored entry's name is in ~/.config/igneum/gh-user, never in the repository. | 7 October 2026, 21:41 UK: a lane switched gh to the other login during the suspension; nobody could say which | +| F02 (Review B): the proof-rule test bypass cannot reach a release build (`proof-rule-bypass-check.sh`; a cell of the node matrix) | An env read of IGNEUM_TEST_SKIP_PROOF_RULE with no cfg(test) or cfg(feature) guard in the 12 lines above, or under a feature in the crate's default features; a release igneumd carrying the bypass string. Red on every node sha until the proving lane's change (the read under a non-default feature or cfg(test)) lands | 8 Oct 2026 | +| the test map merges structurally at a landing (`test-map-merge.py`) and the harness page regenerates from the merged map (`merge-to-master.sh`) | Nothing by itself: two lanes adding cells collided as text and the regenerated page lost rule 26's race; the merge now keeps master's cells plus the branch's, minus what the branch removed and master left, and regenerates the page | 8 Oct 2026 | +| a push that lost the ref race retries without re-running the hook (`merge-to-master.sh` `push_race`, 12 tries) | Nothing by itself: under one landing a minute a 70-second hook per try never won master's compare-and-swap (Review B's landing lost three in a row); once the hook has passed on the first try and the rejection is a ref race, later tries push --no-verify (both parents gated) | 8 Oct 2026 | +| the REV suite is generated from an external review's findings.json and dispatch.md (`review-suite.mjs`; one case per required regression, NOT RUN, the owner from the dispatch table) | A registry whose REV suite differs from the generator's output (--check) | 8 Oct 2026 | | a registry landing carries its batches (`tools/ci/batches/.json`; `merge-to-master.sh` replays them onto master's copy at the merge) | Nothing by itself: the registry is a hot file, and a branch whose own copy of it was recorded during a seven-minute gate lost the race to another lane's rows three times in a row (8 Oct 2026, 19:1x UK). A branch that adds batch files is merged with master's registry, every added batch replayed through `test-record.mjs --record` (idempotent), and the evidence rules run on the merged result; rule 26 does not bind the registry path for such a branch | 8 Oct 2026 | | the registry's evidence rules (`registry-evidence-check.sh`, called by `merge-to-master.sh` after rule 26) | A landing that sets a case's run_status to PASS without an evidence_path that exists (in the tree at the landing, or on a build box over ssh; a box that does not answer is a line, not a refusal); a landing that changes a file under docs/analysis/ or a path a registry row names without moving that row's `updated` (the row and its evidence move together, GOV-04); a PASS whose evidence record pins another manifest than the registry's pinned_manifest_sha (stale evidence reads NOT RUN, GOV-08); a run_status written while the registry carries no approval block (thresholds before results, GOV-02) | 8 Oct 2026 | | the acceptance layer (`test-record.mjs`, `test-map.json`, `test-map-doc.mjs`; the founder's Test and Acceptance Standard, docs/plans/igneum-2.0-test-registry.json) | An automated case of the registry with no cell in the map and no NOT RUN reason; a map naming an unknown case; a stale harness-map page (generated from the JSON); the recorder's self-test: a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, never an accept text, and a case with no harness reads NOT RUN with its reason, never PASS by inference | 8 Oct 2026 | diff --git a/tools/ci/batches/201-7cfa422a-aa0e0f45.json b/tools/ci/batches/201-7cfa422a-aa0e0f45.json new file mode 100644 index 000000000..7694b2c0d --- /dev/null +++ b/tools/ci/batches/201-7cfa422a-aa0e0f45.json @@ -0,0 +1,52 @@ +{ + "run_id": "201-7cfa422a-aa0e0f45", + "manifest_sha": "7cfa422a", + "cut_tip": "aa0e0f45 (miner; cells on 9c844503, the crate identical); node 7cfa422a on the key-succession pairing", + "evidence_dir": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45", + "boxes": [ + "build-2", + "build-4" + ], + "cells": [ + { + "cell": "suite:pow", + "status": "RUNNING", + "evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-pow.log" + }, + { + "cell": "suite:app", + "status": "RUNNING", + "evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log" + }, + { + "cell": "suite:core", + "status": "RUNNING", + "evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-core.log" + }, + { + "cell": "suite:consensus", + "status": "RUNNING", + "evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log" + }, + { + "cell": "suite:exec", + "status": "RUNNING", + "evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-exec.log" + }, + { + "cell": "suite:miner", + "status": "RUNNING", + "evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-miner.log" + }, + { + "cell": "suite:p2p-flows", + "status": "RUNNING", + "evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-p2p-flows.log" + }, + { + "cell": "check:freeze", + "status": "RUNNING", + "evidence": "docs/plans/igneum-2.0-f0-manifest.md; packaging/pow-freeze.txt; build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-kaspad-check.log" + } + ] +} \ No newline at end of file diff --git a/tools/ci/checks.txt b/tools/ci/checks.txt index 7efc1ff48..b40cbf3e3 100644 --- a/tools/ci/checks.txt +++ b/tools/ci/checks.txt @@ -75,6 +75,8 @@ the test map: every automated case of the registry maps to a cell or carries a N the harness map page is generated from tools/ci/test-map.json and current P01 part A, the million-vector driver: a clean run is PASS, one wrong hash or one unanswered nonce is FAIL naming it (self-test, a fake worker) the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test) +F02 (Review B): the proof-rule test bypass cannot reach a release build: an env read with no cfg guard or under a default feature is red; a release binary carrying the bypass string is red (self-test) +the test map merges structurally at a landing: master's cells plus the branch's, minus what the branch removed and master left (self-test) the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first) the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first) every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026) diff --git a/tools/ci/merge-to-master.sh b/tools/ci/merge-to-master.sh index 702e8157c..a573b1ad0 100755 --- a/tools/ci/merge-to-master.sh +++ b/tools/ci/merge-to-master.sh @@ -26,7 +26,7 @@ MERGE_PID_FILE="$(git rev-parse --git-dir)/igneum-merge.pid" printf '%s %s %s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "${IGNEUM_MERGE_TITLE:-untitled}" > "$MERGE_PID_FILE" 2>/dev/null || true trap 'rm -f "$MERGE_PID_FILE"' EXIT . tools/ci/gh-env.sh # every gh call here reads Igneum's own gh directory, never the founder's (8 October 2026) -BRANCH="$(git rev-parse --abbrev-ref HEAD)"; TRIES=6; CI_WAIT_MIN="${CI_WAIT_MIN:-25}"; FIXES_MASTER=0; SELF_TEST=0; REMOTE="${MERGE_REMOTE:-origin}" +BRANCH="$(git rev-parse --abbrev-ref HEAD)"; TRIES=12; CI_WAIT_MIN="${CI_WAIT_MIN:-25}"; FIXES_MASTER=0; SELF_TEST=0; REMOTE="${MERGE_REMOTE:-origin}"; NOVERIFY="" while [ $# -gt 0 ]; do case "$1" in --tries) TRIES="$2"; shift 2 ;; --ci-wait) CI_WAIT_MIN="$2"; shift 2 ;; --fixes-master) FIXES_MASTER=1; shift ;; --remote) REMOTE="$2"; shift 2 ;; --self-test) SELF_TEST=1; shift ;; -*) echo "unknown option $1" >&2; exit 2 ;; *) BRANCH="$1"; shift ;; esac; done # --remote : land on another remote's master (a box mirror, build@:/srv/igneum.git, while GitHub is unreachable; main's # ruling of 7 October 2026, 19:5x UK). CI runs on GitHub only, so the CI rule binds the origin remote; on a mirror the box gate @@ -107,11 +107,39 @@ mirror_master() { # [landed-remote-url]: the landed master to every othe # merge_with_batches : in the current worktree (at ), the merge of ; when the branch added batch files, # the registry takes master's copy and every batch is replayed onto it, then the evidence rules run on the result; returns 1 on a # conflict outside the registry or a red evidence rule +# push_race : 0 when a rejected push lost only the ref's compare-and-swap (another landing moved master between the +# fetch and the push), 1 when the hook refused or something else failed. On a race the merge is rebuilt on the new tip; the hook +# already passed on the first try and both parents are gated (the branch fully, master's tip on its own landing), so the retry +# pushes with --no-verify: under tonight's landing rate (one every minute, 8 October 2026, 20:0x UK) a 70-second hook per try +# never wins the swap +push_race() { case "$1" in *"REFUSED"*|*" RED "*) return 1 ;; *"cannot lock ref"*|*"failed to update ref"*|*"fetch first"*|*"non-fast-forward"*) return 0 ;; *) return 1 ;; esac; } merge_with_batches() { local tip="$1" sha="$2" msg="$3" conflicts f + local MAP_CHANGED="${MAP_CHANGED:-0}" MAP_PATH="${MAP_PATH:-tools/ci/test-map.json}" PAGE_PATH="${PAGE_PATH:-docs/plans/igneum-2.0-test-harness-map.md}" BATCHES="${BATCHES:-}" REGISTRY_PATH="${REGISTRY_PATH:-docs/plans/igneum-2.0-test-registry.json}" if git "${AUTHOR[@]}" merge -q --no-ff --no-commit "$sha" >/dev/null 2>&1; then :; else conflicts=$(git diff --name-only --diff-filter=U) - if [ -z "$BATCHES" ] || [ "$conflicts" != "$REGISTRY_PATH" ]; then git merge --abort 2>/dev/null; return 1; fi + local c ok=1 + for c in $conflicts; do + case "$c" in + "$REGISTRY_PATH") [ -n "$BATCHES" ] || ok=0 ;; # rebuilt from master's copy below + "$PAGE_PATH") [ "$MAP_CHANGED" = 1 ] || ok=0 ;; # regenerated from the merged map below + "$MAP_PATH") [ "$MAP_CHANGED" = 1 ] || ok=0 ;; # merged structurally below (tools/ci/test-map-merge.py) + *) ok=0 ;; + esac + done + if [ "$ok" != 1 ]; then git merge --abort 2>/dev/null; return 1; fi + [ -n "$BATCHES" ] || git checkout -q "$tip" -- "$REGISTRY_PATH" 2>/dev/null || true + fi + if [ "$MAP_CHANGED" = 1 ] && git diff --name-only --diff-filter=U 2>/dev/null | grep -qx "$MAP_PATH"; then + local base3; base3=$(git merge-base "$tip" "$sha") + git show "$base3:$MAP_PATH" > /tmp/map-base.$$ ; git show "$tip:$MAP_PATH" > /tmp/map-master.$$ ; git show "$sha:$MAP_PATH" > /tmp/map-branch.$$ + python3 tools/ci/test-map-merge.py /tmp/map-base.$$ /tmp/map-master.$$ /tmp/map-branch.$$ "$MAP_PATH" || { echo "merge-to-master: the map does not merge structurally" >&2; git merge --abort 2>/dev/null; return 1; } + rm -f /tmp/map-base.$$ /tmp/map-master.$$ /tmp/map-branch.$$; git add "$MAP_PATH"; echo "merge-to-master: merged $MAP_PATH structurally (master's cells plus the branch's)" + fi + if [ "$MAP_CHANGED" = 1 ] && [ -f tools/ci/test-map-doc.mjs ]; then + git checkout -q "$tip" -- "$PAGE_PATH" 2>/dev/null || true # start from master's page; the generator overwrites it from the merged map + node tools/ci/test-map-doc.mjs >/dev/null || { echo "merge-to-master: the harness map page does not regenerate from the merged map" >&2; git merge --abort 2>/dev/null; return 1; } + echo "merge-to-master: regenerated $PAGE_PATH from the merged map"; git add -A fi if [ -n "$BATCHES" ]; then git checkout -q "$tip" -- "$REGISTRY_PATH" # master's copy, never the branch's @@ -208,7 +236,7 @@ success 4 u push run # the merge takes master's copy and replays the batch, so both rows land (the hot-file race, 8 October 2026, 19:1x UK) rb="$d/rb"; mkdir -p "$rb" && ( cd "$rb" && git init -q -b master . && mkdir -p docs/plans tools/ci/batches && cp "$ROOT/tools/ci/test-record.mjs" tools/ci/ && cp "$ROOT/tools/ci/registry-evidence-check.sh" tools/ci/ && cp "$ROOT/tools/ci/docs-only-check.sh" tools/ci/ 2>/dev/null printf '{"approval":"yes","suites":[{"code":"X","tests":[{"id":"X-1","method":"Automated","accept":"a"},{"id":"X-2","method":"Automated","accept":"b"}]}]}\n' > docs/plans/igneum-2.0-test-registry.json - printf '{"cells":{"c1":{"command":"x","box_class":"b","fixtures":[],"cases":["X-1"]},"c2":{"command":"y","box_class":"b","fixtures":[],"cases":["X-2"]}},"not_run":{}}\n' > tools/ci/test-map.json + printf '{"title":"t","registry":"docs/plans/igneum-2.0-test-registry.json","rule":"r","cells":{"c1":{"command":"x","box_class":"b","fixtures":[],"cases":["X-1"]},"c2":{"command":"y","box_class":"b","fixtures":[],"cases":["X-2"]}},"not_run":{}}\n' > tools/ci/test-map.json git add -A && git -c user.name=t -c user.email=t@t commit -q -m base && git tag base git checkout -q -b branch; printf '{"run_id":"r-branch","manifest_sha":"m","cells":[{"cell":"c1","status":"RUNNING","evidence":"tools/ci/test-map.json"}]}\n' > tools/ci/batches/r-branch.json node tools/ci/test-record.mjs --record tools/ci/batches/r-branch.json >/dev/null && git add -A && git -c user.name=t -c user.email=t@t commit -q -m "batch r-branch" @@ -217,7 +245,19 @@ success 4 u push run out=$( cd "$rb" && TIP=$(git rev-parse master) && SHA=$(git rev-parse branch) && BASE=$(git merge-base "$TIP" "$SHA") && BATCHES=$(git diff --name-only --diff-filter=A "$BASE" "$SHA" -- tools/ci/batches/ | grep -E '\.json$') && REGISTRY_PATH=docs/plans/igneum-2.0-test-registry.json && AUTHOR=(-c user.name=t -c user.email=t@t) && export TEST_RECORD_ROOT="$rb" && merge_with_batches "$TIP" "$SHA" "merge with replay" 2>&1 && python3 -c " import json; d=json.load(open('docs/plans/igneum-2.0-test-registry.json')); t={c['id']:c.get('run_id') for s in d['suites'] for c in s['tests']}; print('rows', t)" ) case "$out" in *"'X-1': 'r-branch'"*"'X-2': 'r-master'"*|*"'X-2': 'r-master'"*"'X-1': 'r-branch'"*) ;; *) echo "self-test failed: the batch replay did not land both the branch's row and master's row: $out"; fails=1 ;; esac - [ "$fails" = 0 ] && echo "self-test passed: a GitHub remote is refused with exit 2 while the suspension marker stands and a mirror remote is not; the CI rule binds a GitHub remote only; a landed master is fast-forwarded to every mirror and a refused mirror push is a line, not a failure; a green branch run merges; a red one is refused; an unknown read is waited through and refused only at the deadline; a queued run is waited for with the clock; an unrun branch is pushed once and then waited for; a red master refuses every merge but the declared fix; a registry landing's batches replay onto master's copy at the merge" + # the page race: the branch adds cell c3 to the map (page regenerated), master adds c4 (page regenerated); the merge regenerates the page with both + ( cd "$rb" && cp "$ROOT/tools/ci/test-map-doc.mjs" "$ROOT/tools/ci/test-map-merge.py" tools/ci/ && mkdir -p docs/plans && git checkout -q master && node tools/ci/test-map-doc.mjs >/dev/null 2>&1; git add -A; git -c user.name=t -c user.email=t@t commit -q -m page0; git tag pbase + git checkout -q -b pb; python3 -c "import json; m=json.load(open('tools/ci/test-map.json')); m['cells']['c3']={'command':'z','box_class':'b','fixtures':[],'cases':['X-1']}; json.dump(m,open('tools/ci/test-map.json','w'))"; node tools/ci/test-map-doc.mjs >/dev/null 2>&1; git add -A; git -c user.name=t -c user.email=t@t commit -q -m c3 + git checkout -q master; python3 -c "import json; m=json.load(open('tools/ci/test-map.json')); m['cells']['c4']={'command':'w','box_class':'b','fixtures':[],'cases':['X-2']}; json.dump(m,open('tools/ci/test-map.json','w'))"; node tools/ci/test-map-doc.mjs >/dev/null 2>&1; git add -A; git -c user.name=t -c user.email=t@t commit -q -m c4 ) >/dev/null 2>&1 || { echo "self-test failed: the page-race fixture did not build"; fails=1; } + out=$( cd "$rb" && TIP=$(git rev-parse master) && SHA=$(git rev-parse pb) && BASE=$(git merge-base "$TIP" "$SHA") && BATCHES="" && MAP_CHANGED=1 && MAP_PATH=tools/ci/test-map.json && PAGE_PATH=docs/plans/igneum-2.0-test-harness-map.md && REGISTRY_PATH=docs/plans/igneum-2.0-test-registry.json && AUTHOR=(-c user.name=t -c user.email=t@t) && export TEST_RECORD_ROOT="$rb" && merge_with_batches "$TIP" "$SHA" "merge with page" 2>&1 && grep -c -E '^### c[34]$' docs/plans/igneum-2.0-test-harness-map.md ) + case "$out" in *regenerated*2) ;; *) echo "self-test failed: the merge did not regenerate the page with both sides' cells: $out"; fails=1 ;; esac + push_race "To x + ! [remote rejected] HEAD -> master (failed to update ref) +remote: error: cannot lock ref 'refs/heads/master': is at a but expected b" || { echo "self-test failed: a lost compare-and-swap was not read as a race"; fails=1; } + push_race "pre-push gate: REFUSED. master takes only a commit whose own ci run is green" && { echo "self-test failed: a hook refusal was read as a race"; fails=1; } + push_race " RED 3s no conflict markers in tracked files +error: failed to push some refs" && { echo "self-test failed: a red check was read as a race"; fails=1; } + [ "$fails" = 0 ] && echo "self-test passed: a GitHub remote is refused with exit 2 while the suspension marker stands and a mirror remote is not; the CI rule binds a GitHub remote only; a landed master is fast-forwarded to every mirror and a refused mirror push is a line, not a failure; a green branch run merges; a red one is refused; an unknown read is waited through and refused only at the deadline; a queued run is waited for with the clock; an unrun branch is pushed once and then waited for; a red master refuses every merge but the declared fix; a registry landing's batches replay onto master's copy at the merge; a map change regenerates the harness page at the merge; a push that lost the ref race retries without re-running the hook" exit $fails fi if [ "$SELF_TEST" != 1 ] && github_suspended_refusal "$REMOTE"; then exit 2; fi @@ -251,6 +291,12 @@ bash tools/ci/rule24-crate-gate.sh "$BASE" "$SHA" || { echo "merge-to-master: RE REGISTRY_PATH="${REGISTRY_PATH:-docs/plans/igneum-2.0-test-registry.json}" BATCHES=$(git diff --name-only --diff-filter=A "$BASE" "$SHA" -- tools/ci/batches/ | grep -E '\.json$' || true) RULE26_SKIP_PATHS=""; [ -n "$BATCHES" ] && RULE26_SKIP_PATHS="$REGISTRY_PATH" +# the harness map page is generated from tools/ci/test-map.json (test-map-doc.mjs); a branch that changed the map regenerated the +# whole page, and master's page moves under every lane (8 October 2026, 19:5x UK: the enforced-proving lane lost rule 26's race +# twice on the page alone). The merge regenerates the page from the MERGED map, as it replays batches onto master's registry. +MAP_PATH="${MAP_PATH:-tools/ci/test-map.json}"; PAGE_PATH="${PAGE_PATH:-docs/plans/igneum-2.0-test-harness-map.md}" +MAP_CHANGED=0; git diff --quiet "$BASE" "$SHA" -- "$MAP_PATH" 2>/dev/null || MAP_CHANGED=1 +[ "$MAP_CHANGED" = 1 ] && RULE26_SKIP_PATHS="$RULE26_SKIP_PATHS $PAGE_PATH" # rule 26 (8 October 2026, 17:5x UK): a site/ or docs/ path another lane landed since the branch point is merged, never replaced RULE26_SKIP_PATHS="$RULE26_SKIP_PATHS" bash tools/ci/rule26-no-revert.sh "$BASE" "$SHA" "$REMOTE/master" || { echo "merge-to-master: REFUSED by rule 26 (above)" >&2; exit 1; } # the registry's evidence rules (8 October 2026, 18:4x UK): a PASS carries existing evidence, a touched evidence file moves with its @@ -262,14 +308,16 @@ for i in $(seq 1 "$TRIES"); do W=$(mktemp -d "${TMPDIR:-/tmp}/merge-to-master.XXXXXX"); rmdir "$W" git worktree add -q --detach "$W" "$TIP" if ( cd "$W" && merge_with_batches "$TIP" "$SHA" "Merge $BRANCH ${SHA:0:8} into master ($VERDICT)" ); then - if ( cd "$W" && git push -q "$REMOTE" HEAD:master ); then # on a GitHub remote the hook asks ci-state about ${SHA:0:8} once more + pushout=$( cd "$W" && git push "$REMOTE" HEAD:master ${NOVERIFY:+--no-verify} 2>&1 ) && pushed=1 || pushed=0 + [ "$pushed" = 1 ] || { printf '%s\n' "$pushout" | grep -E 'REFUSED| RED |rejected|error' | head -4 | cut -c1-160; } + if [ "$pushed" = 1 ]; then # on a GitHub remote the hook asks ci-state about ${SHA:0:8} once more git worktree remove --force "$W"; git fetch -q "$REMOTE" master echo "merge-to-master: pushed on try $i: $REMOTE/master $(git log -1 --format='%h %ci' "$REMOTE/master") $(TZ=Europe/London date '+%H:%M %Z')" # the landed master to every other mirror, whichever remote took the landing (8 October 2026, 14:0x UK: a box landing never fanned # out, so build-3 and build-4 cut branches from a tip 23 hours old) mirror_master "$(git rev-parse "$REMOTE/master")" "$(git remote get-url "$REMOTE" 2>/dev/null)"; exit 0 fi - echo "merge-to-master: try $i: the push was rejected (master moved or the hook was red); again" + if push_race "$pushout"; then NOVERIFY=1; echo "merge-to-master: try $i: master moved under the push (the ref's compare-and-swap lost); the hook passed, the next try pushes without re-running it"; else echo "merge-to-master: try $i: the push was refused by the hook or failed; again" >&2; fi else echo "merge-to-master: the merge of $BRANCH onto ${TIP:0:8} does not apply cleanly; resolve on the branch (git merge origin/master) and retry" >&2 git worktree remove --force "$W"; exit 1 diff --git a/tools/ci/pre-push.sh b/tools/ci/pre-push.sh index ba54d5e05..f749c559e 100755 --- a/tools/ci/pre-push.sh +++ b/tools/ci/pre-push.sh @@ -174,6 +174,8 @@ tree_checks() { run "the harness map page is generated from tools/ci/test-map.json and current" node tools/ci/test-map-doc.mjs --check run "P01 part A, the million-vector driver: a clean run is PASS, one wrong hash or one unanswered nonce is FAIL naming it (self-test, a fake worker)" python3 tools/ci/p01-vectors.py --self-test run "the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test)" bash tools/ci/registry-evidence-check.sh --self-test + run "F02 (Review B): the proof-rule test bypass cannot reach a release build: an env read with no cfg guard or under a default feature is red; a release binary carrying the bypass string is red (self-test)" bash tools/ci/proof-rule-bypass-check.sh --self-test + run "the test map merges structurally at a landing: master's cells plus the branch's, minus what the branch removed and master left (self-test)" python3 tools/ci/test-map-merge.py --self-test run "the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first)" bash -c 'node tools/ledger/export-public.mjs --self-test && node tools/ledger/export-public.mjs --check' run "the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first)" node tools/ledger-page.mjs --self-test run "every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026)" bash tools/ci/workflow-timeouts-check.sh --self-test diff --git a/tools/ci/proof-rule-bypass-check.sh b/tools/ci/proof-rule-bypass-check.sh new file mode 100755 index 000000000..d62bb29d8 --- /dev/null +++ b/tools/ci/proof-rule-bypass-check.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# F02 (Review B, 8 October 2026): the proof-rule test bypass (IGNEUM_TEST_SKIP_PROOF_RULE, read in the node fork's +# consensus/src/pipeline/body_processor/body_validation_in_context.rs) must never be compiled into a release build. Two rules: +# source: every occurrence of the bypass name in a .rs file of the fork sits in a file under tests/ or inside an item guarded by +# #[cfg(test)] or #[cfg(feature = "")] / cfg!(feature = "") where is NOT in the crate's default features +# (the guard must appear in the 12 lines above the occurrence, inside the same item) +# binary: a release node binary (igneumd), when given, does not contain the bypass name as a string (strings | grep) +# tools/ci/proof-rule-bypass-check.sh [] exit 0 clean, 1 red (every occurrence named), 2 bad args +# tools/ci/proof-rule-bypass-check.sh --self-test +set -euo pipefail +NAME="${PROOF_RULE_BYPASS_NAME:-IGNEUM_TEST_SKIP_PROOF_RULE}" +HERE="$(cd "$(dirname "$0")" && pwd -P)"; ME="$HERE/$(basename "$0")" +source_rule() { # -> prints "red : " lines; returns 1 when any + local tree="$1" rc=0 f n guard feat crate_toml defaults + while IFS=: read -r f n _; do + [ -n "$f" ] || continue + case "$f" in */tests/*|*/benches/*) continue ;; esac + case "$(sed -n "${n}p" "$f")" in *"//"*"$NAME"*) if ! sed -n "${n}p" "$f" | grep -qE "env::var|env!\(|\"$NAME\""; then continue; fi ;; esac + guard=$(awk -v n="$n" 'NR>=n-12 && NR/dev/null || true) + case "$defaults" in *"\"$feat\""*) echo "red $f:$n guarded by feature \"$feat\", which is in the crate's default features ($crate_toml)"; rc=1 ;; esac + done < <(grep -rn --include='*.rs' -F "$NAME" "$tree" 2>/dev/null || true) + return $rc +} +binary_rule() { # -> 1 when the string is inside + local bin="$1" + if strings "$bin" 2>/dev/null | grep -qF "$NAME"; then echo "red $bin carries the string $NAME: the bypass is compiled in"; return 1; fi + return 0 +} +if [ "${1:-}" = --self-test ]; then + d=$(mktemp -d); trap 'rm -rf "$d"' EXIT; fails=0 + mk() { mkdir -p "$d/$1/src"; printf '[package]\nname = "c"\nversion = "0.1.0"\n[features]\ndefault = [%s]\ntest-bypass = []\n' "$2" > "$d/$1/Cargo.toml"; printf '%s\n' "$3" > "$d/$1/src/lib.rs"; } + mk unguarded '' 'fn f() -> bool { std::env::var("IGNEUM_TEST_SKIP_PROOF_RULE").is_ok() }' + mk guarded '' '#[cfg(feature = "test-bypass")] +fn f() -> bool { std::env::var("IGNEUM_TEST_SKIP_PROOF_RULE").is_ok() } +#[cfg(not(feature = "test-bypass"))] +fn f() -> bool { false }' + mk default-feature '"test-bypass"' '#[cfg(feature = "test-bypass")] +fn f() -> bool { std::env::var("IGNEUM_TEST_SKIP_PROOF_RULE").is_ok() }' + mk cfgtest '' '#[cfg(test)] +mod t { fn f() -> bool { std::env::var("IGNEUM_TEST_SKIP_PROOF_RULE").is_ok() } }' + mk comment-only '' '// the bypass IGNEUM_TEST_SKIP_PROOF_RULE is gone from this crate +fn f() -> bool { false }' + out=$(bash "$ME" "$d/unguarded" 2>&1) && { echo "self-test failed: an unguarded env read passed"; fails=1; }; case "$out" in *"no cfg(test) or cfg(feature) guard"*) ;; *) echo "self-test failed: the unguarded read was not named: $out"; fails=1 ;; esac + bash "$ME" "$d/guarded" >/dev/null 2>&1 || { echo "self-test failed: a read under a non-default feature was refused: $(bash "$ME" "$d/guarded" 2>&1)"; fails=1; } + out=$(bash "$ME" "$d/default-feature" 2>&1) && { echo "self-test failed: a read under a DEFAULT feature passed"; fails=1; }; case "$out" in *"default features"*) ;; *) echo "self-test failed: the default feature was not named: $out"; fails=1 ;; esac + bash "$ME" "$d/cfgtest" >/dev/null 2>&1 || { echo "self-test failed: a read under #[cfg(test)] was refused"; fails=1; } + bash "$ME" "$d/comment-only" >/dev/null 2>&1 || { echo "self-test failed: a comment naming the bypass was refused"; fails=1; } + printf 'ELF\0\0igneumd IGNEUM_TEST_SKIP_PROOF_RULE\0' > "$d/bad.bin"; printf 'ELF\0\0igneumd clean\0' > "$d/good.bin" + out=$(bash "$ME" "$d/guarded" "$d/bad.bin" 2>&1) && { echo "self-test failed: a binary carrying the bypass string passed"; fails=1; }; case "$out" in *"compiled in"*) ;; *) echo "self-test failed: the binary was not named: $out"; fails=1 ;; esac + bash "$ME" "$d/guarded" "$d/good.bin" >/dev/null 2>&1 || { echo "self-test failed: a clean binary was refused"; fails=1; } + [ "$fails" = 0 ] && echo "self-test passed: an env read of the bypass with no guard, or under a default feature, is red and named; a read under cfg(test) or a non-default feature passes; a comment passes; a release binary carrying the bypass string is red, a clean one passes" + exit $fails +fi +[ $# -ge 1 ] || { echo "usage: proof-rule-bypass-check.sh [] | --self-test" >&2; exit 2; } +rc=0; out=$(source_rule "$1") || rc=1 +[ -n "${2:-}" ] && { bout=$(binary_rule "$2") || rc=1; out="$out${bout:+ +$bout}"; } +printf '%s\n' "$out" | sed -n 's/^red /proof-rule-bypass: RED: /p' | grep . || true +[ "$rc" = 0 ] && echo "proof-rule-bypass: every $NAME read is under cfg(test) or a non-default feature${2:+; the release binary carries no bypass string}" +exit $rc diff --git a/tools/ci/review-suite.mjs b/tools/ci/review-suite.mjs new file mode 100644 index 000000000..27128c6f8 --- /dev/null +++ b/tools/ci/review-suite.mjs @@ -0,0 +1,62 @@ +#!/usr/bin/env node +// The REV suite of the acceptance registry: one case per required regression of an external review's findings.json, the owner from +// its dispatch.md table, the finding id and priority carried as fields, status NOT RUN until a lane records a run through the batch +// tools (main through the coordinator, 8 October 2026, 19:5x UK: Review B's 44 regressions). The registry's one structural edit +// per review: generated here, never by hand; --check refuses a registry whose REV suite differs from the generator's output. +// +// node tools/ci/review-suite.mjs --findings --dispatch --prefix REV [--write | --check] +// node tools/ci/review-suite.mjs --self-test +import fs from 'node:fs'; import path from 'node:path'; +const args = process.argv.slice(2); const arg = (n) => { const i = args.indexOf(n); return i >= 0 ? args[i + 1] : undefined; }; +const ROOT = process.env.TEST_RECORD_ROOT || path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..'); +const REG = process.env.TEST_REGISTRY || path.join(ROOT, 'docs/plans/igneum-2.0-test-registry.json'); +function owners(dispatchMd) { // "| F01 title | P0 | owner a, owner b | ..." -> {F01: "owner a, owner b"} + const out = {}; + for (const line of dispatchMd.split('\n')) { + const m = line.match(/^\|\s*(F\d+)\b[^|]*\|\s*([^|]*)\|\s*([^|]*)\|/); if (m) out[m[1]] = m[3].trim(); + } + return out; +} +function suite(findings, dispatchMd, prefix, sourceNote) { + const own = owners(dispatchMd); const tests = []; + for (const f of findings.findings || []) { + (f.required_regressions || []).forEach((line, i) => { + tests.push({ id: `${prefix}-${f.id}-${i + 1}`, title: line, setup: `The regression ${f.id} requires (review finding ${f.id}: ${f.title}).`, steps: [line], + accept: line, evidence: 'The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.', priority: String(f.priority || '').split(' ')[0] || 'P1', + profile: 'P00', cadence: 'Every release candidate', method: 'Automated + independent review', status: 'NOT RUN', source: [f.id], gate: 'Review findings closed', + owner: own[f.id] || 'unassigned', manual_page: null, finding: f.id, finding_title: f.title, finding_priority: f.priority, owner_lane: own[f.id] || 'unassigned', run_status: 'NOT RUN' }); + }); + } + return { code: prefix, title: `${prefix}: the external review's required regressions`, source: sourceNote, gate: 'Review findings closed', owner: 'the owner lanes per the dispatch table', fixtures: ['F0', 'F5'], + summary: `${tests.length} regressions from ${(findings.findings || []).length} findings; each reads NOT RUN until its owner lane records a run`, tests }; +} +function merge(reg, s) { // replace the suite of the same code, keeping live fields of cases that already exist + const old = (reg.suites || []).find((x) => x.code === s.code); const live = new Map((old?.tests || []).map((t) => [t.id, t])); + for (const t of s.tests) { const o = live.get(t.id); if (o) for (const k of ['run_status', 'run_id', 'evidence_path', 'updated', 'evidence_record']) if (k in o) t[k] = o[k]; } + reg.suites = [...(reg.suites || []).filter((x) => x.code !== s.code), s]; return reg; +} +if (args.includes('--self-test')) { + let fails = 0; + const findings = { findings: [{ id: 'F01', title: 'A', priority: 'P0 - blocker', required_regressions: ['r one', 'r two'] }, { id: 'F02', title: 'B', priority: 'P1 - x', required_regressions: ['r three'] }] }; + const dispatch = '| Finding | Priority | Owner | Default |\n|---|---|---|---|\n| F01 A | P0 | lane x, lane y | d |\n| F02 B | P1 | lane z | d |\n'; + const s = suite(findings, dispatch, 'REV', 'test'); + if (!(s.tests.length === 3 && s.tests[0].id === 'REV-F01-1' && s.tests[2].id === 'REV-F02-1')) { console.log(`self-test failed: the ids are not --: ${s.tests.map((t) => t.id)}`); fails = 1; } + if (!(s.tests[0].title === 'r one' && s.tests[0].accept === 'r one')) { console.log('self-test failed: the title and accept are not the regression line verbatim'); fails = 1; } + if (!(s.tests[0].owner_lane === 'lane x, lane y' && s.tests[2].owner_lane === 'lane z')) { console.log(`self-test failed: owners not read from the dispatch table: ${s.tests.map((t) => t.owner_lane)}`); fails = 1; } + if (!(s.tests[0].finding === 'F01' && s.tests[0].priority === 'P0' && s.tests[0].run_status === 'NOT RUN' && s.tests[0].method.includes('Automated'))) { console.log('self-test failed: finding, priority, NOT RUN or method missing'); fails = 1; } + const reg = { suites: [{ code: 'GOV', tests: [] }, { code: 'REV', tests: [{ id: 'REV-F01-1', run_status: 'RUNNING', run_id: 'r9' }] }] }; + const m = merge(JSON.parse(JSON.stringify(reg)), s); const rev = m.suites.find((x) => x.code === 'REV'); + if (!(m.suites.length === 2 && rev.tests.length === 3 && rev.tests[0].run_status === 'RUNNING' && rev.tests[0].run_id === 'r9' && rev.tests[1].run_status === 'NOT RUN')) { console.log('self-test failed: a regenerated suite did not keep the existing case\'s live fields or dropped another suite'); fails = 1; } + if (!fails) console.log('self-test passed: one case per required regression with the id --, the line verbatim as title and accept, the owner from the dispatch table, finding and priority carried, NOT RUN; regenerating keeps live fields and the other suites'); + process.exit(fails); +} +const findings = JSON.parse(fs.readFileSync(arg('--findings'), 'utf8')); const dispatch = fs.readFileSync(arg('--dispatch'), 'utf8'); const prefix = arg('--prefix') || 'REV'; +const s = suite(findings, dispatch, prefix, `${path.relative(ROOT, arg('--findings'))} and ${path.relative(ROOT, arg('--dispatch'))}`); +const reg = JSON.parse(fs.readFileSync(REG, 'utf8')); +if (args.includes('--check')) { + const cur = (reg.suites || []).find((x) => x.code === prefix); const want = merge(JSON.parse(JSON.stringify(reg)), s).suites.find((x) => x.code === prefix); + if (JSON.stringify(cur) !== JSON.stringify(want)) { console.error(`review-suite: the registry's ${prefix} suite differs from the generator's output; run --write and commit`); process.exit(1); } + console.log(`review-suite: the ${prefix} suite matches its findings (${s.tests.length} cases)`); process.exit(0); +} +if (args.includes('--write')) { fs.writeFileSync(REG, JSON.stringify(merge(reg, s), null, 2) + '\n'); console.log(`review-suite: ${prefix} written, ${s.tests.length} cases from ${(findings.findings || []).length} findings`); process.exit(0); } +console.error('usage: review-suite.mjs --findings f --dispatch d [--prefix REV] --write|--check | --self-test'); process.exit(2); diff --git a/tools/ci/test-map-merge.py b/tools/ci/test-map-merge.py new file mode 100755 index 000000000..bfcd9551c --- /dev/null +++ b/tools/ci/test-map-merge.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""A structural three-way merge of tools/ci/test-map.json (8 October 2026, 20:0x UK): two lanes adding cells on adjacent lines +collide as text; as objects they do not. Result = master's map, plus every cell (and not_run entry) the branch added or changed +against the base, minus the cells the branch removed that master left as the base had them. Everything else of the map (title, +registry, rule) is master's. Usage: test-map-merge.py ; --self-test.""" +import json, sys, tempfile, os + +def merge(base, master, branch): + out = json.loads(json.dumps(master)) + for key in ("cells", "not_run"): + b, m, r = base.get(key, {}), master.get(key, {}), branch.get(key, {}) + res = dict(m) + for k, v in r.items(): + if k not in b or b[k] != v: + res[k] = v + for k in b: + if k not in r and k in m and m[k] == b[k]: + del res[k] + out[key] = res + return out + +def self_test(): + fails = 0 + base = {"title": "t", "cells": {"c1": {"a": 1}, "c2": {"a": 2}, "c9": {"a": 9}}, "not_run": {"X-5": "none"}} + master = {"title": "t2", "cells": {"c1": {"a": 1}, "c2": {"a": 2}, "c9": {"a": 9}, "c4": {"a": 4}}, "not_run": {"X-5": "none", "X-6": "m"}} + branch = {"title": "t", "cells": {"c1": {"a": 1}, "c2": {"a": 22}, "c3": {"a": 3}}, "not_run": {}} # adds c3, changes c2, removes c9, clears X-5 + r = merge(base, master, branch) + want_cells = {"c1": {"a": 1}, "c2": {"a": 22}, "c4": {"a": 4}, "c3": {"a": 3}} + if r["cells"] != want_cells: print("self-test failed: cells:", r["cells"]); fails = 1 + if r["not_run"] != {"X-6": "m"}: print("self-test failed: not_run:", r["not_run"]); fails = 1 + if r["title"] != "t2": print("self-test failed: master's other fields not kept"); fails = 1 + # master changed c9 too: the branch's removal does not win + master2 = json.loads(json.dumps(master)); master2["cells"]["c9"] = {"a": 99} + if "c9" not in merge(base, master2, branch)["cells"]: print("self-test failed: a cell master changed was removed by the branch"); fails = 1 + if not fails: print("self-test passed: master's map plus the branch's added and changed cells and not_run entries, minus what the branch removed and master left alone; master's other fields kept") + return fails + +if __name__ == "__main__": + if "--self-test" in sys.argv: sys.exit(self_test()) + base, master, branch, out = (json.load(open(p)) for p in sys.argv[1:4]), None, None, None + b, m, r = base + res = merge(b, m, r) + with open(sys.argv[4], "w") as f: json.dump(res, f, indent=2); f.write("\n") + print(f"test-map-merge: {len(res.get('cells', {}))} cells, {len(res.get('not_run', {}))} NOT RUN reasons") diff --git a/tools/ci/test-record.mjs b/tools/ci/test-record.mjs index f75bd3728..cdaea54e4 100644 --- a/tools/ci/test-record.mjs +++ b/tools/ci/test-record.mjs @@ -10,8 +10,10 @@ // node tools/ci/test-record.mjs --record batch: {run_id, manifest_sha, evidence_dir, cells:[{cell, status, evidence}]} // each cell's case ids come from the map; the registry gains status/run/evidence/manifest // node tools/ci/test-record.mjs --cases the case ids a matrix cell answers (for the matrix scripts' column) +// node tools/ci/test-record.mjs --note "" append a dated note to a suite's notes (a ruling, a review finding's +// disposition); never a case's accept text // node tools/ci/test-record.mjs --self-test -import fs from 'node:fs'; import path from 'node:path'; +import fs from 'node:fs'; import path from 'node:path'; import child_process from 'node:child_process'; const args = process.argv.slice(2); const arg = (n) => { const i = args.indexOf(n); return i >= 0 ? args[i + 1] : undefined; }; const ROOT = process.env.TEST_RECORD_ROOT || path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..'); const REG = process.env.TEST_REGISTRY || path.join(ROOT, 'docs/plans/igneum-2.0-test-registry.json'); @@ -65,15 +67,26 @@ if (args.includes('--self-test')) { if (!(reg.cases[1].run_status === 'NOT RUN' && /corpus/.test(reg.cases[1].evidence_record.reason))) { console.log('self-test failed: an unmapped Automated case did not read NOT RUN with its reason'); fails = 1; } if (reg.cases[2].run_status) { console.log('self-test failed: a manual case was given a run status'); fails = 1; } const regS = { suites: [{ code: 'X', tests: [{ id: 'X-1', method: 'Automated', accept: 'a' }] }] }; if (casesOf(regS).length !== 1) { console.log('self-test failed: the suites/tests registry shape was not read'); fails = 1; } + const regN = { suites: [{ code: 'FIN', tests: [{ id: 'F-1', method: 'Automated', accept: 'keep' }] }] }; fs.writeFileSync(`${d}/regn.json`, JSON.stringify(regN)); + const nr = child_process.spawnSync(process.execPath, [new URL(import.meta.url).pathname, '--note', 'FIN', 'the ruling'], { env: { ...process.env, TEST_REGISTRY: `${d}/regn.json`, TEST_MAP: `${d}/map.json` }, encoding: 'utf8' }); + const regN2 = JSON.parse(fs.readFileSync(`${d}/regn.json`, 'utf8')); + if (!(nr.status === 0 && regN2.suites[0].notes?.length === 1 && regN2.suites[0].notes[0].text === 'the ruling' && regN2.suites[0].tests[0].accept === 'keep')) { console.log(`self-test failed: --note did not append a dated note to the suite and keep the accept text: ${nr.stdout} ${nr.stderr}`); fails = 1; } let threw = false; try { record(reg, map, { run_id: 'r2', manifest_sha: 'x', cells: [{ cell: 'ghost', status: 'PASS' }] }); } catch { threw = true; } if (!threw) { console.log('self-test failed: a batch naming a cell not in the map was accepted'); fails = 1; } fs.rmSync(d, { recursive: true, force: true }); - if (!fails) console.log('self-test passed: a complete map checks; an unknown case id and an unmapped Automated case are refused; a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, leaves every accept text byte-identical, gives an unmapped Automated case NOT RUN with its reason and a manual case nothing; a batch naming an unknown cell is refused'); + if (!fails) console.log('self-test passed: a complete map checks; an unknown case id and an unmapped Automated case are refused; a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, leaves every accept text byte-identical, gives an unmapped Automated case NOT RUN with its reason and a manual case nothing; a batch naming an unknown cell is refused; --note appends a dated note to a suite and never touches an accept text'); process.exit(fails); } const reg = load(REG); const map = load(MAP); if (args.includes('--check')) { const r = check(reg, map); for (const l of r.lines) console.error(`test-record: ${l}`); console.log(`test-record: ${r.automated} Automated cases, ${r.mapped} mapped to cells, ${r.notRun} NOT RUN with a reason${r.bad ? `, ${r.bad} problems` : ''}`); process.exit(r.bad ? 1 : 0); } if (arg('--cases')) { console.log(((map.cells || {})[arg('--cases')]?.cases || []).join(',')); process.exit(0); } +if (arg('--note')) { + const code = arg('--note'); const text = args[args.indexOf('--note') + 2]; const suite = (reg.suites || []).find((s) => s.code === code); + if (!suite || !text) { console.error(`test-record: --note needs a suite code in the registry and a text (got ${code}, ${text ? 'text' : 'no text'})`); process.exit(2); } + const before = acceptSnapshot(reg); suite.notes = suite.notes || []; suite.notes.push({ at: new Date().toISOString(), text }); + if (acceptSnapshot(reg) !== before) { console.error('test-record: REFUSED: the note would change an accept text'); process.exit(1); } + fs.writeFileSync(REG, JSON.stringify(reg, null, 2) + '\n'); console.log(`test-record: note ${suite.notes.length} on ${code}: ${text.slice(0, 80)}`); process.exit(0); +} if (arg('--record')) { const batch = load(arg('--record')); const before = acceptSnapshot(reg); const touched = record(reg, map, batch); if (acceptSnapshot(reg) !== before) { console.error('test-record: REFUSED: the record would change an accept text'); process.exit(1); } From 35feaa17cc89d4f01188bb8ef675453d0c0fc7da Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:07:06 +0000 Subject: [PATCH 2/6] The REV suite: Review B's 44 required regressions in the acceptance registry, and the founder's two rulings as notes tools/ci/review-suite.mjs writes the REV suite from docs/analysis/review-2026-10-08-b/findings.json and dispatch.md: one case per required regression (REV-F01-1 onward), the regression line verbatim as title and accept, status NOT RUN, the owner lane from the dispatch table, the finding id and priority carried as fields; every unmapped case gets a NOT RUN reason in tools/ci/test-map.json naming its owner lane; the gate's check refuses a registry whose REV suite drifts from the findings. The founder's 19:57 rulings on F04 (the recovery lock kept, always labelled recovery) and F14 (the public miner from 2.0.2 without remote jobs; the lab build for our fleet) are dated notes on the FIN, UX and OPS suites through test-record.mjs --note, and resolved fields in F0. The harness page is regenerated. Co-Authored-By: Claude Fable 5.1 --- docs/plans/igneum-2.0-test-harness-map.md | 48 +- docs/plans/igneum-2.0-test-registry.json | 1176 +++++++++++++++++++++ tools/ci/checks.txt | 1 + tools/ci/pre-push.sh | 1 + tools/ci/review-suite-check.sh | 5 + tools/ci/review-suite.mjs | 16 +- tools/ci/test-map.json | 968 +++++++++-------- 7 files changed, 1749 insertions(+), 466 deletions(-) create mode 100755 tools/ci/review-suite-check.sh diff --git a/docs/plans/igneum-2.0-test-harness-map.md b/docs/plans/igneum-2.0-test-harness-map.md index 24e0c15ed..9e6b8d6de 100644 --- a/docs/plans/igneum-2.0-test-harness-map.md +++ b/docs/plans/igneum-2.0-test-harness-map.md @@ -1,6 +1,6 @@ # Igneum 2.0 test harness map -Generated from tools/ci/test-map.json by tools/ci/test-map-doc.mjs; edit the JSON, never this page. Registry: docs/plans/igneum-2.0-test-registry.json (128 cases). +Generated from tools/ci/test-map.json by tools/ci/test-map-doc.mjs; edit the JSON, never this page. Registry: docs/plans/igneum-2.0-test-registry.json (172 cases). Rule: a case maps to a cell only where the cell's tests visibly answer it; coverage names what the cell proves and what remains; a mapped cell's green writes RUNNING, PASS only when coverage is full and the evidence file exists; an automated case with no cell reads NOT RUN with its reason, never PASS by inference. @@ -295,7 +295,51 @@ Rule: a case maps to a cell only where the cell's tests visibly answer it; cover - LEAD-05 Measure control and dependency concentration: observation window - LEAD-06 Complete the reliability observation window: observation window - LEAD-08 Keep leadership claims valid after release: observation window +- REV-F01-1 Valid proof A, warm cache, carried statement B: refuse exactly as a cold node does.: F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map +- REV-F01-2 Run valid/invalid contexts in both orders, concurrently and across cache eviction/restart.: F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map +- REV-F01-3 Change payout, network, kind, program ID and activation context; no accepted misbinding.: F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map +- REV-F01-4 A native two-node test must agree on block validity and payouts despite different cache histories.: F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map +- REV-F02-1 Release build cannot activate test bypass.: F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map +- REV-F02-2 Missing oracle or pinned keys prevents service readiness after enforcement activation.: F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map +- REV-F02-3 Missing proof bytes retry without incorrectly marking a valid block permanently invalid.: F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map +- REV-F03-1 Clean build from one manifest, including the pool and workers, with no unpublished vendor tree.: F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map +- REV-F03-2 Same job context produces identical accepted work in node, CPU reference, CUDA, Metal, OpenCL and pool.: F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map +- REV-F03-3 Cross every scheduled transition with old/new client behavior documented and identical rule identities.: F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map +- REV-F04-1 Native multi-node 40/40/20 partition, equivocation and dust-valid mining on both sides past the window.: F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map +- REV-F04-2 Proof that the chosen recovery guarantee matches the public finality claim; two valid contradictory certificates are a hard failure for strong finality.: F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map +- REV-F04-3 Pause-only resume with historical backfill, missing historical data and all old keys returning.: F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map +- REV-F04-4 Wallet, receipt and oracle consumers distinguish any weaker recovery state.: F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map +- REV-F05-1 Native reference-vs-incremental expression equivalence across all source registers and real instruction updates.: F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map +- REV-F05-2 Full-kernel output equivalence, registers, spills, wall power and accepted throughput across target GPUs.: F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map +- REV-F05-3 Adversary physical design includes prefix caching/recomputation cost; no assumed full 63-read cost on every load.: F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map +- REV-F06-1 Acceptance/reference/emitter evaluate the same activated schedule.: F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map +- REV-F06-2 Full live-dataset census on unseen seeds and the complete v6 pack.: F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map +- REV-F06-3 A failed experimental rule does not silently exhaust generation or bypass the intended resource requirement.: F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map +- REV-F07-1 Same final v6 configuration: mine -> evict -> prove -> aggregate -> submit -> rebuild -> resume; no leaked reservations.: F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map +- REV-F07-2 OOM, process crash and stale work recover without losing wallet state or silently consuming power.: F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map +- REV-F07-3 16 GB+ simultaneous mode only after measured peak plus next-epoch headroom; smaller-card modes labelled separately.: F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map +- REV-F08-1 Report every eligible job outcome, including expired work; a bounded list cannot hide losses.: F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map +- REV-F08-2 Consumer tiers complete and receive payment for declared jobs before claims about income.: F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map +- REV-F08-3 Sustained real workload across class transitions, with restart/retry and no publisher intervention.: F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map +- REV-F09-1 Generate all pass/fail cells directly from the declared inequalities and inputs.: F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map +- REV-F09-2 Independent feasibility and cost evaluation of the strongest modeled SRAM/hybrid opponent.: F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map +- REV-F09-3 GPU owners and entrants remain viable under the approved scenario envelope without assuming chip absence or death.: F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map +- REV-F10-1 Compare exact found nonce/hash sets with full-read mode, including all-hit overflow and zero-hit cases.: F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map +- REV-F10-2 Test stale jobs, high-32 rollover, tail batches and asynchronous buffer reuse.: F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map +- REV-F10-3 Compare production throughput and wall energy, not only the isolated kernel timer.: F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map +- REV-F11-1 Goal switch from an efficiency prior can explore higher core/power when policy allows.: F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map +- REV-F11-2 Driver, workload, dataset, compiler and device changes invalidate certification while retaining optional hints.: F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map +- REV-F11-3 Thermal/error/late-share events revert safely, including process or machine crash.: F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map +- REV-F12-1 Crash before/after broadcast, response timeout, restart before snapshot: no duplicate payment or silent debt loss.: F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map +- REV-F12-2 Same signed transaction retried, fee replacement reconciled by intent, not a new payment.: F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map +- REV-F12-3 Receipt reorg and finality pause leave correct pending obligations.: F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map +- REV-F13-1 Repeated authorization rejected or atomically replaces and cleans prior state.: F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map +- REV-F13-2 Oversized unterminated frame rejected within fixed memory/time budget.: F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map +- REV-F13-3 Slow clients and invalid share floods cannot grow unbounded member, nonce or outgoing state.: F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map +- REV-F14-1 Public build has no default arbitrary remote execution and a documented least-privilege boundary.: F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map +- REV-F14-2 Automatic updates off remains off for urgent manifests until explicit action.: F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map +- REV-F14-3 A compromised fleet/update signing key cannot silently acquire wallet access or activate a consensus change.: F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map ## Count -109 automated cases: 45 mapped to a cell, 67 NOT RUN with a reason. +153 automated cases: 45 mapped to a cell, 111 NOT RUN with a reason. diff --git a/docs/plans/igneum-2.0-test-registry.json b/docs/plans/igneum-2.0-test-registry.json index 5a18193c6..d3d105cfb 100644 --- a/docs/plans/igneum-2.0-test-registry.json +++ b/docs/plans/igneum-2.0-test-registry.json @@ -3646,6 +3646,12 @@ "at": "2026-10-08T18:38:45.233Z" } } + ], + "notes": [ + { + "at": "2026-10-08T19:06:34.012Z", + "text": "F04 (Review B), the founder's ruling 8 October 19:57 UK: the recovery lock is kept and is always labelled 'recovery', never 'final', on every surface (the checkpoint field, the explorer, receipts, the light client, the oracle, the site)" + } ] }, { @@ -4267,6 +4273,12 @@ "at": "2026-10-08T19:06:33.513Z" } } + ], + "notes": [ + { + "at": "2026-10-08T19:06:34.181Z", + "text": "F14 (Review B), the founder's ruling 8 October 19:57 UK: the public miner ships from 2.0.2 without remote jobs; our own fleet runs the lab build with its own signing root" + } ] }, { @@ -4600,6 +4612,12 @@ "at": "2026-10-08T18:28:32.408Z" } } + ], + "notes": [ + { + "at": "2026-10-08T19:06:34.094Z", + "text": "F14 (Review B), the founder's ruling 8 October 19:57 UK: the public miner ships from 2.0.2 without remote jobs; our own fleet runs the lab build with its own signing root" + } ] }, { @@ -5249,6 +5267,1164 @@ } } ] + }, + { + "code": "REV", + "title": "REV: the external review's required regressions", + "source": "docs/analysis/review-2026-10-08-b/findings.json and docs/analysis/review-2026-10-08-b/dispatch.md", + "gate": "Review findings closed", + "owner": "the owner lanes per the dispatch table", + "fixtures": [ + "F0", + "F5" + ], + "summary": "44 regressions from 14 findings; each reads NOT RUN until its owner lane records a run", + "tests": [ + { + "id": "REV-F01-1", + "title": "Valid proof A, warm cache, carried statement B: refuse exactly as a cold node does.", + "setup": "The regression F01 requires (review finding F01: Proof-verdict cache omits the statement being verified).", + "steps": [ + "Valid proof A, warm cache, carried statement B: refuse exactly as a cold node does." + ], + "accept": "Valid proof A, warm cache, carried statement B: refuse exactly as a cold node does.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F01" + ], + "gate": "Review findings closed", + "owner": "proving lane, node lane", + "manual_page": null, + "finding": "F01", + "finding_title": "Proof-verdict cache omits the statement being verified", + "finding_priority": "P0 - public/value-bearing release blocker", + "owner_lane": "proving lane, node lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F01-2", + "title": "Run valid/invalid contexts in both orders, concurrently and across cache eviction/restart.", + "setup": "The regression F01 requires (review finding F01: Proof-verdict cache omits the statement being verified).", + "steps": [ + "Run valid/invalid contexts in both orders, concurrently and across cache eviction/restart." + ], + "accept": "Run valid/invalid contexts in both orders, concurrently and across cache eviction/restart.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F01" + ], + "gate": "Review findings closed", + "owner": "proving lane, node lane", + "manual_page": null, + "finding": "F01", + "finding_title": "Proof-verdict cache omits the statement being verified", + "finding_priority": "P0 - public/value-bearing release blocker", + "owner_lane": "proving lane, node lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F01-3", + "title": "Change payout, network, kind, program ID and activation context; no accepted misbinding.", + "setup": "The regression F01 requires (review finding F01: Proof-verdict cache omits the statement being verified).", + "steps": [ + "Change payout, network, kind, program ID and activation context; no accepted misbinding." + ], + "accept": "Change payout, network, kind, program ID and activation context; no accepted misbinding.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F01" + ], + "gate": "Review findings closed", + "owner": "proving lane, node lane", + "manual_page": null, + "finding": "F01", + "finding_title": "Proof-verdict cache omits the statement being verified", + "finding_priority": "P0 - public/value-bearing release blocker", + "owner_lane": "proving lane, node lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F01-4", + "title": "A native two-node test must agree on block validity and payouts despite different cache histories.", + "setup": "The regression F01 requires (review finding F01: Proof-verdict cache omits the statement being verified).", + "steps": [ + "A native two-node test must agree on block validity and payouts despite different cache histories." + ], + "accept": "A native two-node test must agree on block validity and payouts despite different cache histories.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F01" + ], + "gate": "Review findings closed", + "owner": "proving lane, node lane", + "manual_page": null, + "finding": "F01", + "finding_title": "Proof-verdict cache omits the statement being verified", + "finding_priority": "P0 - public/value-bearing release blocker", + "owner_lane": "proving lane, node lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F02-1", + "title": "Release build cannot activate test bypass.", + "setup": "The regression F02 requires (review finding F02: Proof-rule infrastructure can fail open).", + "steps": [ + "Release build cannot activate test bypass." + ], + "accept": "Release build cannot activate test bypass.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F02" + ], + "gate": "Review findings closed", + "owner": "proving lane, CI steward", + "manual_page": null, + "finding": "F02", + "finding_title": "Proof-rule infrastructure can fail open", + "finding_priority": "P0 - release configuration blocker", + "owner_lane": "proving lane, CI steward", + "run_status": "NOT RUN" + }, + { + "id": "REV-F02-2", + "title": "Missing oracle or pinned keys prevents service readiness after enforcement activation.", + "setup": "The regression F02 requires (review finding F02: Proof-rule infrastructure can fail open).", + "steps": [ + "Missing oracle or pinned keys prevents service readiness after enforcement activation." + ], + "accept": "Missing oracle or pinned keys prevents service readiness after enforcement activation.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F02" + ], + "gate": "Review findings closed", + "owner": "proving lane, CI steward", + "manual_page": null, + "finding": "F02", + "finding_title": "Proof-rule infrastructure can fail open", + "finding_priority": "P0 - release configuration blocker", + "owner_lane": "proving lane, CI steward", + "run_status": "NOT RUN" + }, + { + "id": "REV-F02-3", + "title": "Missing proof bytes retry without incorrectly marking a valid block permanently invalid.", + "setup": "The regression F02 requires (review finding F02: Proof-rule infrastructure can fail open).", + "steps": [ + "Missing proof bytes retry without incorrectly marking a valid block permanently invalid." + ], + "accept": "Missing proof bytes retry without incorrectly marking a valid block permanently invalid.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F02" + ], + "gate": "Review findings closed", + "owner": "proving lane, CI steward", + "manual_page": null, + "finding": "F02", + "finding_title": "Proof-rule infrastructure can fail open", + "finding_priority": "P0 - release configuration blocker", + "owner_lane": "proving lane, CI steward", + "run_status": "NOT RUN" + }, + { + "id": "REV-F03-1", + "title": "Clean build from one manifest, including the pool and workers, with no unpublished vendor tree.", + "setup": "The regression F03 requires (review finding F03: The bundle contains a v6 candidate, not a demonstrated integrated v6 release).", + "steps": [ + "Clean build from one manifest, including the pool and workers, with no unpublished vendor tree." + ], + "accept": "Clean build from one manifest, including the pool and workers, with no unpublished vendor tree.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F03" + ], + "gate": "Review findings closed", + "owner": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", + "manual_page": null, + "finding": "F03", + "finding_title": "The bundle contains a v6 candidate, not a demonstrated integrated v6 release", + "finding_priority": "P0 - freeze/integration blocker", + "owner_lane": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F03-2", + "title": "Same job context produces identical accepted work in node, CPU reference, CUDA, Metal, OpenCL and pool.", + "setup": "The regression F03 requires (review finding F03: The bundle contains a v6 candidate, not a demonstrated integrated v6 release).", + "steps": [ + "Same job context produces identical accepted work in node, CPU reference, CUDA, Metal, OpenCL and pool." + ], + "accept": "Same job context produces identical accepted work in node, CPU reference, CUDA, Metal, OpenCL and pool.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F03" + ], + "gate": "Review findings closed", + "owner": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", + "manual_page": null, + "finding": "F03", + "finding_title": "The bundle contains a v6 candidate, not a demonstrated integrated v6 release", + "finding_priority": "P0 - freeze/integration blocker", + "owner_lane": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F03-3", + "title": "Cross every scheduled transition with old/new client behavior documented and identical rule identities.", + "setup": "The regression F03 requires (review finding F03: The bundle contains a v6 candidate, not a demonstrated integrated v6 release).", + "steps": [ + "Cross every scheduled transition with old/new client behavior documented and identical rule identities." + ], + "accept": "Cross every scheduled transition with old/new client behavior documented and identical rule identities.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F03" + ], + "gate": "Review findings closed", + "owner": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", + "manual_page": null, + "finding": "F03", + "finding_title": "The bundle contains a v6 candidate, not a demonstrated integrated v6 release", + "finding_priority": "P0 - freeze/integration blocker", + "owner_lane": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F04-1", + "title": "Native multi-node 40/40/20 partition, equivocation and dust-valid mining on both sides past the window.", + "setup": "The regression F04 requires (review finding F04: Finality v4 recovery deliberately has a weaker safety boundary).", + "steps": [ + "Native multi-node 40/40/20 partition, equivocation and dust-valid mining on both sides past the window." + ], + "accept": "Native multi-node 40/40/20 partition, equivocation and dust-valid mining on both sides past the window.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F04" + ], + "gate": "Review findings closed", + "owner": "node lane, reference apps, site (explorer)", + "manual_page": null, + "finding": "F04", + "finding_title": "Finality v4 recovery deliberately has a weaker safety boundary", + "finding_priority": "P0 - finality guarantee decision", + "owner_lane": "node lane, reference apps, site (explorer)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F04-2", + "title": "Proof that the chosen recovery guarantee matches the public finality claim; two valid contradictory certificates are a hard failure for strong finality.", + "setup": "The regression F04 requires (review finding F04: Finality v4 recovery deliberately has a weaker safety boundary).", + "steps": [ + "Proof that the chosen recovery guarantee matches the public finality claim; two valid contradictory certificates are a hard failure for strong finality." + ], + "accept": "Proof that the chosen recovery guarantee matches the public finality claim; two valid contradictory certificates are a hard failure for strong finality.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F04" + ], + "gate": "Review findings closed", + "owner": "node lane, reference apps, site (explorer)", + "manual_page": null, + "finding": "F04", + "finding_title": "Finality v4 recovery deliberately has a weaker safety boundary", + "finding_priority": "P0 - finality guarantee decision", + "owner_lane": "node lane, reference apps, site (explorer)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F04-3", + "title": "Pause-only resume with historical backfill, missing historical data and all old keys returning.", + "setup": "The regression F04 requires (review finding F04: Finality v4 recovery deliberately has a weaker safety boundary).", + "steps": [ + "Pause-only resume with historical backfill, missing historical data and all old keys returning." + ], + "accept": "Pause-only resume with historical backfill, missing historical data and all old keys returning.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F04" + ], + "gate": "Review findings closed", + "owner": "node lane, reference apps, site (explorer)", + "manual_page": null, + "finding": "F04", + "finding_title": "Finality v4 recovery deliberately has a weaker safety boundary", + "finding_priority": "P0 - finality guarantee decision", + "owner_lane": "node lane, reference apps, site (explorer)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F04-4", + "title": "Wallet, receipt and oracle consumers distinguish any weaker recovery state.", + "setup": "The regression F04 requires (review finding F04: Finality v4 recovery deliberately has a weaker safety boundary).", + "steps": [ + "Wallet, receipt and oracle consumers distinguish any weaker recovery state." + ], + "accept": "Wallet, receipt and oracle consumers distinguish any weaker recovery state.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P0", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F04" + ], + "gate": "Review findings closed", + "owner": "node lane, reference apps, site (explorer)", + "manual_page": null, + "finding": "F04", + "finding_title": "Finality v4 recovery deliberately has a weaker safety boundary", + "finding_priority": "P0 - finality guarantee decision", + "owner_lane": "node lane, reference apps, site (explorer)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F05-1", + "title": "Native reference-vs-incremental expression equivalence across all source registers and real instruction updates.", + "setup": "The regression F05 requires (review finding F05: reg64 address coupling has an exact incremental alternative).", + "steps": [ + "Native reference-vs-incremental expression equivalence across all source registers and real instruction updates." + ], + "accept": "Native reference-vs-incremental expression equivalence across all source registers and real instruction updates.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F05" + ], + "gate": "Review findings closed", + "owner": "hash lane, adversary lane, floor lane 3", + "manual_page": null, + "finding": "F05", + "finding_title": "reg64 address coupling has an exact incremental alternative", + "finding_priority": "P1 - adversarial hardware evaluation", + "owner_lane": "hash lane, adversary lane, floor lane 3", + "run_status": "NOT RUN" + }, + { + "id": "REV-F05-2", + "title": "Full-kernel output equivalence, registers, spills, wall power and accepted throughput across target GPUs.", + "setup": "The regression F05 requires (review finding F05: reg64 address coupling has an exact incremental alternative).", + "steps": [ + "Full-kernel output equivalence, registers, spills, wall power and accepted throughput across target GPUs." + ], + "accept": "Full-kernel output equivalence, registers, spills, wall power and accepted throughput across target GPUs.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F05" + ], + "gate": "Review findings closed", + "owner": "hash lane, adversary lane, floor lane 3", + "manual_page": null, + "finding": "F05", + "finding_title": "reg64 address coupling has an exact incremental alternative", + "finding_priority": "P1 - adversarial hardware evaluation", + "owner_lane": "hash lane, adversary lane, floor lane 3", + "run_status": "NOT RUN" + }, + { + "id": "REV-F05-3", + "title": "Adversary physical design includes prefix caching/recomputation cost; no assumed full 63-read cost on every load.", + "setup": "The regression F05 requires (review finding F05: reg64 address coupling has an exact incremental alternative).", + "steps": [ + "Adversary physical design includes prefix caching/recomputation cost; no assumed full 63-read cost on every load." + ], + "accept": "Adversary physical design includes prefix caching/recomputation cost; no assumed full 63-read cost on every load.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F05" + ], + "gate": "Review findings closed", + "owner": "hash lane, adversary lane, floor lane 3", + "manual_page": null, + "finding": "F05", + "finding_title": "reg64 address coupling has an exact incremental alternative", + "finding_priority": "P1 - adversarial hardware evaluation", + "owner_lane": "hash lane, adversary lane, floor lane 3", + "run_status": "NOT RUN" + }, + { + "id": "REV-F06-1", + "title": "Acceptance/reference/emitter evaluate the same activated schedule.", + "setup": "The regression F06 requires (review finding F06: The v6 acceptance and census gates are not complete for the final execution).", + "steps": [ + "Acceptance/reference/emitter evaluate the same activated schedule." + ], + "accept": "Acceptance/reference/emitter evaluate the same activated schedule.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F06" + ], + "gate": "Review findings closed", + "owner": "hash lane, research lane D", + "manual_page": null, + "finding": "F06", + "finding_title": "The v6 acceptance and census gates are not complete for the final execution", + "finding_priority": "P1 - freeze blocker", + "owner_lane": "hash lane, research lane D", + "run_status": "NOT RUN" + }, + { + "id": "REV-F06-2", + "title": "Full live-dataset census on unseen seeds and the complete v6 pack.", + "setup": "The regression F06 requires (review finding F06: The v6 acceptance and census gates are not complete for the final execution).", + "steps": [ + "Full live-dataset census on unseen seeds and the complete v6 pack." + ], + "accept": "Full live-dataset census on unseen seeds and the complete v6 pack.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F06" + ], + "gate": "Review findings closed", + "owner": "hash lane, research lane D", + "manual_page": null, + "finding": "F06", + "finding_title": "The v6 acceptance and census gates are not complete for the final execution", + "finding_priority": "P1 - freeze blocker", + "owner_lane": "hash lane, research lane D", + "run_status": "NOT RUN" + }, + { + "id": "REV-F06-3", + "title": "A failed experimental rule does not silently exhaust generation or bypass the intended resource requirement.", + "setup": "The regression F06 requires (review finding F06: The v6 acceptance and census gates are not complete for the final execution).", + "steps": [ + "A failed experimental rule does not silently exhaust generation or bypass the intended resource requirement." + ], + "accept": "A failed experimental rule does not silently exhaust generation or bypass the intended resource requirement.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F06" + ], + "gate": "Review findings closed", + "owner": "hash lane, research lane D", + "manual_page": null, + "finding": "F06", + "finding_title": "The v6 acceptance and census gates are not complete for the final execution", + "finding_priority": "P1 - freeze blocker", + "owner_lane": "hash lane, research lane D", + "run_status": "NOT RUN" + }, + { + "id": "REV-F07-1", + "title": "Same final v6 configuration: mine -> evict -> prove -> aggregate -> submit -> rebuild -> resume; no leaked reservations.", + "setup": "The regression F07 requires (review finding F07: VRAM admission and proving deadlines need one operator-level scheduler).", + "steps": [ + "Same final v6 configuration: mine -> evict -> prove -> aggregate -> submit -> rebuild -> resume; no leaked reservations." + ], + "accept": "Same final v6 configuration: mine -> evict -> prove -> aggregate -> submit -> rebuild -> resume; no leaked reservations.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F07" + ], + "gate": "Review findings closed", + "owner": "app lane, fleet lane", + "manual_page": null, + "finding": "F07", + "finding_title": "VRAM admission and proving deadlines need one operator-level scheduler", + "finding_priority": "P1 - miner economics and reliability", + "owner_lane": "app lane, fleet lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F07-2", + "title": "OOM, process crash and stale work recover without losing wallet state or silently consuming power.", + "setup": "The regression F07 requires (review finding F07: VRAM admission and proving deadlines need one operator-level scheduler).", + "steps": [ + "OOM, process crash and stale work recover without losing wallet state or silently consuming power." + ], + "accept": "OOM, process crash and stale work recover without losing wallet state or silently consuming power.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F07" + ], + "gate": "Review findings closed", + "owner": "app lane, fleet lane", + "manual_page": null, + "finding": "F07", + "finding_title": "VRAM admission and proving deadlines need one operator-level scheduler", + "finding_priority": "P1 - miner economics and reliability", + "owner_lane": "app lane, fleet lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F07-3", + "title": "16 GB+ simultaneous mode only after measured peak plus next-epoch headroom; smaller-card modes labelled separately.", + "setup": "The regression F07 requires (review finding F07: VRAM admission and proving deadlines need one operator-level scheduler).", + "steps": [ + "16 GB+ simultaneous mode only after measured peak plus next-epoch headroom; smaller-card modes labelled separately." + ], + "accept": "16 GB+ simultaneous mode only after measured peak plus next-epoch headroom; smaller-card modes labelled separately.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F07" + ], + "gate": "Review findings closed", + "owner": "app lane, fleet lane", + "manual_page": null, + "finding": "F07", + "finding_title": "VRAM admission and proving deadlines need one operator-level scheduler", + "finding_priority": "P1 - miner economics and reliability", + "owner_lane": "app lane, fleet lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F08-1", + "title": "Report every eligible job outcome, including expired work; a bounded list cannot hide losses.", + "setup": "The regression F08 requires (review finding F08: The proving pipeline reports waste and deadline censoring, not sustained capacity).", + "steps": [ + "Report every eligible job outcome, including expired work; a bounded list cannot hide losses." + ], + "accept": "Report every eligible job outcome, including expired work; a bounded list cannot hide losses.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F08" + ], + "gate": "Review findings closed", + "owner": "proving lane, fleet lane, site (ops page)", + "manual_page": null, + "finding": "F08", + "finding_title": "The proving pipeline reports waste and deadline censoring, not sustained capacity", + "finding_priority": "P1 - proving product gate", + "owner_lane": "proving lane, fleet lane, site (ops page)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F08-2", + "title": "Consumer tiers complete and receive payment for declared jobs before claims about income.", + "setup": "The regression F08 requires (review finding F08: The proving pipeline reports waste and deadline censoring, not sustained capacity).", + "steps": [ + "Consumer tiers complete and receive payment for declared jobs before claims about income." + ], + "accept": "Consumer tiers complete and receive payment for declared jobs before claims about income.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F08" + ], + "gate": "Review findings closed", + "owner": "proving lane, fleet lane, site (ops page)", + "manual_page": null, + "finding": "F08", + "finding_title": "The proving pipeline reports waste and deadline censoring, not sustained capacity", + "finding_priority": "P1 - proving product gate", + "owner_lane": "proving lane, fleet lane, site (ops page)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F08-3", + "title": "Sustained real workload across class transitions, with restart/retry and no publisher intervention.", + "setup": "The regression F08 requires (review finding F08: The proving pipeline reports waste and deadline censoring, not sustained capacity).", + "steps": [ + "Sustained real workload across class transitions, with restart/retry and no publisher intervention." + ], + "accept": "Sustained real workload across class transitions, with restart/retry and no publisher intervention.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F08" + ], + "gate": "Review findings closed", + "owner": "proving lane, fleet lane, site (ops page)", + "manual_page": null, + "finding": "F08", + "finding_title": "The proving pipeline reports waste and deadline censoring, not sustained capacity", + "finding_priority": "P1 - proving product gate", + "owner_lane": "proving lane, fleet lane, site (ops page)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F09-1", + "title": "Generate all pass/fail cells directly from the declared inequalities and inputs.", + "setup": "The regression F09 requires (review finding F09: The economic model explicitly retains a failed specialist case).", + "steps": [ + "Generate all pass/fail cells directly from the declared inequalities and inputs." + ], + "accept": "Generate all pass/fail cells directly from the declared inequalities and inputs.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F09" + ], + "gate": "Review findings closed", + "owner": "research lane, floor lane 3, coordinator", + "manual_page": null, + "finding": "F09", + "finding_title": "The economic model explicitly retains a failed specialist case", + "finding_priority": "P1 - founding claim not yet earned", + "owner_lane": "research lane, floor lane 3, coordinator", + "run_status": "NOT RUN" + }, + { + "id": "REV-F09-2", + "title": "Independent feasibility and cost evaluation of the strongest modeled SRAM/hybrid opponent.", + "setup": "The regression F09 requires (review finding F09: The economic model explicitly retains a failed specialist case).", + "steps": [ + "Independent feasibility and cost evaluation of the strongest modeled SRAM/hybrid opponent." + ], + "accept": "Independent feasibility and cost evaluation of the strongest modeled SRAM/hybrid opponent.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F09" + ], + "gate": "Review findings closed", + "owner": "research lane, floor lane 3, coordinator", + "manual_page": null, + "finding": "F09", + "finding_title": "The economic model explicitly retains a failed specialist case", + "finding_priority": "P1 - founding claim not yet earned", + "owner_lane": "research lane, floor lane 3, coordinator", + "run_status": "NOT RUN" + }, + { + "id": "REV-F09-3", + "title": "GPU owners and entrants remain viable under the approved scenario envelope without assuming chip absence or death.", + "setup": "The regression F09 requires (review finding F09: The economic model explicitly retains a failed specialist case).", + "steps": [ + "GPU owners and entrants remain viable under the approved scenario envelope without assuming chip absence or death." + ], + "accept": "GPU owners and entrants remain viable under the approved scenario envelope without assuming chip absence or death.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F09" + ], + "gate": "Review findings closed", + "owner": "research lane, floor lane 3, coordinator", + "manual_page": null, + "finding": "F09", + "finding_title": "The economic model explicitly retains a failed specialist case", + "finding_priority": "P1 - founding claim not yet earned", + "owner_lane": "research lane, floor lane 3, coordinator", + "run_status": "NOT RUN" + }, + { + "id": "REV-F10-1", + "title": "Compare exact found nonce/hash sets with full-read mode, including all-hit overflow and zero-hit cases.", + "setup": "The regression F10 requires (review finding F10: CUDA production readback has an existing OpenCL optimization to borrow).", + "steps": [ + "Compare exact found nonce/hash sets with full-read mode, including all-hit overflow and zero-hit cases." + ], + "accept": "Compare exact found nonce/hash sets with full-read mode, including all-hit overflow and zero-hit cases.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P2", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F10" + ], + "gate": "Review findings closed", + "owner": "worker lane (new)", + "manual_page": null, + "finding": "F10", + "finding_title": "CUDA production readback has an existing OpenCL optimization to borrow", + "finding_priority": "P2 - byte-preserving performance experiment", + "owner_lane": "worker lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F10-2", + "title": "Test stale jobs, high-32 rollover, tail batches and asynchronous buffer reuse.", + "setup": "The regression F10 requires (review finding F10: CUDA production readback has an existing OpenCL optimization to borrow).", + "steps": [ + "Test stale jobs, high-32 rollover, tail batches and asynchronous buffer reuse." + ], + "accept": "Test stale jobs, high-32 rollover, tail batches and asynchronous buffer reuse.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P2", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F10" + ], + "gate": "Review findings closed", + "owner": "worker lane (new)", + "manual_page": null, + "finding": "F10", + "finding_title": "CUDA production readback has an existing OpenCL optimization to borrow", + "finding_priority": "P2 - byte-preserving performance experiment", + "owner_lane": "worker lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F10-3", + "title": "Compare production throughput and wall energy, not only the isolated kernel timer.", + "setup": "The regression F10 requires (review finding F10: CUDA production readback has an existing OpenCL optimization to borrow).", + "steps": [ + "Compare production throughput and wall energy, not only the isolated kernel timer." + ], + "accept": "Compare production throughput and wall energy, not only the isolated kernel timer.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P2", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F10" + ], + "gate": "Review findings closed", + "owner": "worker lane (new)", + "manual_page": null, + "finding": "F10", + "finding_title": "CUDA production readback has an existing OpenCL optimization to borrow", + "finding_priority": "P2 - byte-preserving performance experiment", + "owner_lane": "worker lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F11-1", + "title": "Goal switch from an efficiency prior can explore higher core/power when policy allows.", + "setup": "The regression F11 requires (review finding F11: Ember needs workload-aware identity and objective-aware search).", + "steps": [ + "Goal switch from an efficiency prior can explore higher core/power when policy allows." + ], + "accept": "Goal switch from an efficiency prior can explore higher core/power when policy allows.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P2", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F11" + ], + "gate": "Review findings closed", + "owner": "Ember lane (new)", + "manual_page": null, + "finding": "F11", + "finding_title": "Ember needs workload-aware identity and objective-aware search", + "finding_priority": "P2 - product performance", + "owner_lane": "Ember lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F11-2", + "title": "Driver, workload, dataset, compiler and device changes invalidate certification while retaining optional hints.", + "setup": "The regression F11 requires (review finding F11: Ember needs workload-aware identity and objective-aware search).", + "steps": [ + "Driver, workload, dataset, compiler and device changes invalidate certification while retaining optional hints." + ], + "accept": "Driver, workload, dataset, compiler and device changes invalidate certification while retaining optional hints.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P2", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F11" + ], + "gate": "Review findings closed", + "owner": "Ember lane (new)", + "manual_page": null, + "finding": "F11", + "finding_title": "Ember needs workload-aware identity and objective-aware search", + "finding_priority": "P2 - product performance", + "owner_lane": "Ember lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F11-3", + "title": "Thermal/error/late-share events revert safely, including process or machine crash.", + "setup": "The regression F11 requires (review finding F11: Ember needs workload-aware identity and objective-aware search).", + "steps": [ + "Thermal/error/late-share events revert safely, including process or machine crash." + ], + "accept": "Thermal/error/late-share events revert safely, including process or machine crash.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P2", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F11" + ], + "gate": "Review findings closed", + "owner": "Ember lane (new)", + "manual_page": null, + "finding": "F11", + "finding_title": "Ember needs workload-aware identity and objective-aware search", + "finding_priority": "P2 - product performance", + "owner_lane": "Ember lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F12-1", + "title": "Crash before/after broadcast, response timeout, restart before snapshot: no duplicate payment or silent debt loss.", + "setup": "The regression F12 requires (review finding F12: Pool payouts have a broadcast-before-durable-intent window).", + "steps": [ + "Crash before/after broadcast, response timeout, restart before snapshot: no duplicate payment or silent debt loss." + ], + "accept": "Crash before/after broadcast, response timeout, restart before snapshot: no duplicate payment or silent debt loss.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F12" + ], + "gate": "Review findings closed", + "owner": "pool lane (new)", + "manual_page": null, + "finding": "F12", + "finding_title": "Pool payouts have a broadcast-before-durable-intent window", + "finding_priority": "P1 - payment integrity", + "owner_lane": "pool lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F12-2", + "title": "Same signed transaction retried, fee replacement reconciled by intent, not a new payment.", + "setup": "The regression F12 requires (review finding F12: Pool payouts have a broadcast-before-durable-intent window).", + "steps": [ + "Same signed transaction retried, fee replacement reconciled by intent, not a new payment." + ], + "accept": "Same signed transaction retried, fee replacement reconciled by intent, not a new payment.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F12" + ], + "gate": "Review findings closed", + "owner": "pool lane (new)", + "manual_page": null, + "finding": "F12", + "finding_title": "Pool payouts have a broadcast-before-durable-intent window", + "finding_priority": "P1 - payment integrity", + "owner_lane": "pool lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F12-3", + "title": "Receipt reorg and finality pause leave correct pending obligations.", + "setup": "The regression F12 requires (review finding F12: Pool payouts have a broadcast-before-durable-intent window).", + "steps": [ + "Receipt reorg and finality pause leave correct pending obligations." + ], + "accept": "Receipt reorg and finality pause leave correct pending obligations.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F12" + ], + "gate": "Review findings closed", + "owner": "pool lane (new)", + "manual_page": null, + "finding": "F12", + "finding_title": "Pool payouts have a broadcast-before-durable-intent window", + "finding_priority": "P1 - payment integrity", + "owner_lane": "pool lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F13-1", + "title": "Repeated authorization rejected or atomically replaces and cleans prior state.", + "setup": "The regression F13 requires (review finding F13: Pool admission and membership need bounded resources).", + "steps": [ + "Repeated authorization rejected or atomically replaces and cleans prior state." + ], + "accept": "Repeated authorization rejected or atomically replaces and cleans prior state.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F13" + ], + "gate": "Review findings closed", + "owner": "pool lane (new)", + "manual_page": null, + "finding": "F13", + "finding_title": "Pool admission and membership need bounded resources", + "finding_priority": "P1 - service resilience", + "owner_lane": "pool lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F13-2", + "title": "Oversized unterminated frame rejected within fixed memory/time budget.", + "setup": "The regression F13 requires (review finding F13: Pool admission and membership need bounded resources).", + "steps": [ + "Oversized unterminated frame rejected within fixed memory/time budget." + ], + "accept": "Oversized unterminated frame rejected within fixed memory/time budget.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F13" + ], + "gate": "Review findings closed", + "owner": "pool lane (new)", + "manual_page": null, + "finding": "F13", + "finding_title": "Pool admission and membership need bounded resources", + "finding_priority": "P1 - service resilience", + "owner_lane": "pool lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F13-3", + "title": "Slow clients and invalid share floods cannot grow unbounded member, nonce or outgoing state.", + "setup": "The regression F13 requires (review finding F13: Pool admission and membership need bounded resources).", + "steps": [ + "Slow clients and invalid share floods cannot grow unbounded member, nonce or outgoing state." + ], + "accept": "Slow clients and invalid share floods cannot grow unbounded member, nonce or outgoing state.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F13" + ], + "gate": "Review findings closed", + "owner": "pool lane (new)", + "manual_page": null, + "finding": "F13", + "finding_title": "Pool admission and membership need bounded resources", + "finding_priority": "P1 - service resilience", + "owner_lane": "pool lane (new)", + "run_status": "NOT RUN" + }, + { + "id": "REV-F14-1", + "title": "Public build has no default arbitrary remote execution and a documented least-privilege boundary.", + "setup": "The regression F14 requires (review finding F14: Developer fleet control must not silently become the public client trust model).", + "steps": [ + "Public build has no default arbitrary remote execution and a documented least-privilege boundary." + ], + "accept": "Public build has no default arbitrary remote execution and a documented least-privilege boundary.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F14" + ], + "gate": "Review findings closed", + "owner": "app lane, relay lane", + "manual_page": null, + "finding": "F14", + "finding_title": "Developer fleet control must not silently become the public client trust model", + "finding_priority": "P1 - public client/independence gate", + "owner_lane": "app lane, relay lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F14-2", + "title": "Automatic updates off remains off for urgent manifests until explicit action.", + "setup": "The regression F14 requires (review finding F14: Developer fleet control must not silently become the public client trust model).", + "steps": [ + "Automatic updates off remains off for urgent manifests until explicit action." + ], + "accept": "Automatic updates off remains off for urgent manifests until explicit action.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F14" + ], + "gate": "Review findings closed", + "owner": "app lane, relay lane", + "manual_page": null, + "finding": "F14", + "finding_title": "Developer fleet control must not silently become the public client trust model", + "finding_priority": "P1 - public client/independence gate", + "owner_lane": "app lane, relay lane", + "run_status": "NOT RUN" + }, + { + "id": "REV-F14-3", + "title": "A compromised fleet/update signing key cannot silently acquire wallet access or activate a consensus change.", + "setup": "The regression F14 requires (review finding F14: Developer fleet control must not silently become the public client trust model).", + "steps": [ + "A compromised fleet/update signing key cannot silently acquire wallet access or activate a consensus change." + ], + "accept": "A compromised fleet/update signing key cannot silently acquire wallet access or activate a consensus change.", + "evidence": "The run record of the regression as its owner lane records it through tools/ci/test-record.mjs.", + "priority": "P1", + "profile": "P00", + "cadence": "Every release candidate", + "method": "Automated + independent review", + "status": "NOT RUN", + "source": [ + "F14" + ], + "gate": "Review findings closed", + "owner": "app lane, relay lane", + "manual_page": null, + "finding": "F14", + "finding_title": "Developer fleet control must not silently become the public client trust model", + "finding_priority": "P1 - public client/independence gate", + "owner_lane": "app lane, relay lane", + "run_status": "NOT RUN" + } + ] } ], "profiles": { diff --git a/tools/ci/checks.txt b/tools/ci/checks.txt index b40cbf3e3..3605b81bf 100644 --- a/tools/ci/checks.txt +++ b/tools/ci/checks.txt @@ -77,6 +77,7 @@ P01 part A, the million-vector driver: a clean run is PASS, one wrong hash or on the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test) F02 (Review B): the proof-rule test bypass cannot reach a release build: an env read with no cfg guard or under a default feature is red; a release binary carrying the bypass string is red (self-test) the test map merges structurally at a landing: master's cells plus the branch's, minus what the branch removed and master left (self-test) +the REV suite is generated from Review B's findings and dispatch and matches them (self-test, then the tree) the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first) the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first) every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026) diff --git a/tools/ci/pre-push.sh b/tools/ci/pre-push.sh index f749c559e..1b0c3fa51 100755 --- a/tools/ci/pre-push.sh +++ b/tools/ci/pre-push.sh @@ -176,6 +176,7 @@ tree_checks() { run "the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test)" bash tools/ci/registry-evidence-check.sh --self-test run "F02 (Review B): the proof-rule test bypass cannot reach a release build: an env read with no cfg guard or under a default feature is red; a release binary carrying the bypass string is red (self-test)" bash tools/ci/proof-rule-bypass-check.sh --self-test run "the test map merges structurally at a landing: master's cells plus the branch's, minus what the branch removed and master left (self-test)" python3 tools/ci/test-map-merge.py --self-test + run "the REV suite is generated from Review B's findings and dispatch and matches them (self-test, then the tree)" bash tools/ci/review-suite-check.sh run "the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first)" bash -c 'node tools/ledger/export-public.mjs --self-test && node tools/ledger/export-public.mjs --check' run "the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first)" node tools/ledger-page.mjs --self-test run "every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026)" bash tools/ci/workflow-timeouts-check.sh --self-test diff --git a/tools/ci/review-suite-check.sh b/tools/ci/review-suite-check.sh new file mode 100755 index 000000000..4830972a0 --- /dev/null +++ b/tools/ci/review-suite-check.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# The REV suite of the registry matches Review B's findings and dispatch (tools/ci/review-suite.mjs --check), self-test first. +set -euo pipefail +node tools/ci/review-suite.mjs --self-test >/dev/null +node tools/ci/review-suite.mjs --findings docs/analysis/review-2026-10-08-b/findings.json --dispatch docs/analysis/review-2026-10-08-b/dispatch.md --prefix REV --check diff --git a/tools/ci/review-suite.mjs b/tools/ci/review-suite.mjs index 27128c6f8..3f19fb58b 100644 --- a/tools/ci/review-suite.mjs +++ b/tools/ci/review-suite.mjs @@ -47,7 +47,9 @@ if (args.includes('--self-test')) { const reg = { suites: [{ code: 'GOV', tests: [] }, { code: 'REV', tests: [{ id: 'REV-F01-1', run_status: 'RUNNING', run_id: 'r9' }] }] }; const m = merge(JSON.parse(JSON.stringify(reg)), s); const rev = m.suites.find((x) => x.code === 'REV'); if (!(m.suites.length === 2 && rev.tests.length === 3 && rev.tests[0].run_status === 'RUNNING' && rev.tests[0].run_id === 'r9' && rev.tests[1].run_status === 'NOT RUN')) { console.log('self-test failed: a regenerated suite did not keep the existing case\'s live fields or dropped another suite'); fails = 1; } - if (!fails) console.log('self-test passed: one case per required regression with the id --, the line verbatim as title and accept, the owner from the dispatch table, finding and priority carried, NOT RUN; regenerating keeps live fields and the other suites'); + const map = { cells: { c1: { cases: ['REV-F01-1'] } }, not_run: { 'REV-F02-1': 'old' } }; const n = mapReasons(map, s); + if (!(n === 2 && !('REV-F01-1' in map.not_run) && /lane z/.test(map.not_run['REV-F02-1']) && /lane x/.test(map.not_run['REV-F01-2']))) { console.log(`self-test failed: the map's NOT RUN reasons: ${JSON.stringify(map.not_run)} n=${n}`); fails = 1; } + if (!fails) console.log('self-test passed: one case per required regression with the id --, the line verbatim as title and accept, the owner from the dispatch table, finding and priority carried, NOT RUN; regenerating keeps live fields and the other suites; every unmapped case gets a NOT RUN reason naming its owner lane in the map, a mapped one loses it'); process.exit(fails); } const findings = JSON.parse(fs.readFileSync(arg('--findings'), 'utf8')); const dispatch = fs.readFileSync(arg('--dispatch'), 'utf8'); const prefix = arg('--prefix') || 'REV'; @@ -58,5 +60,15 @@ if (args.includes('--check')) { if (JSON.stringify(cur) !== JSON.stringify(want)) { console.error(`review-suite: the registry's ${prefix} suite differs from the generator's output; run --write and commit`); process.exit(1); } console.log(`review-suite: the ${prefix} suite matches its findings (${s.tests.length} cases)`); process.exit(0); } -if (args.includes('--write')) { fs.writeFileSync(REG, JSON.stringify(merge(reg, s), null, 2) + '\n'); console.log(`review-suite: ${prefix} written, ${s.tests.length} cases from ${(findings.findings || []).length} findings`); process.exit(0); } +const MAP = process.env.TEST_MAP || path.join(ROOT, 'tools/ci/test-map.json'); +function mapReasons(map, s) { // every generated case with no cell reads NOT RUN with the owner lane named; a case a cell maps loses its reason + const mapped = new Set(Object.values(map.cells || {}).flatMap((c) => c.cases || [])); map.not_run = map.not_run || {}; let n = 0; + for (const t of s.tests) { if (mapped.has(t.id)) { delete map.not_run[t.id]; continue; } map.not_run[t.id] = `${t.finding} (${t.priority}, the external review): the regression's harness is the owner lane's (${t.owner_lane}); not yet named in the map`; n++; } + return n; +} +if (args.includes('--write')) { + fs.writeFileSync(REG, JSON.stringify(merge(reg, s), null, 2) + '\n'); + let n = 0; if (fs.existsSync(MAP)) { const map = JSON.parse(fs.readFileSync(MAP, 'utf8')); n = mapReasons(map, s); fs.writeFileSync(MAP, JSON.stringify(map, null, 2) + '\n'); } + console.log(`review-suite: ${prefix} written, ${s.tests.length} cases from ${(findings.findings || []).length} findings; ${n} NOT RUN reasons in the map`); process.exit(0); +} console.error('usage: review-suite.mjs --findings f --dispatch d [--prefix REV] --write|--check | --self-test'); process.exit(2); diff --git a/tools/ci/test-map.json b/tools/ci/test-map.json index f100892a1..e73e182e1 100644 --- a/tools/ci/test-map.json +++ b/tools/ci/test-map.json @@ -1,466 +1,510 @@ { - "title": "Igneum 2.0 test harness map", - "registry": "docs/plans/igneum-2.0-test-registry.json", - "rule": "a case maps to a cell only where the cell's tests visibly answer it; coverage names what the cell proves and what remains; a mapped cell's green writes RUNNING, PASS only when coverage is full and the evidence file exists; an automated case with no cell reads NOT RUN with its reason, never PASS by inference", - "cells": { - "suite:pow": { - "command": "tools/build-remote.sh --priority gate -- test --release (from igneum-pow/)", - "box_class": "suite (gate priority)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "POW-02", - "POW-07", - "POW-08" - ], - "coverage": { - "POW-02": "partial: program derivation, ds55 geometry, the v6 fold, the packs and the spec read-back tests; the independent re-implementation and the index-fold census are the hash lane's harnesses", - "POW-08": "partial: the freeze list and the generator version pin; the public-claim scrub is the site gate's", - "POW-07": "the mixed FP32 branch is excluded and unreachable: no class flag reaches an FP op in igneum-pow on master (the mixedfp lane's branch is not on master); evidence the grep of the emitters on master, recorded by the hash lane" - } + "title": "Igneum 2.0 test harness map", + "registry": "docs/plans/igneum-2.0-test-registry.json", + "rule": "a case maps to a cell only where the cell's tests visibly answer it; coverage names what the cell proves and what remains; a mapped cell's green writes RUNNING, PASS only when coverage is full and the evidence file exists; an automated case with no cell reads NOT RUN with its reason, never PASS by inference", + "cells": { + "suite:pow": { + "command": "tools/build-remote.sh --priority gate -- test --release (from igneum-pow/)", + "box_class": "suite (gate priority)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "POW-02", + "POW-07", + "POW-08" + ], + "coverage": { + "POW-02": "partial: program derivation, ds55 geometry, the v6 fold, the packs and the spec read-back tests; the independent re-implementation and the index-fold census are the hash lane's harnesses", + "POW-08": "partial: the freeze list and the generator version pin; the public-claim scrub is the site gate's", + "POW-07": "the mixed FP32 branch is excluded and unreachable: no class flag reaches an FP op in igneum-pow on master (the mixedfp lane's branch is not on master); evidence the grep of the emitters on master, recorded by the hash lane" + } + }, + "suite:app": { + "command": "tools/build-remote.sh --priority gate -- test --release (from app/igneum-app/)", + "box_class": "suite (gate priority)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "UX-02", + "UX-03", + "UX-07", + "VER-08" + ], + "coverage": { + "UX-02": "partial: the engine state machine's pause, stop and knob tests; the operator study is UX-01's", + "UX-03": "partial: the card and earnings rendering tests; the net-earnings model against real bills is COM/ECO evidence", + "UX-07": "partial: the refused-update and manifest tests; the update-return lane's install classes are its own rows", + "VER-08": "partial: the app's own state-word tests; the wallet and light client rows are VER-01 to VER-03" + } + }, + "suite:core": { + "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-consensus-core (from the node fork)", + "box_class": "suite (gate priority)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "FIN-01", + "INC-01", + "ROT-06" + ], + "coverage": { + "FIN-01": "partial: the finality field and checkpoint tests on the object; ordering under load is the consensus suite and the sim", + "INC-01": "partial: emission, fee and payout arithmetic tests; the reconciliation over a live chain is the economics lane's", + "ROT-06": "partial: the dataset activation and digest tests; a live activation is the fast-time harness" + } + }, + "suite:consensus": { + "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-consensus (from the node fork)", + "box_class": "suite (gate priority)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "FIN-01", + "FIN-03", + "FIN-04", + "FIN-05", + "FIN-07", + "ROT-05", + "ZKP-01" + ], + "coverage": { + "FIN-01": "partial: the finality processes' agreement tests", + "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", + "FIN-04": "partial: the frozen table without its time expiry (rule v4)", + "FIN-05": "partial: key succession and another scheme's vote refused", + "FIN-07": "partial: majority-continuity recovery (rule v4)", + "ROT-05": "partial: the finality-stopped pause tests", + "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" + } + }, + "suite:exec": { + "command": "tools/build-remote.sh --priority gate -- test --release -p igneum-exec (from the node fork)", + "box_class": "suite (gate priority)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "ZKP-01", + "ZKP-03", + "OPS-04", + "EVM-02" + ], + "coverage": { + "ZKP-01": "partial: a real proof verifies, a wrong statement and garbage are refused (nativeverify)", + "ZKP-03": "partial: a snapshot under another digest refused, the epoch streams bound to the digest", + "OPS-04": "partial: snapshot install, replay and genesis recapture after a crash", + "EVM-02": "partial: the replay tests on the day stream; the signature and chain-id binding vectors are an EVM harness still to map" + } + }, + "suite:miner": { + "command": "tools/build-remote.sh --priority gate -- test --release -p igneum-miner (from the node fork)", + "box_class": "suite (gate priority)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "UX-06", + "UX-04", + "POW-01" + ], + "coverage": { + "UX-06": "partial: the miner's own template selection tests", + "UX-04": "partial: payout label and share accounting tests; custody is the pool lane's row", + "POW-01": "partial: the pack re-check seam against the pack's 96 vectors (recheck_pack); the million-vector campaign is harness:p01-vectors" + } + }, + "suite:p2p-flows": { + "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-p2p-flows (from the node fork)", + "box_class": "suite (gate priority)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "OPS-06", + "ZKP-06" + ], + "coverage": { + "OPS-06": "partial: malformed relay messages refused; traffic containment under load is an OPS harness", + "ZKP-06": "partial: proof relay coverage tests; aggregation completeness is the proving lane's test set" + } + }, + "gate:pre-push": { + "command": "tools/ci/pre-push.sh (every landing; the heavy checks ship to a box)", + "box_class": "gate", + "fixtures": [ + "F1" + ], + "cases": [ + "GOV-05", + "GOV-06", + "UX-08" + ], + "coverage": { + "GOV-05": "partial: every gate check carries a self-test that fires on a known failure and passes a known success (77 checks); the suites' own oracles are their mutation rows", + "GOV-06": "partial: the launch-gates, forbidden-strings and scope checks on the served site", + "UX-08": "partial: the site gate on every served page, plus docs/build/tuning.md (the published tuning and build-settings half, the hash lane's); the open builds and the fee conditions are the shipper's and the site lane's" + } + }, + "check:freeze": { + "command": "consensus/pow/build.rs rule 19 at every kaspa-pow build; packaging/pow-freeze.txt and packaging/d1-freeze.txt", + "box_class": "build", + "fixtures": [ + "F0" + ], + "cases": [ + "GOV-01" + ], + "coverage": { + "GOV-01": "partial: the linked igneum-pow tree's fingerprint must match a listed freeze or the build fails, the binary prints which; the manifest (igneum_getManifest) names the object digest; the signed F0 manifest is the node lane's row tonight" + } + }, + "harness:fast-time-60x": { + "command": "the v5 fast-time harness on the devnet object at 60x (infra/fast-time/override-60x.json; the node lane's run shape)", + "box_class": "harness (lease pool, never build-1)", + "fixtures": [ + "F0", + "F3" + ], + "cases": [ + "ROT-01", + "ROT-02" + ], + "coverage": { + "ROT-01": "partial: hourly boundaries crossed at 60x with every node agreeing", + "ROT-02": "partial: the weekly and family boundary crossings at 60x" + } + }, + "harness:finality-sim": { + "command": "igneum/harness-sim, the finality lane's scenarios (sim/results_v2.md, the Rule v4 section: N1, N1b, N2, N2b, N3, N4, N6 and the real-node known-failed line)", + "box_class": "harness", + "fixtures": [ + "F0", + "F4" + ], + "cases": [ + "FIN-08" + ], + "coverage": { + "FIN-08": "partial: the combined boundary and fault scenarios in the simulator with adversarial schedules; model checking is the formal review" + } + }, + "harness:p01-vectors": { + "command": "tools/ci/p01-vectors.py --worker --pack --reference /srv/artefacts/packs/p01-vectors/.txt --count 1000000 --out : the worker driven with pool.rs's job lines at an all-pass target, every found hash diffed against the CPU reference list (igneum-pow hash-bound --count 1000000, prehash 00..01, the genesis seeds), exit 1 on any disagreement or unanswered nonce", + "box_class": "pods (one backend each)", + "fixtures": [ + "F0", + "F2" + ], + "cases": [ + "POW-01" + ], + "coverage": { + "POW-01": "the million-vector campaign per backend per pack, bit-for-bit; PASS only when every supported backend reads a million vectors with zero disagreement; the malformed-input half is harness:parser-malformed" + } + }, + "harness:parser-malformed": { + "command": "cargo test --release -p igneum-exec --lib -- malformed --nocapture; cargo test --release -p igneum-miner --bins -- malformed --nocapture (node fork branch parser-malformed f0204947, taken into release-2.0.0-node at the node lane's next cut): ten thousand seeded mutations per parser through DayStream::from_bytes plus check, rpc::dispatch over nineteen igneum_ methods, and pool::job_seeds; the summary line per parser is the evidence", + "box_class": "suite", + "fixtures": [ + "F5" + ], + "cases": [ + "POW-06" + ], + "coverage": { + "POW-06": "partial: three parsers of external bytes (the state stream, the igneum_ RPC params, the pool job line), ten thousand seeded malformed cases each, zero panics, every case under 500 ms (the slowest 152 microseconds); 'accepted' counts mutations that left a valid input, not a parser fault; the verifier work bound (the other half of the accept text) is the proving lane's measurement" + } + }, + "bench:pc1-packs": { + "command": "tools/ca3-v4-amend/pc1-ca4-packs.ps1 on PC 1 (RTX 5090, the signed-jobs channel, --cards-off, the Power Helper lock at 1,300 MHz, nvidia-smi at 1 Hz, 250 x 2^24 per row, the kit's CUDA worker --bench)", + "box_class": "PC 1 bench", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "GPU-02", + "GPU-03", + "GPU-05", + "POW-08" + ], + "coverage": { + "GPU-02": "partial: the paired stock and locked rows on the same board, host and workload (the rate held, 2.37 against 3.26 microjoules per hash on the class v5 pack); the historical 34 to 41 percent claim's full configuration set is owed", + "GPU-03": "partial: hl-v6-all against hl-v6-foldrw on the 5090, the window's cost per unit of work, registers and blocks per SM, no spill; the mandatory-SKU set is owed", + "GPU-05": "partial: v3-1g, v3-ds29, v3-ds30, ds55, ds4g-ms complete with their fingerprints, energy per step at stock and at the knee on the 5090 and the 7600; the 8.5 and 11.5 GiB candidates are owed", + "POW-08": "partial: rw-w4, rw-w32, rw-w64 and the 1p5x long-program packs as regression controls for the excluded levers" + } + }, + "bench:pc1-amd": { + "command": "tools/ca3-v4-amend/pc1-amd-cardin-bench.ps1 on PC 1 (RX 7600, OpenCL, gfx1102, 30 dispatches of 2^24 per size, rate only)", + "box_class": "PC 1 bench", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "GPU-01", + "GPU-05" + ], + "coverage": { + "GPU-01": "partial: the 8 GB AMD cell, fingerprints and rates at 1, 2, 4 and 5.5 GiB; one cell of P02's twelve", + "GPU-05": "partial: the 8 GB tier's fit rows" + } + }, + "bench:fleet-pods": { + "command": "the fleet lane's one-shot RunPod cards (5090, 4090, H100, 3090) with the same worker --bench and nvidia-smi sampling, the lock through nvidia-smi -lgc", + "box_class": "rented pods", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "GPU-01", + "GPU-03", + "POW-08" + ], + "coverage": { + "GPU-01": "partial: the NVIDIA cells of P02 that RunPod carries", + "GPU-03": "partial: the 4090 cell", + "POW-08": "partial: W = 16 on four cards" + } + }, + "census:class-v6": { + "command": "the census lane's harness on class-v6-census-fold: the acceptance rule with (c''') on every candidate, the attempts census, the per-site index-bit read, attack-f8 at 2^22 on the live state", + "box_class": "harness (the lease pool)", + "fixtures": [ + "F0", + "F3" + ], + "cases": [ + "POW-02" + ], + "coverage": { + "POW-02": "partial: the fold's index statistics and the grammar bounds on 256 seeds plus the F8 set; the malformed programs are owed to harness:parser-malformed" + } + }, + "crosscheck:review-harness": { + "command": "python3 run_all.py in docs/analysis/review-2026-10-08/harness.zip (the reviewer's C/Python transcription of the V2 to V4 paths; numpy and cc; about 1 GB) on a box, its all_results.json the evidence; the tree's side is igneum-pow's own pins of the same constants (src/verify.rs, src/bind.rs, proto-cuda/packs/igneum-genesis/vectors.json) under suite:pow", + "box_class": "suite (nice 10)", + "fixtures": [ + "F0", + "F3" + ], + "cases": [ + "POW-01" + ], + "coverage": { + "POW-01": "partial: independent execution agrees with the tree on the V2/V3 genesis program id and op mix, the two closed-form hashes, the three census ids and the eight header-bound memory-hard vectors; the v5 object's and the v6 freeze's vectors are outside the transcription's model (its README) and read NOT RUN for this cell; every backend is harness:p01-vectors" + } + }, + "model:eco05": { + "command": "python3 sim/economy/coexist/eco05.py 0.5 31.65e6 and python3 sim/economy/coexist/eco05.py 0.055 31.65e6 on a build box (python3, no packages; the frozen register docs/analysis/class-v6/eco-05-scenarios.md; the cube to sim/economy/coexist/out/)", + "box_class": "build box (CPU, python3)", + "fixtures": [ + "F0", + "F7" + ], + "cases": [ + "ECO-05" + ], + "coverage": { + "ECO-05": "full on the frozen register's grid and the eight adversarial rows at the team's reconciled specialist rows; the independent reviewer's own adversarial rows (ECO-08) remain" + } + }, + "model:coexist-fixtures": { + "command": "python3 sim/economy/coexist/fixtures.py on a build box (exit 0 = the second implementation of the per-class cost formula agrees with the hand-worked values and the model's own function within 0.5 percent)", + "box_class": "build box (CPU, python3)", + "fixtures": [ + "F7" + ], + "cases": [ + "ECO-01", + "ECO-08" + ], + "coverage": { + "ECO-01": "partial: the hand-worked fixtures and the second implementation; the independent reconciliation of inputs and units remains", + "ECO-08": "partial: the package runs from the served files (README, inputs with sources and labels, fixtures); the independent report, the rerun and the perturbations remain" + } + }, + "harness:finality-sim-fin02": { + "command": "igneum/harness-sim, the split honest populations and boundary splits (the 40/40/20 fixture, the pause valid, zero conflicting final certificates within the bound)", + "box_class": "harness", + "fixtures": [ + "F0", + "F4" + ], + "cases": [ + "FIN-02" + ], + "coverage": { + "FIN-02": "the simulator half of the accept text; the real-node run on the fault network F4 with independent operators is node:finality-realnode" + } + }, + "node:finality-realnode": { + "command": "the node lane's v3.mjs lines on release-2.0.0-node (real nodes, the rule v4 harness; rows in sim/results_v2.md)", + "box_class": "harness (the lease pool)", + "fixtures": [ + "F0", + "F4" + ], + "cases": [ + "FIN-02", + "FIN-07" + ], + "coverage": { + "FIN-02": "partial: the real-node half; independent operators and the review remain", + "FIN-07": "partial: deterministic recovery after reconnection and crash on real nodes (the HEAL reruns)" + } + }, + "harness:proving-enforcement": { + "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-consensus -p igneum-exec --lib enforced_ (from the node fork; the succession_* and p22_stage_* tests with it); tools/fast-time-remote.sh --node-bin -- node infra/fast-time/proving-enforcement.mjs --floor 240 ... (the crossing) and --succession --window --prior-ids ... --next-ids ... --real-proof ... --next-proof ... (the key-succession crossing)", + "box_class": "suite (gate priority) and a fast-time run (normal class, 3 local nodes)", + "fixtures": [ + "F0", + "F1" + ], + "cases": [ + "ZKP-01", + "ZKP-02", + "ZKP-03", + "ZKP-04", + "ZKP-05", + "ZKP-08", + "EVM-08" + ], + "coverage": { + "ZKP-01": "partial: the seven refusals as named tests (no proof never inserted; a wrong proof and another program id invalidate the block; the honest record paid once) and the fast-time crossing with a modified producer; the genuine-proof positive control through ordinary network paths is the testnet's live read, not run here", + "ZKP-02": "partial: the pinned-id refusal on a real proof, the daemon's start refusal, key succession (the epochs, the accepted ids, a verdict counting only where its pair is accepted, the seven refusals on both sides of the height, the start refusal under a succession, the real-proof refusal of a pair the epoch does not accept) and the fast-time crossing of a scheduled succession with a real proof under each pair; the downgrade through an old node path is not run", + "ZKP-03": "partial: the chain binding (a record signed for another network), the replay, a wrong block, a wrong shard, a stale record outside the window; the fork and replayed-sync steps are not run", + "ZKP-04": "partial: an altered payout address (after signing and re-signed), a statement over altered rewards or payouts vetoed natively, the inputs commitment of P22 stage 1 (shard 0 and the aggregator carry the commitment the node recomputes) and the derivation commitment of stage 2 (the payouts derived in the guest from the carried records); the rewards' proved derivation is P22 stage 3, PENDING", + "ZKP-05": "partial: a duplicate of a paid record pays nothing and the honest record pays once; the race, reorder and crash-recover steps are not run", + "ZKP-08": "partial: the body rule and the payment rule read one floor, a producer with its body rule off still pays nothing on honest nodes (the fast-time crossing); the replacement-prover and authority steps are not run; the proof side of the derivation is P22 stage 3, PENDING", + "EVM-08": "partial: the controlled verifier upgrade as a key succession (both pairs embedded, the window, the start refusal) and its fast-time crossing; the mixed-client crossing on the live network and the failed-distribution step are not run" + } + } }, - "suite:app": { - "command": "tools/build-remote.sh --priority gate -- test --release (from app/igneum-app/)", - "box_class": "suite (gate priority)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "UX-02", - "UX-03", - "UX-07", - "VER-08" - ], - "coverage": { - "UX-02": "partial: the engine state machine's pause, stop and knob tests; the operator study is UX-01's", - "UX-03": "partial: the card and earnings rendering tests; the net-earnings model against real bills is COM/ECO evidence", - "UX-07": "partial: the refused-update and manifest tests; the update-return lane's install classes are its own rows", - "VER-08": "partial: the app's own state-word tests; the wallet and light client rows are VER-01 to VER-03" - } - }, - "suite:core": { - "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-consensus-core (from the node fork)", - "box_class": "suite (gate priority)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "FIN-01", - "INC-01", - "ROT-06" - ], - "coverage": { - "FIN-01": "partial: the finality field and checkpoint tests on the object; ordering under load is the consensus suite and the sim", - "INC-01": "partial: emission, fee and payout arithmetic tests; the reconciliation over a live chain is the economics lane's", - "ROT-06": "partial: the dataset activation and digest tests; a live activation is the fast-time harness" - } - }, - "suite:consensus": { - "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-consensus (from the node fork)", - "box_class": "suite (gate priority)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "FIN-01", - "FIN-03", - "FIN-04", - "FIN-05", - "FIN-07", - "ROT-05", - "ZKP-01" - ], - "coverage": { - "FIN-01": "partial: the finality processes' agreement tests", - "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", - "FIN-04": "partial: the frozen table without its time expiry (rule v4)", - "FIN-05": "partial: key succession and another scheme's vote refused", - "FIN-07": "partial: majority-continuity recovery (rule v4)", - "ROT-05": "partial: the finality-stopped pause tests", - "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" - } - }, - "suite:exec": { - "command": "tools/build-remote.sh --priority gate -- test --release -p igneum-exec (from the node fork)", - "box_class": "suite (gate priority)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "ZKP-01", - "ZKP-03", - "OPS-04", - "EVM-02" - ], - "coverage": { - "ZKP-01": "partial: a real proof verifies, a wrong statement and garbage are refused (nativeverify)", - "ZKP-03": "partial: a snapshot under another digest refused, the epoch streams bound to the digest", - "OPS-04": "partial: snapshot install, replay and genesis recapture after a crash", - "EVM-02": "partial: the replay tests on the day stream; the signature and chain-id binding vectors are an EVM harness still to map" - } - }, - "suite:miner": { - "command": "tools/build-remote.sh --priority gate -- test --release -p igneum-miner (from the node fork)", - "box_class": "suite (gate priority)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "UX-06", - "UX-04", - "POW-01" - ], - "coverage": { - "UX-06": "partial: the miner's own template selection tests", - "UX-04": "partial: payout label and share accounting tests; custody is the pool lane's row", - "POW-01": "partial: the pack re-check seam against the pack's 96 vectors (recheck_pack); the million-vector campaign is harness:p01-vectors" - } - }, - "suite:p2p-flows": { - "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-p2p-flows (from the node fork)", - "box_class": "suite (gate priority)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "OPS-06", - "ZKP-06" - ], - "coverage": { - "OPS-06": "partial: malformed relay messages refused; traffic containment under load is an OPS harness", - "ZKP-06": "partial: proof relay coverage tests; aggregation completeness is the proving lane's test set" - } - }, - "gate:pre-push": { - "command": "tools/ci/pre-push.sh (every landing; the heavy checks ship to a box)", - "box_class": "gate", - "fixtures": [ - "F1" - ], - "cases": [ - "GOV-05", - "GOV-06", - "UX-08" - ], - "coverage": { - "GOV-05": "partial: every gate check carries a self-test that fires on a known failure and passes a known success (77 checks); the suites' own oracles are their mutation rows", - "GOV-06": "partial: the launch-gates, forbidden-strings and scope checks on the served site", - "UX-08": "partial: the site gate on every served page, plus docs/build/tuning.md (the published tuning and build-settings half, the hash lane's); the open builds and the fee conditions are the shipper's and the site lane's" - } - }, - "check:freeze": { - "command": "consensus/pow/build.rs rule 19 at every kaspa-pow build; packaging/pow-freeze.txt and packaging/d1-freeze.txt", - "box_class": "build", - "fixtures": [ - "F0" - ], - "cases": [ - "GOV-01" - ], - "coverage": { - "GOV-01": "partial: the linked igneum-pow tree's fingerprint must match a listed freeze or the build fails, the binary prints which; the manifest (igneum_getManifest) names the object digest; the signed F0 manifest is the node lane's row tonight" - } - }, - "harness:fast-time-60x": { - "command": "the v5 fast-time harness on the devnet object at 60x (infra/fast-time/override-60x.json; the node lane's run shape)", - "box_class": "harness (lease pool, never build-1)", - "fixtures": [ - "F0", - "F3" - ], - "cases": [ - "ROT-01", - "ROT-02" - ], - "coverage": { - "ROT-01": "partial: hourly boundaries crossed at 60x with every node agreeing", - "ROT-02": "partial: the weekly and family boundary crossings at 60x" - } - }, - "harness:finality-sim": { - "command": "igneum/harness-sim, the finality lane's scenarios (sim/results_v2.md, the Rule v4 section: N1, N1b, N2, N2b, N3, N4, N6 and the real-node known-failed line)", - "box_class": "harness", - "fixtures": [ - "F0", - "F4" - ], - "cases": [ - "FIN-08" - ], - "coverage": { - "FIN-08": "partial: the combined boundary and fault scenarios in the simulator with adversarial schedules; model checking is the formal review" - } - }, - "harness:p01-vectors": { - "command": "tools/ci/p01-vectors.py --worker --pack --reference /srv/artefacts/packs/p01-vectors/.txt --count 1000000 --out : the worker driven with pool.rs's job lines at an all-pass target, every found hash diffed against the CPU reference list (igneum-pow hash-bound --count 1000000, prehash 00..01, the genesis seeds), exit 1 on any disagreement or unanswered nonce", - "box_class": "pods (one backend each)", - "fixtures": [ - "F0", - "F2" - ], - "cases": [ - "POW-01" - ], - "coverage": { - "POW-01": "the million-vector campaign per backend per pack, bit-for-bit; PASS only when every supported backend reads a million vectors with zero disagreement; the malformed-input half is harness:parser-malformed" - } - }, - "harness:parser-malformed": { - "command": "cargo test --release -p igneum-exec --lib -- malformed --nocapture; cargo test --release -p igneum-miner --bins -- malformed --nocapture (node fork branch parser-malformed f0204947, taken into release-2.0.0-node at the node lane's next cut): ten thousand seeded mutations per parser through DayStream::from_bytes plus check, rpc::dispatch over nineteen igneum_ methods, and pool::job_seeds; the summary line per parser is the evidence", - "box_class": "suite", - "fixtures": [ - "F5" - ], - "cases": [ - "POW-06" - ], - "coverage": { - "POW-06": "partial: three parsers of external bytes (the state stream, the igneum_ RPC params, the pool job line), ten thousand seeded malformed cases each, zero panics, every case under 500 ms (the slowest 152 microseconds); 'accepted' counts mutations that left a valid input, not a parser fault; the verifier work bound (the other half of the accept text) is the proving lane's measurement" - } - }, - "bench:pc1-packs": { - "command": "tools/ca3-v4-amend/pc1-ca4-packs.ps1 on PC 1 (RTX 5090, the signed-jobs channel, --cards-off, the Power Helper lock at 1,300 MHz, nvidia-smi at 1 Hz, 250 x 2^24 per row, the kit's CUDA worker --bench)", - "box_class": "PC 1 bench", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "GPU-02", - "GPU-03", - "GPU-05", - "POW-08" - ], - "coverage": { - "GPU-02": "partial: the paired stock and locked rows on the same board, host and workload (the rate held, 2.37 against 3.26 microjoules per hash on the class v5 pack); the historical 34 to 41 percent claim's full configuration set is owed", - "GPU-03": "partial: hl-v6-all against hl-v6-foldrw on the 5090, the window's cost per unit of work, registers and blocks per SM, no spill; the mandatory-SKU set is owed", - "GPU-05": "partial: v3-1g, v3-ds29, v3-ds30, ds55, ds4g-ms complete with their fingerprints, energy per step at stock and at the knee on the 5090 and the 7600; the 8.5 and 11.5 GiB candidates are owed", - "POW-08": "partial: rw-w4, rw-w32, rw-w64 and the 1p5x long-program packs as regression controls for the excluded levers" - } - }, - "bench:pc1-amd": { - "command": "tools/ca3-v4-amend/pc1-amd-cardin-bench.ps1 on PC 1 (RX 7600, OpenCL, gfx1102, 30 dispatches of 2^24 per size, rate only)", - "box_class": "PC 1 bench", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "GPU-01", - "GPU-05" - ], - "coverage": { - "GPU-01": "partial: the 8 GB AMD cell, fingerprints and rates at 1, 2, 4 and 5.5 GiB; one cell of P02's twelve", - "GPU-05": "partial: the 8 GB tier's fit rows" - } - }, - "bench:fleet-pods": { - "command": "the fleet lane's one-shot RunPod cards (5090, 4090, H100, 3090) with the same worker --bench and nvidia-smi sampling, the lock through nvidia-smi -lgc", - "box_class": "rented pods", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "GPU-01", - "GPU-03", - "POW-08" - ], - "coverage": { - "GPU-01": "partial: the NVIDIA cells of P02 that RunPod carries", - "GPU-03": "partial: the 4090 cell", - "POW-08": "partial: W = 16 on four cards" - } - }, - "census:class-v6": { - "command": "the census lane's harness on class-v6-census-fold: the acceptance rule with (c''') on every candidate, the attempts census, the per-site index-bit read, attack-f8 at 2^22 on the live state", - "box_class": "harness (the lease pool)", - "fixtures": [ - "F0", - "F3" - ], - "cases": [ - "POW-02" - ], - "coverage": { - "POW-02": "partial: the fold's index statistics and the grammar bounds on 256 seeds plus the F8 set; the malformed programs are owed to harness:parser-malformed" - } - }, - "crosscheck:review-harness": { - "command": "python3 run_all.py in docs/analysis/review-2026-10-08/harness.zip (the reviewer's C/Python transcription of the V2 to V4 paths; numpy and cc; about 1 GB) on a box, its all_results.json the evidence; the tree's side is igneum-pow's own pins of the same constants (src/verify.rs, src/bind.rs, proto-cuda/packs/igneum-genesis/vectors.json) under suite:pow", - "box_class": "suite (nice 10)", - "fixtures": [ - "F0", - "F3" - ], - "cases": [ - "POW-01" - ], - "coverage": { - "POW-01": "partial: independent execution agrees with the tree on the V2/V3 genesis program id and op mix, the two closed-form hashes, the three census ids and the eight header-bound memory-hard vectors; the v5 object's and the v6 freeze's vectors are outside the transcription's model (its README) and read NOT RUN for this cell; every backend is harness:p01-vectors" - } - }, - "model:eco05": { - "command": "python3 sim/economy/coexist/eco05.py 0.5 31.65e6 and python3 sim/economy/coexist/eco05.py 0.055 31.65e6 on a build box (python3, no packages; the frozen register docs/analysis/class-v6/eco-05-scenarios.md; the cube to sim/economy/coexist/out/)", - "box_class": "build box (CPU, python3)", - "fixtures": [ - "F0", - "F7" - ], - "cases": [ - "ECO-05" - ], - "coverage": { - "ECO-05": "full on the frozen register's grid and the eight adversarial rows at the team's reconciled specialist rows; the independent reviewer's own adversarial rows (ECO-08) remain" - } - }, - "model:coexist-fixtures": { - "command": "python3 sim/economy/coexist/fixtures.py on a build box (exit 0 = the second implementation of the per-class cost formula agrees with the hand-worked values and the model's own function within 0.5 percent)", - "box_class": "build box (CPU, python3)", - "fixtures": [ - "F7" - ], - "cases": [ - "ECO-01", - "ECO-08" - ], - "coverage": { - "ECO-01": "partial: the hand-worked fixtures and the second implementation; the independent reconciliation of inputs and units remains", - "ECO-08": "partial: the package runs from the served files (README, inputs with sources and labels, fixtures); the independent report, the rerun and the perturbations remain" - } - }, - "harness:finality-sim-fin02": { - "command": "igneum/harness-sim, the split honest populations and boundary splits (the 40/40/20 fixture, the pause valid, zero conflicting final certificates within the bound)", - "box_class": "harness", - "fixtures": [ - "F0", - "F4" - ], - "cases": [ - "FIN-02" - ], - "coverage": { - "FIN-02": "the simulator half of the accept text; the real-node run on the fault network F4 with independent operators is node:finality-realnode" - } - }, - "node:finality-realnode": { - "command": "the node lane's v3.mjs lines on release-2.0.0-node (real nodes, the rule v4 harness; rows in sim/results_v2.md)", - "box_class": "harness (the lease pool)", - "fixtures": [ - "F0", - "F4" - ], - "cases": [ - "FIN-02", - "FIN-07" - ], - "coverage": { - "FIN-02": "partial: the real-node half; independent operators and the review remain", - "FIN-07": "partial: deterministic recovery after reconnection and crash on real nodes (the HEAL reruns)" - } - }, - "harness:proving-enforcement": { - "command": "tools/build-remote.sh --priority gate -- test --release -p kaspa-consensus -p igneum-exec --lib enforced_ (from the node fork; the succession_* and p22_stage_* tests with it); tools/fast-time-remote.sh --node-bin -- node infra/fast-time/proving-enforcement.mjs --floor 240 ... (the crossing) and --succession --window --prior-ids ... --next-ids ... --real-proof ... --next-proof ... (the key-succession crossing)", - "box_class": "suite (gate priority) and a fast-time run (normal class, 3 local nodes)", - "fixtures": [ - "F0", - "F1" - ], - "cases": [ - "ZKP-01", - "ZKP-02", - "ZKP-03", - "ZKP-04", - "ZKP-05", - "ZKP-08", - "EVM-08" - ], - "coverage": { - "ZKP-01": "partial: the seven refusals as named tests (no proof never inserted; a wrong proof and another program id invalidate the block; the honest record paid once) and the fast-time crossing with a modified producer; the genuine-proof positive control through ordinary network paths is the testnet's live read, not run here", - "ZKP-02": "partial: the pinned-id refusal on a real proof, the daemon's start refusal, key succession (the epochs, the accepted ids, a verdict counting only where its pair is accepted, the seven refusals on both sides of the height, the start refusal under a succession, the real-proof refusal of a pair the epoch does not accept) and the fast-time crossing of a scheduled succession with a real proof under each pair; the downgrade through an old node path is not run", - "ZKP-03": "partial: the chain binding (a record signed for another network), the replay, a wrong block, a wrong shard, a stale record outside the window; the fork and replayed-sync steps are not run", - "ZKP-04": "partial: an altered payout address (after signing and re-signed), a statement over altered rewards or payouts vetoed natively, the inputs commitment of P22 stage 1 (shard 0 and the aggregator carry the commitment the node recomputes) and the derivation commitment of stage 2 (the payouts derived in the guest from the carried records); the rewards' proved derivation is P22 stage 3, PENDING", - "ZKP-05": "partial: a duplicate of a paid record pays nothing and the honest record pays once; the race, reorder and crash-recover steps are not run", - "ZKP-08": "partial: the body rule and the payment rule read one floor, a producer with its body rule off still pays nothing on honest nodes (the fast-time crossing); the replacement-prover and authority steps are not run; the proof side of the derivation is P22 stage 3, PENDING", - "EVM-08": "partial: the controlled verifier upgrade as a key succession (both pairs embedded, the window, the start refusal) and its fast-time crossing; the mixed-client crossing on the live network and the failed-distribution step are not run" - } + "not_run": { + "GOV-02": "the approval is recorded in the registry's approval field; the automated half (thresholds frozen before any run_status) is the gate rule landing by 21:00", + "GOV-04": "the evidence vault F9 (raw and negative evidence preserved) is the gate rule landing by 21:00: a PASS must carry its evidence file", + "GOV-08": "the stale-evidence rule (evidence older than the manifest sha reads NOT RUN) is the gate rule landing by 21:00", + "GPU-04": "the memory-clock ladder has no harness tonight: PC 1 mines nothing under the Devnet 3 off order", + "GPU-06": "accepted work under ordinary connectivity needs the fault network F4", + "GPU-07": "the sustained thermal and power soak has no harness tonight: PC 1 mines nothing under the Devnet 3 off order", + "POW-05": "amortised cheap winning attempts are the attack lanes' grind and era harnesses (tools/attack/f7-era, f9-grind), not in the release matrix; their rows come from those lanes", + "ADV-04": "selective participation needs the economic model F7 and a live chain window", + "ADV-06": "process-advantage separation is the adversary lanes' chip study", + "ADV-07": "lifetime rows are the adversary lanes' models", + "ROT-03": "miner-voted bring-forward needs a vote harness on the fault network F4", + "ROT-04": "seed-selection resistance is the census harness (the class v6 invention lane), not yet in the matrix", + "ROT-07": "layer ablation is a research harness, not a release suite", + "ROT-08": "the no-new-rules counterfactual is a research harness", + "ECO-02": "F7", + "ECO-03": "F7", + "ECO-04": "F7", + "ECO-06": "F7", + "ECO-07": "F7", + "EVM-01": "no EVM conformance-vector harness is mapped tonight; the exec suite does not run the reference test vectors", + "EVM-03": "the two-dimensional fee tests need the proving-limit harness", + "EVM-04": "block context and randomness vectors are an EVM harness still to map", + "EVM-05": "contract journeys need the DEX lane's integration set on Devnet 4", + "EVM-06": "wallet, RPC and indexer validation is the explorer and wallet lanes' rows", + "EVM-07": "execution DoS workloads need the workload catalogue F3", + "CAP-01": "the consumer-shard reproduction is the fleet lane's pods", + "CAP-02": "proving on the mining configuration is the fleet lane's", + "CAP-03": "the request-to-payment path is the proving fleet's measurement", + "CAP-04": "sustained load is the proving fleet's", + "CAP-05": "overload and recovery is the proving fleet's", + "CAP-06": "assignment windows are the proving fleet's", + "CAP-07": "reassignment is the proving fleet's", + "CAP-08": "customer-verifiable output is the reference apps plus the fleet", + "INC-02": "revenue separation is the economics lane's model", + "INC-03": "the modified-client task choice needs an adversarial client harness", + "INC-04": "demand spikes are the economic model", + "INC-05": "reservation abuse needs the capacity harness", + "INC-06": "difficulty and timestamp manipulation needs the fault network F4", + "INC-07": "self-dealing fees need the economic model and a live window", + "INC-08": "failure concentration is a live-window measurement", + "FIN-06": "old-key compromise analysis is the finality lane's long-range scenario, not yet in the sim", + "VER-01": "light-client bootstrap is the reference apps lane (/light); no automated harness mapped tonight", + "VER-02": "the evolving-authority statements are the reference apps lane's", + "VER-03": "payment proof (/receipt) is the reference apps lane's", + "VER-05": "state reconstruction without founder storage is the OPS no-founder exercise", + "VER-06": "withholding and corruption detection needs the fault network F4", + "VER-07": "wallet key protection is the wallet lane's security row", + "OPS-01": "the no-founder exercise is an operations run, not a suite", + "OPS-02": "bootstrap diversity needs the fault network F4", + "OPS-03": "update distribution separation is the update-return lane's row", + "OPS-05": "proving workload isolation is the fleet's pod row", + "OPS-07": "runbook detection is an operations run", + "OPS-08": "repeat independent operation is a cross-release observation", + "UX-05": "voting keys through pooling is the pool lane's row", + "COM-01": "commercial evidence, no automated harness", + "COM-02": "commercial evidence", + "COM-03": "commercial evidence", + "COM-04": "commercial evidence", + "COM-05": "commercial evidence", + "COM-06": "commercial evidence", + "COM-07": "commercial evidence", + "LEAD-02": "leadership comparison, an observation window", + "LEAD-03": "observation window", + "LEAD-04": "observation window", + "LEAD-05": "observation window", + "LEAD-06": "observation window", + "LEAD-08": "observation window", + "REV-F01-1": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", + "REV-F01-2": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", + "REV-F01-3": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", + "REV-F01-4": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", + "REV-F02-1": "F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map", + "REV-F02-2": "F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map", + "REV-F02-3": "F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map", + "REV-F03-1": "F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map", + "REV-F03-2": "F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map", + "REV-F03-3": "F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map", + "REV-F04-1": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", + "REV-F04-2": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", + "REV-F04-3": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", + "REV-F04-4": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", + "REV-F05-1": "F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map", + "REV-F05-2": "F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map", + "REV-F05-3": "F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map", + "REV-F06-1": "F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map", + "REV-F06-2": "F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map", + "REV-F06-3": "F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map", + "REV-F07-1": "F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map", + "REV-F07-2": "F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map", + "REV-F07-3": "F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map", + "REV-F08-1": "F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map", + "REV-F08-2": "F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map", + "REV-F08-3": "F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map", + "REV-F09-1": "F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map", + "REV-F09-2": "F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map", + "REV-F09-3": "F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map", + "REV-F10-1": "F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map", + "REV-F10-2": "F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map", + "REV-F10-3": "F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map", + "REV-F11-1": "F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map", + "REV-F11-2": "F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map", + "REV-F11-3": "F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map", + "REV-F12-1": "F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", + "REV-F12-2": "F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", + "REV-F12-3": "F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", + "REV-F13-1": "F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", + "REV-F13-2": "F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", + "REV-F13-3": "F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", + "REV-F14-1": "F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map", + "REV-F14-2": "F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map", + "REV-F14-3": "F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map" } - }, - "not_run": { - "GOV-02": "the approval is recorded in the registry's approval field; the automated half (thresholds frozen before any run_status) is the gate rule landing by 21:00", - "GOV-04": "the evidence vault F9 (raw and negative evidence preserved) is the gate rule landing by 21:00: a PASS must carry its evidence file", - "GOV-08": "the stale-evidence rule (evidence older than the manifest sha reads NOT RUN) is the gate rule landing by 21:00", - "GPU-04": "the memory-clock ladder has no harness tonight: PC 1 mines nothing under the Devnet 3 off order", - "GPU-06": "accepted work under ordinary connectivity needs the fault network F4", - "GPU-07": "the sustained thermal and power soak has no harness tonight: PC 1 mines nothing under the Devnet 3 off order", - "POW-05": "amortised cheap winning attempts are the attack lanes' grind and era harnesses (tools/attack/f7-era, f9-grind), not in the release matrix; their rows come from those lanes", - "ADV-04": "selective participation needs the economic model F7 and a live chain window", - "ADV-06": "process-advantage separation is the adversary lanes' chip study", - "ADV-07": "lifetime rows are the adversary lanes' models", - "ROT-03": "miner-voted bring-forward needs a vote harness on the fault network F4", - "ROT-04": "seed-selection resistance is the census harness (the class v6 invention lane), not yet in the matrix", - "ROT-07": "layer ablation is a research harness, not a release suite", - "ROT-08": "the no-new-rules counterfactual is a research harness", - "ECO-02": "F7", - "ECO-03": "F7", - "ECO-04": "F7", - "ECO-06": "F7", - "ECO-07": "F7", - "EVM-01": "no EVM conformance-vector harness is mapped tonight; the exec suite does not run the reference test vectors", - "EVM-03": "the two-dimensional fee tests need the proving-limit harness", - "EVM-04": "block context and randomness vectors are an EVM harness still to map", - "EVM-05": "contract journeys need the DEX lane's integration set on Devnet 4", - "EVM-06": "wallet, RPC and indexer validation is the explorer and wallet lanes' rows", - "EVM-07": "execution DoS workloads need the workload catalogue F3", - "CAP-01": "the consumer-shard reproduction is the fleet lane's pods", - "CAP-02": "proving on the mining configuration is the fleet lane's", - "CAP-03": "the request-to-payment path is the proving fleet's measurement", - "CAP-04": "sustained load is the proving fleet's", - "CAP-05": "overload and recovery is the proving fleet's", - "CAP-06": "assignment windows are the proving fleet's", - "CAP-07": "reassignment is the proving fleet's", - "CAP-08": "customer-verifiable output is the reference apps plus the fleet", - "INC-02": "revenue separation is the economics lane's model", - "INC-03": "the modified-client task choice needs an adversarial client harness", - "INC-04": "demand spikes are the economic model", - "INC-05": "reservation abuse needs the capacity harness", - "INC-06": "difficulty and timestamp manipulation needs the fault network F4", - "INC-07": "self-dealing fees need the economic model and a live window", - "INC-08": "failure concentration is a live-window measurement", - "FIN-06": "old-key compromise analysis is the finality lane's long-range scenario, not yet in the sim", - "VER-01": "light-client bootstrap is the reference apps lane (/light); no automated harness mapped tonight", - "VER-02": "the evolving-authority statements are the reference apps lane's", - "VER-03": "payment proof (/receipt) is the reference apps lane's", - "VER-05": "state reconstruction without founder storage is the OPS no-founder exercise", - "VER-06": "withholding and corruption detection needs the fault network F4", - "VER-07": "wallet key protection is the wallet lane's security row", - "OPS-01": "the no-founder exercise is an operations run, not a suite", - "OPS-02": "bootstrap diversity needs the fault network F4", - "OPS-03": "update distribution separation is the update-return lane's row", - "OPS-05": "proving workload isolation is the fleet's pod row", - "OPS-07": "runbook detection is an operations run", - "OPS-08": "repeat independent operation is a cross-release observation", - "UX-05": "voting keys through pooling is the pool lane's row", - "COM-01": "commercial evidence, no automated harness", - "COM-02": "commercial evidence", - "COM-03": "commercial evidence", - "COM-04": "commercial evidence", - "COM-05": "commercial evidence", - "COM-06": "commercial evidence", - "COM-07": "commercial evidence", - "LEAD-02": "leadership comparison, an observation window", - "LEAD-03": "observation window", - "LEAD-04": "observation window", - "LEAD-05": "observation window", - "LEAD-06": "observation window", - "LEAD-08": "observation window" - } } From b8f9ada5eaf07247a5d959254351545f60e81796 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:16:03 +0000 Subject: [PATCH 3/6] The registry's structural transforms replay at the merge like batches: the REV generator and the notes; a NOT RUN row is stamped only on change merge-to-master.sh rebuilds the registry from master's copy whenever a landing carries any transform, then regenerates the REV suite from the merged tree's findings and dispatch (review-suite.mjs --write), replays every added batch, and replays every added note file (tools/ci/notes/.json, {suite, text}, through test-record.mjs --note-file), then regenerates the harness page from the structurally merged map. The founder's two rulings ride as note files. test-record.mjs stamps a NOT RUN row only when its status or reason changes (every landing had been colliding on 39 untouched rows, the reference-apps lane's finding). Co-Authored-By: Claude Fable 5.1 --- tools/ci/merge-to-master.sh | 15 ++++++++++++++- tools/ci/notes/f04-fin-20261008.json | 4 ++++ tools/ci/notes/f14-ops-20261008.json | 4 ++++ tools/ci/notes/f14-ux-20261008.json | 4 ++++ tools/ci/test-record.mjs | 9 +++++++-- 5 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tools/ci/notes/f04-fin-20261008.json create mode 100644 tools/ci/notes/f14-ops-20261008.json create mode 100644 tools/ci/notes/f14-ux-20261008.json diff --git a/tools/ci/merge-to-master.sh b/tools/ci/merge-to-master.sh index a573b1ad0..491917e45 100755 --- a/tools/ci/merge-to-master.sh +++ b/tools/ci/merge-to-master.sh @@ -115,7 +115,7 @@ mirror_master() { # [landed-remote-url]: the landed master to every othe push_race() { case "$1" in *"REFUSED"*|*" RED "*) return 1 ;; *"cannot lock ref"*|*"failed to update ref"*|*"fetch first"*|*"non-fast-forward"*) return 0 ;; *) return 1 ;; esac; } merge_with_batches() { local tip="$1" sha="$2" msg="$3" conflicts f - local MAP_CHANGED="${MAP_CHANGED:-0}" MAP_PATH="${MAP_PATH:-tools/ci/test-map.json}" PAGE_PATH="${PAGE_PATH:-docs/plans/igneum-2.0-test-harness-map.md}" BATCHES="${BATCHES:-}" REGISTRY_PATH="${REGISTRY_PATH:-docs/plans/igneum-2.0-test-registry.json}" + local MAP_CHANGED="${MAP_CHANGED:-0}" MAP_PATH="${MAP_PATH:-tools/ci/test-map.json}" PAGE_PATH="${PAGE_PATH:-docs/plans/igneum-2.0-test-harness-map.md}" BATCHES="${BATCHES:-}" NOTES="${NOTES:-}" REGISTRY_PATH="${REGISTRY_PATH:-docs/plans/igneum-2.0-test-registry.json}" if git "${AUTHOR[@]}" merge -q --no-ff --no-commit "$sha" >/dev/null 2>&1; then :; else conflicts=$(git diff --name-only --diff-filter=U) local c ok=1 @@ -143,11 +143,21 @@ merge_with_batches() { fi if [ -n "$BATCHES" ]; then git checkout -q "$tip" -- "$REGISTRY_PATH" # master's copy, never the branch's + if [ -f tools/ci/review-suite.mjs ] && [ -f docs/analysis/review-2026-10-08-b/findings.json ]; then + node tools/ci/review-suite.mjs --findings docs/analysis/review-2026-10-08-b/findings.json --dispatch docs/analysis/review-2026-10-08-b/dispatch.md --prefix REV --write >/dev/null || { echo "merge-to-master: the REV suite does not regenerate on the merged tree" >&2; git merge --abort 2>/dev/null; return 1; } + echo "merge-to-master: regenerated the REV suite on master's registry" + fi for f in $BATCHES; do + [ "$f" = . ] && continue git checkout -q "$sha" -- "$f" node tools/ci/test-record.mjs --record "$f" >/dev/null || { echo "merge-to-master: the batch $f does not replay onto master's registry" >&2; git merge --abort 2>/dev/null; return 1; } echo "merge-to-master: replayed $f onto master's registry" done + for f in ${NOTES:-}; do + git checkout -q "$sha" -- "$f" + node tools/ci/test-record.mjs --note-file "$f" >/dev/null || { echo "merge-to-master: the note $f does not apply" >&2; git merge --abort 2>/dev/null; return 1; } + echo "merge-to-master: replayed the note $f" + done git add -A fi git "${AUTHOR[@]}" commit -q -m "$msg" || return 1 @@ -290,6 +300,9 @@ bash tools/ci/rule24-crate-gate.sh "$BASE" "$SHA" || { echo "merge-to-master: RE # copy is never what lands and rule 26 does not bind the registry path for such a branch (the evidence rules run on the merged result) REGISTRY_PATH="${REGISTRY_PATH:-docs/plans/igneum-2.0-test-registry.json}" BATCHES=$(git diff --name-only --diff-filter=A "$BASE" "$SHA" -- tools/ci/batches/ | grep -E '\.json$' || true) +NOTES=$(git diff --name-only --diff-filter=A "$BASE" "$SHA" -- tools/ci/notes/ | grep -E '\.json$' || true) # {suite, text}, replayed through test-record.mjs --note-file +REVGEN=0; git diff --quiet "$BASE" "$SHA" -- tools/ci/review-suite.mjs docs/analysis/review-2026-10-08-b/findings.json docs/analysis/review-2026-10-08-b/dispatch.md 2>/dev/null || REVGEN=1 # the REV suite regenerates on the merged tree +[ -n "$NOTES" ] || [ "$REVGEN" = 1 ] && BATCHES="${BATCHES:-.}" # the registry is rebuilt from master's copy whenever any transform rides RULE26_SKIP_PATHS=""; [ -n "$BATCHES" ] && RULE26_SKIP_PATHS="$REGISTRY_PATH" # the harness map page is generated from tools/ci/test-map.json (test-map-doc.mjs); a branch that changed the map regenerated the # whole page, and master's page moves under every lane (8 October 2026, 19:5x UK: the enforced-proving lane lost rule 26's race diff --git a/tools/ci/notes/f04-fin-20261008.json b/tools/ci/notes/f04-fin-20261008.json new file mode 100644 index 000000000..d1ed37843 --- /dev/null +++ b/tools/ci/notes/f04-fin-20261008.json @@ -0,0 +1,4 @@ +{ + "suite": "FIN", + "text": "F04 (Review B), the founder's ruling 8 October 19:57 UK: the recovery lock is kept and is always labelled 'recovery', never 'final', on every surface (the checkpoint field, the explorer, receipts, the light client, the oracle, the site)" +} diff --git a/tools/ci/notes/f14-ops-20261008.json b/tools/ci/notes/f14-ops-20261008.json new file mode 100644 index 000000000..05ad8f2f8 --- /dev/null +++ b/tools/ci/notes/f14-ops-20261008.json @@ -0,0 +1,4 @@ +{ + "suite": "OPS", + "text": "F14 (Review B), the founder's ruling 8 October 19:57 UK: the public miner ships from 2.0.2 without remote jobs; our own fleet runs the lab build with its own signing root" +} diff --git a/tools/ci/notes/f14-ux-20261008.json b/tools/ci/notes/f14-ux-20261008.json new file mode 100644 index 000000000..689adbbc9 --- /dev/null +++ b/tools/ci/notes/f14-ux-20261008.json @@ -0,0 +1,4 @@ +{ + "suite": "UX", + "text": "F14 (Review B), the founder's ruling 8 October 19:57 UK: the public miner ships from 2.0.2 without remote jobs; our own fleet runs the lab build with its own signing root" +} diff --git a/tools/ci/test-record.mjs b/tools/ci/test-record.mjs index cdaea54e4..aac60b034 100644 --- a/tools/ci/test-record.mjs +++ b/tools/ci/test-record.mjs @@ -47,7 +47,9 @@ function record(reg, map, batch) { touched.push(id); } } - for (const [id, reason] of Object.entries(map.not_run || {})) { const c = byId.get(id); if (c && (!c.run_status || c.run_status === 'NOT RUN')) { c.run_status = 'NOT RUN'; c.evidence_record = { reason, at: now }; c.updated = now; } } + // a NOT RUN row is stamped only when its status or reason changes (8 October 2026, 20:1x UK: re-stamping every NOT RUN row on every + // run made each lane's landing collide on 39 rows it never touched) + for (const [id, reason] of Object.entries(map.not_run || {})) { const c = byId.get(id); if (c && (!c.run_status || c.run_status === 'NOT RUN') && !(c.run_status === 'NOT RUN' && c.evidence_record?.reason === reason)) { c.run_status = 'NOT RUN'; c.evidence_record = { reason, at: now }; c.updated = now; } } return touched; } const acceptSnapshot = (reg) => JSON.stringify(casesOf(reg).map((c) => { const o = { id: idOf(c) }; for (const k of ACCEPT_KEYS) if (k in c) o[k] = c[k]; return o; })); @@ -65,6 +67,8 @@ if (args.includes('--self-test')) { if (acceptSnapshot(reg) !== before) { console.log('self-test failed: a record changed an accept text'); fails = 1; } if (!(touched.length === 1 && reg.cases[0].run_status === 'PASS' && reg.cases[0].run_id === 'r1' && reg.cases[0].evidence_record.manifest_sha === 'abc' && reg.cases[0].evidence_path === '/e/pow.log' && reg.cases[0].updated)) { console.log(`self-test failed: the run was not written to the mapped case's live fields: ${JSON.stringify(reg.cases[0])}`); fails = 1; } if (!(reg.cases[1].run_status === 'NOT RUN' && /corpus/.test(reg.cases[1].evidence_record.reason))) { console.log('self-test failed: an unmapped Automated case did not read NOT RUN with its reason'); fails = 1; } + const stamp1 = reg.cases[1].updated; record(reg, map, { run_id: 'r1b', manifest_sha: 'abc', evidence_dir: '/e', cells: [{ cell: 'pow', status: 'PASS', evidence: '/e/pow.log' }] }); + if (reg.cases[1].updated !== stamp1) { console.log('self-test failed: an unchanged NOT RUN row was re-stamped on a later run'); fails = 1; } if (reg.cases[2].run_status) { console.log('self-test failed: a manual case was given a run status'); fails = 1; } const regS = { suites: [{ code: 'X', tests: [{ id: 'X-1', method: 'Automated', accept: 'a' }] }] }; if (casesOf(regS).length !== 1) { console.log('self-test failed: the suites/tests registry shape was not read'); fails = 1; } const regN = { suites: [{ code: 'FIN', tests: [{ id: 'F-1', method: 'Automated', accept: 'keep' }] }] }; fs.writeFileSync(`${d}/regn.json`, JSON.stringify(regN)); @@ -74,12 +78,13 @@ if (args.includes('--self-test')) { let threw = false; try { record(reg, map, { run_id: 'r2', manifest_sha: 'x', cells: [{ cell: 'ghost', status: 'PASS' }] }); } catch { threw = true; } if (!threw) { console.log('self-test failed: a batch naming a cell not in the map was accepted'); fails = 1; } fs.rmSync(d, { recursive: true, force: true }); - if (!fails) console.log('self-test passed: a complete map checks; an unknown case id and an unmapped Automated case are refused; a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, leaves every accept text byte-identical, gives an unmapped Automated case NOT RUN with its reason and a manual case nothing; a batch naming an unknown cell is refused; --note appends a dated note to a suite and never touches an accept text'); + if (!fails) console.log('self-test passed: a complete map checks; an unknown case id and an unmapped Automated case are refused; a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, leaves every accept text byte-identical, gives an unmapped Automated case NOT RUN with its reason and a manual case nothing; a batch naming an unknown cell is refused; --note appends a dated note to a suite and never touches an accept text; an unchanged NOT RUN row is not re-stamped'); process.exit(fails); } const reg = load(REG); const map = load(MAP); if (args.includes('--check')) { const r = check(reg, map); for (const l of r.lines) console.error(`test-record: ${l}`); console.log(`test-record: ${r.automated} Automated cases, ${r.mapped} mapped to cells, ${r.notRun} NOT RUN with a reason${r.bad ? `, ${r.bad} problems` : ''}`); process.exit(r.bad ? 1 : 0); } if (arg('--cases')) { console.log(((map.cells || {})[arg('--cases')]?.cases || []).join(',')); process.exit(0); } +if (arg('--note-file')) { const n = load(arg('--note-file')); args.push('--note', n.suite, n.text); } if (arg('--note')) { const code = arg('--note'); const text = args[args.indexOf('--note') + 2]; const suite = (reg.suites || []).find((s) => s.code === code); if (!suite || !text) { console.error(`test-record: --note needs a suite code in the registry and a text (got ${code}, ${text ? 'text' : 'no text'})`); process.exit(2); } From 1dd0576c2c571f93959fbc21863918318f243e5a Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:25:37 +0000 Subject: [PATCH 4/6] merge-to-master: the harness page regenerates after the registry rebuild, never from a copy with conflict markers (the REV landing's 20:24 loss); fixture extended Co-Authored-By: Claude Fable 5.1 --- tools/ci/merge-to-master.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/ci/merge-to-master.sh b/tools/ci/merge-to-master.sh index 491917e45..16031229c 100755 --- a/tools/ci/merge-to-master.sh +++ b/tools/ci/merge-to-master.sh @@ -136,11 +136,6 @@ merge_with_batches() { python3 tools/ci/test-map-merge.py /tmp/map-base.$$ /tmp/map-master.$$ /tmp/map-branch.$$ "$MAP_PATH" || { echo "merge-to-master: the map does not merge structurally" >&2; git merge --abort 2>/dev/null; return 1; } rm -f /tmp/map-base.$$ /tmp/map-master.$$ /tmp/map-branch.$$; git add "$MAP_PATH"; echo "merge-to-master: merged $MAP_PATH structurally (master's cells plus the branch's)" fi - if [ "$MAP_CHANGED" = 1 ] && [ -f tools/ci/test-map-doc.mjs ]; then - git checkout -q "$tip" -- "$PAGE_PATH" 2>/dev/null || true # start from master's page; the generator overwrites it from the merged map - node tools/ci/test-map-doc.mjs >/dev/null || { echo "merge-to-master: the harness map page does not regenerate from the merged map" >&2; git merge --abort 2>/dev/null; return 1; } - echo "merge-to-master: regenerated $PAGE_PATH from the merged map"; git add -A - fi if [ -n "$BATCHES" ]; then git checkout -q "$tip" -- "$REGISTRY_PATH" # master's copy, never the branch's if [ -f tools/ci/review-suite.mjs ] && [ -f docs/analysis/review-2026-10-08-b/findings.json ]; then @@ -160,6 +155,11 @@ merge_with_batches() { done git add -A fi + if [ "$MAP_CHANGED" = 1 ] && [ -f tools/ci/test-map-doc.mjs ]; then + git checkout -q "$tip" -- "$PAGE_PATH" 2>/dev/null || true # start from master's page; the generator overwrites it from the merged map + node tools/ci/test-map-doc.mjs >/dev/null || { echo "merge-to-master: the harness map page does not regenerate from the merged map" >&2; git merge --abort 2>/dev/null; return 1; } + echo "merge-to-master: regenerated $PAGE_PATH from the merged map"; git add -A + fi git "${AUTHOR[@]}" commit -q -m "$msg" || return 1 if [ -n "$BATCHES" ]; then bash tools/ci/registry-evidence-check.sh "$tip" HEAD || { echo "merge-to-master: REFUSED by the registry's evidence rules on the merged registry (above)" >&2; return 1; } @@ -261,6 +261,11 @@ import json; d=json.load(open('docs/plans/igneum-2.0-test-registry.json')); t={c git checkout -q master; python3 -c "import json; m=json.load(open('tools/ci/test-map.json')); m['cells']['c4']={'command':'w','box_class':'b','fixtures':[],'cases':['X-2']}; json.dump(m,open('tools/ci/test-map.json','w'))"; node tools/ci/test-map-doc.mjs >/dev/null 2>&1; git add -A; git -c user.name=t -c user.email=t@t commit -q -m c4 ) >/dev/null 2>&1 || { echo "self-test failed: the page-race fixture did not build"; fails=1; } out=$( cd "$rb" && TIP=$(git rev-parse master) && SHA=$(git rev-parse pb) && BASE=$(git merge-base "$TIP" "$SHA") && BATCHES="" && MAP_CHANGED=1 && MAP_PATH=tools/ci/test-map.json && PAGE_PATH=docs/plans/igneum-2.0-test-harness-map.md && REGISTRY_PATH=docs/plans/igneum-2.0-test-registry.json && AUTHOR=(-c user.name=t -c user.email=t@t) && export TEST_RECORD_ROOT="$rb" && merge_with_batches "$TIP" "$SHA" "merge with page" 2>&1 && grep -c -E '^### c[34]$' docs/plans/igneum-2.0-test-harness-map.md ) case "$out" in *regenerated*2) ;; *) echo "self-test failed: the merge did not regenerate the page with both sides' cells: $out"; fails=1 ;; esac + # both at once: the branch records a batch (its registry copy conflicts with master's) and adds a map cell; the page must regenerate + # after the registry is rebuilt, never from a copy with conflict markers (8 October 2026, 20:24 UK: the REV landing lost to this) + ( cd "$rb" && git checkout -q -b both pbase && printf '{"run_id":"r-both","manifest_sha":"m","cells":[{"cell":"c1","status":"RUNNING","evidence":"tools/ci/test-map.json"}]}\n' > tools/ci/batches/r-both.json && node tools/ci/test-record.mjs --record tools/ci/batches/r-both.json >/dev/null && python3 -c "import json; m=json.load(open('tools/ci/test-map.json')); m['cells']['c5']={'command':'v','box_class':'b','fixtures':[],'cases':['X-1']}; json.dump(m,open('tools/ci/test-map.json','w'))" && node tools/ci/test-map-doc.mjs >/dev/null 2>&1; git add -A; git -c user.name=t -c user.email=t@t commit -q -m both ) >/dev/null 2>&1 + out=$( cd "$rb" && TIP=$(git rev-parse master) && SHA=$(git rev-parse both) && BASE=$(git merge-base "$TIP" "$SHA") && BATCHES=$(git diff --name-only --diff-filter=A "$BASE" "$SHA" -- tools/ci/batches/ | grep -E '\.json$') && MAP_CHANGED=1 && MAP_PATH=tools/ci/test-map.json && PAGE_PATH=docs/plans/igneum-2.0-test-harness-map.md && REGISTRY_PATH=docs/plans/igneum-2.0-test-registry.json && AUTHOR=(-c user.name=t -c user.email=t@t) && export TEST_RECORD_ROOT="$rb" && merge_with_batches "$TIP" "$SHA" "merge both" 2>&1 && grep -c -E '^### c[45]$' docs/plans/igneum-2.0-test-harness-map.md && python3 -c "import json; d=json.load(open('docs/plans/igneum-2.0-test-registry.json')); print('ok' if any(c.get('run_id')=='r-both' for s in d['suites'] for c in s['tests']) else 'no-batch')" ) + case "$out" in *replayed*2*ok*) ;; *) echo "self-test failed: a landing with both a batch and a map change did not land both (the page before the registry rebuild?): $out"; fails=1 ;; esac push_race "To x ! [remote rejected] HEAD -> master (failed to update ref) remote: error: cannot lock ref 'refs/heads/master': is at a but expected b" || { echo "self-test failed: a lost compare-and-swap was not read as a race"; fails=1; } From a1802ac31cc36df0c7b6477513e6cb8d920b7d7f Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:07:53 +0000 Subject: [PATCH 5/6] CUDA worker: the select pass (review B F10), ported from the OpenCL worker The serving loop read 8 bytes per nonce back over the bus (128 MiB per 2^24-nonce dispatch) and scanned them on the host under the GPU mutex. Now a tiny igneum_select kernel, compiled once by NVRTC with no pack involved, writes the hits (index, hash word) behind an atomic counter plus 34 sentinel words, and the host reads back a few hundred bytes; the found lines come in nonce order from the sorted hits, the hash word printed is the kernel's own out[i]. A chunk with more than 256 hits falls back to the full read of that chunk. The sentinels feed the stale-output detector the OpenCL worker has (an unchanged signature across two chunks exits 3). --readback full or IGNEUM_READBACK=full keeps the old path; a select pass that fails to build falls back to it with an info line. The ready line carries "readback select|full"; a transfers line per 200 jobs and at quit gives the per-chunk budget. No hash changes: the bound kernel and its result layout are untouched. The emulation backend learns the select kernel (module S, a host loop in reverse index order so the sort is exercised). emu/select-check.sh, called from emu/test.sh, compares select with the full read line for line, known-failed first (IGNEUM_READBACK_FAULT_TEST skips the counter reset): zero hits, partial hits, the all-hit overflow with its full fallbacks, a 96-nonce tail with a 32-lane launch, the high-32 rollover, two queued jobs, hits then a zero chunk, a mismatch error then a job. Green on build-7 (2255 found lines, 10 jobs, 2 fallbacks). serve-bench.sh is the serving-mode measurement (production and steady numbers beside the kernel timer). Co-Authored-By: Claude Fable 5.1 --- proto-cuda/nvrtc/emu/emu_backend.cpp | 30 ++++- proto-cuda/nvrtc/emu/select-check.sh | 83 ++++++++++++++ proto-cuda/nvrtc/emu/test.sh | 3 + proto-cuda/nvrtc/serve-bench.sh | 88 +++++++++++++++ proto-cuda/nvrtc/worker.cpp | 160 +++++++++++++++++++++++++-- 5 files changed, 354 insertions(+), 10 deletions(-) create mode 100755 proto-cuda/nvrtc/emu/select-check.sh create mode 100755 proto-cuda/nvrtc/serve-bench.sh diff --git a/proto-cuda/nvrtc/emu/emu_backend.cpp b/proto-cuda/nvrtc/emu/emu_backend.cpp index feb9e6c02..f2b8bf46c 100644 --- a/proto-cuda/nvrtc/emu/emu_backend.cpp +++ b/proto-cuda/nvrtc/emu/emu_backend.cpp @@ -112,6 +112,15 @@ static void checkSource(EmuProg* p, bool defaultDevice, bool noCuda) { if (bad.empty() && p->headers.count("memhard.h")) bad = firstUnannotated("memhard.h", p->headers["memhard.h"], noCuda); if (!bad.empty()) { p->log = "emu-nvrtc: " + bad + ": A function without execution space annotations (__host__/__device__/__global__) is considered a host function, and host functions are not allowed in JIT mode (pass -default-device or -DIGNEUM_NO_CUDA)"; p->ok = false; return; } } + // The select pass (8 October 2026): the worker's own text, no pack involved; it is recorded as module 3 and run by + // d_launch as a host loop (in reverse index order, so the hits land out of nonce order and the worker's sort is exercised) + if (p->name == "igneum_select.cu") { + if (p->src.find("__global__ void igneum_select(") == std::string::npos || p->src.find("atomicAdd(count, 1u)") == std::string::npos) { p->log = "emu-nvrtc: igneum_select.cu is not the select pass this stand-in knows"; p->ok = false; return; } + p->pack = 3; p->ok = true; + std::printf("info emu-nvrtc: igneum_select.cu source check PASS: %zu bytes, the select pass runs as a host loop\n", p->src.size()); + std::fflush(stdout); + return; + } for (int which = 1; which <= 2; ++which) { std::string dir = packDir(which); if (dir.empty()) continue; @@ -159,7 +168,7 @@ static nvrtcResult e_compile(nvrtcProgram prog, int numOptions, const char* cons } static nvrtcResult e_logSize(nvrtcProgram prog, size_t* n) { *n = ((EmuProg*)prog)->log.size() + 1; return NVRTC_SUCCESS; } static nvrtcResult e_log(nvrtcProgram prog, char* out) { std::strcpy(out, ((EmuProg*)prog)->log.c_str()); return NVRTC_SUCCESS; } -static std::string image(EmuProg* p) { return std::string("EMU-IMAGE:") + (p->pack == 2 ? "B" : "A"); } +static std::string image(EmuProg* p) { return std::string("EMU-IMAGE:") + (p->pack == 3 ? "S" : p->pack == 2 ? "B" : "A"); } static nvrtcResult e_imgSize(nvrtcProgram prog, size_t* n) { *n = image((EmuProg*)prog).size() + 1; return NVRTC_SUCCESS; } static nvrtcResult e_img(nvrtcProgram prog, char* out) { std::strcpy(out, image((EmuProg*)prog).c_str()); return NVRTC_SUCCESS; } static nvrtcResult e_addName(nvrtcProgram prog, const char* e) { ((EmuProg*)prog)->exprs.push_back(e); return NVRTC_SUCCESS; } @@ -210,12 +219,13 @@ static CUresult d_htod(CUdeviceptr dst, const void* src, size_t n) { std::memcpy static CUresult d_modLoad(CUmodule* m, const void* img) { const char* s = (const char*)img; if (std::strncmp(s, "EMU-IMAGE:", 10) != 0) return CUDA_ERROR_INVALID_IMAGE; - *m = (CUmodule)(uintptr_t)(s[10] == 'B' ? 2 : 1); + *m = (CUmodule)(uintptr_t)(s[10] == 'S' ? 3 : s[10] == 'B' ? 2 : 1); return CUDA_SUCCESS; } static CUresult d_modUnload(CUmodule) { return CUDA_SUCCESS; } static CUresult d_getFn(CUfunction* f, CUmodule m, const char* name) { int pack = (int)(uintptr_t)m, idx; + if (pack == 3) { if (std::strcmp(name, "igneum_select") != 0) return CUDA_ERROR_NOT_FOUND; *f = (CUfunction)(uintptr_t)7; return CUDA_SUCCESS; } if (std::strcmp(name, "igneum_cache_fill") == 0) idx = 1; else if (std::strcmp(name, "igneum_build") == 0) idx = 2; else if (std::strcmp(name, "igneum_hash_bound") == 0) idx = 3; @@ -255,6 +265,22 @@ static CUresult d_launch(CUfunction f, unsigned gx, unsigned, unsigned, unsigned } case 6: emu_launch(emu_pack_b::igneum_hash_bound, gx, bx, dptr(params, 0), dptr(params, 1), arg(params, 2), arg(params, 3), arg(params, 4)); return CUDA_SUCCESS; #endif + case 7: { + // the select pass (8 October 2026): the kernel text's semantics as a host loop, threads visited in reverse so the + // hit table fills out of nonce order (a GPU's atomics give no order either) and the worker's sort is exercised + const uint64_t* out = dptr(params, 0); uint32_t n = arg(params, 1); uint64_t target = arg(params, 2); + uint32_t* count = dptr(params, 3); uint64_t* hits = dptr(params, 4); uint32_t maxHits = arg(params, 5); uint64_t* sentinel = dptr(params, 6); + uint64_t threads = (uint64_t)gx * bx; + for (uint64_t t = threads; t-- > 0;) { + uint32_t i = (uint32_t)t; + if (i >= n) continue; + uint64_t h = out[i]; + if (h <= target) { uint32_t k = (*count)++; if (k < maxHits) { hits[2u * k] = i; hits[2u * k + 1u] = h; } } + if (i < 32u) sentinel[i] = h; + if (i == 0u) { sentinel[32] = out[n / 2u]; sentinel[33] = out[n - 1u]; } + } + return CUDA_SUCCESS; + } default: return CUDA_ERROR_INVALID_HANDLE; } } diff --git a/proto-cuda/nvrtc/emu/select-check.sh b/proto-cuda/nvrtc/emu/select-check.sh new file mode 100755 index 000000000..1a557268c --- /dev/null +++ b/proto-cuda/nvrtc/emu/select-check.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# The select pass equivalence check (8 October 2026, review B finding F10): the found nonce and hash set of +# --readback select equals the full read-back's, line for line, over the cases the finding names, on one worker +# binary (the CPU emulation from test.sh, or a real GPU build). Known-failed first: IGNEUM_READBACK_FAULT_TEST=1 makes +# the worker skip the counter reset from the second chunk on, so stale hits come back again; the comparison must flag +# that run before the real one counts. +# select_fault_detected the fault run differs from the full read (the check can fail) +# found_set_equals_full_zero_hits z1: target 0, two chunks, no found line in either mode +# found_set_equals_full_partial_hits p1: target 03ff..., about 16 hits per chunk, four chunks +# found_set_equals_full_all_hit_overflow a1: target ffff..., every nonce a hit, every chunk over IG_MAX_HITS (full fallback) +# found_set_equals_full_tail_batch t1: 1120 nonces at 1024 per chunk and 64 per block: a 96-nonce tail with a 32-lane launch +# found_set_equals_full_high32_rollover r1: a job from 2^32 - 32 across the high-word step +# found_set_equals_full_stale_job_queued s1, s2: two job lines queued at once, the second served after the first +# buffer_reuse_hits_then_zero b1 then b2: a hit chunk followed by a zero-target chunk prints nothing stale +# mismatch_error_then_job m1 (no pair for its seeds) errors the same way, c1 after it is served +# Usage: select-check.sh (the command carries --serve --pack etc.) +set -euo pipefail +PACK_A="$1"; OUT="$2"; shift 2 +mkdir -p "$OUT" +seedline() { sed -n "s/^$2 //p" "$1/seeds.txt"; } +A_EPOCH="$(seedline "$PACK_A" epoch_seed_hex)"; A_DAY="$(seedline "$PACK_A" day_seed_hex)" +[ -n "$A_EPOCH" ] && [ -n "$A_DAY" ] || { echo "FAIL: no seeds.txt in $PACK_A"; exit 1; } +PRE="00000000000000000000000000000000000000000000000000000000000000f1" +OTHER="1111111111111111111111111111111111111111111111111111111111111111" +PART="03ffffffffffffff" +script() { + echo "job z1 $PRE 0000000000000000 0 2048 $A_EPOCH $A_DAY" + echo "job p1 $PRE $PART 2048 4096 $A_EPOCH $A_DAY" + echo "job a1 $PRE ffffffffffffffff 8192 2048 $A_EPOCH $A_DAY" + echo "job t1 $PRE $PART 16384 1120 $A_EPOCH $A_DAY" + echo "job r1 $PRE $PART 4294967264 2048 $A_EPOCH $A_DAY" + echo "job s1 $PRE $PART 32768 2048 $A_EPOCH $A_DAY" + echo "job s2 $PRE $PART 40960 2048 $A_EPOCH $A_DAY" + echo "job b1 $PRE $PART 49152 1024 $A_EPOCH $A_DAY" + echo "job b2 $PRE 0000000000000000 50176 1024 $A_EPOCH $A_DAY" + echo "job m1 $PRE $PART 0 1024 $OTHER $A_DAY" + echo "job c1 $PRE $PART 51200 1024 $A_EPOCH $A_DAY" + echo "quit" +} +run() { # + local mode="$1" log="$2"; shift 2 + case "$mode" in + full) script | IGNEUM_READBACK=full "$@" > "$log" 2>&1 || true ;; + select) script | IGNEUM_READBACK=select "$@" > "$log" 2>&1 || true ;; + fault) script | IGNEUM_READBACK=select IGNEUM_READBACK_FAULT_TEST=1 "$@" > "$log" 2>&1 || true ;; + esac +} +# the lines both modes must agree on: found, need, error, and done with its wall time stripped +norm() { grep -E '^(found|need|error|done) ' "$1" | sed -E 's/^(done [^ ]+ [0-9]+) [0-9.]+$/\1/'; } +WORKER=("$@") +run full "$OUT/rb-full.log" "${WORKER[@]}" +run select "$OUT/rb-select.log" "${WORKER[@]}" +run fault "$OUT/rb-fault.log" "${WORKER[@]}" +norm "$OUT/rb-full.log" > "$OUT/rb-full.norm" +norm "$OUT/rb-select.log" > "$OUT/rb-select.norm" +norm "$OUT/rb-fault.log" > "$OUT/rb-fault.norm" +grep -q '^ready .* readback full ' "$OUT/rb-full.log" || { echo "FAIL: the full run has no 'readback full' ready line"; exit 1; } +grep -q '^ready .* readback select ' "$OUT/rb-select.log" || { echo "FAIL: the select run has no 'readback select' ready line"; exit 1; } +[ "$(grep -c '^done ' "$OUT/rb-full.norm")" = 10 ] || { echo "FAIL: the full run should finish 10 jobs"; grep -E '^(error|done)' "$OUT/rb-full.log"; exit 1; } + +echo "== select_fault_detected (known-failed first: the counter is not reset from the second chunk on)" +if cmp -s "$OUT/rb-full.norm" "$OUT/rb-fault.norm"; then echo "FAIL: the fault run equals the full read; the comparison cannot fail"; exit 1; fi +echo "flagged: $(diff "$OUT/rb-full.norm" "$OUT/rb-fault.norm" | grep -c '^>') stale or extra lines in the fault run" + +echo "== found_set_equals_full_* (every case, line for line)" +if ! cmp -s "$OUT/rb-full.norm" "$OUT/rb-select.norm"; then echo "FAIL: select differs from the full read:"; diff "$OUT/rb-full.norm" "$OUT/rb-select.norm" | head -20; exit 1; fi +count() { grep -c "^found $1 " "$2" || true; } +[ "$(count z1 "$OUT/rb-select.norm")" = 0 ] || { echo "FAIL: zero_hits: z1 found lines"; exit 1; } +[ "$(count p1 "$OUT/rb-select.norm")" -gt 0 ] || { echo "FAIL: partial_hits: p1 found nothing"; exit 1; } +[ "$(count a1 "$OUT/rb-select.norm")" = 2048 ] || { echo "FAIL: all_hit_overflow: a1 should find 2048"; exit 1; } +grep -q '^done t1 1120' "$OUT/rb-select.norm" || { echo "FAIL: tail_batch: t1 did not finish 1120"; exit 1; } +[ "$(count t1 "$OUT/rb-select.norm")" -gt 0 ] || { echo "FAIL: tail_batch: t1 found nothing"; exit 1; } +grep -q '^done r1 2048' "$OUT/rb-select.norm" || { echo "FAIL: high32_rollover: r1 did not finish"; exit 1; } +awk '$1 == "found" && $2 == "r1" && $3 + 0 >= 4294967296 { n++ } END { exit n > 0 ? 0 : 1 }' "$OUT/rb-select.norm" || { echo "FAIL: high32_rollover: no found nonce at or past 2^32"; exit 1; } +grep -q '^done s1 2048' "$OUT/rb-select.norm" && grep -q '^done s2 2048' "$OUT/rb-select.norm" || { echo "FAIL: stale_job_queued: s1 or s2 did not finish"; exit 1; } +[ "$(count b1 "$OUT/rb-select.norm")" -gt 0 ] && [ "$(count b2 "$OUT/rb-select.norm")" = 0 ] || { echo "FAIL: buffer_reuse_hits_then_zero: b1 $(count b1 "$OUT/rb-select.norm") found, b2 $(count b2 "$OUT/rb-select.norm")"; exit 1; } +grep -q '^error m1 ' "$OUT/rb-select.norm" && grep -q '^done c1 1024' "$OUT/rb-select.norm" || { echo "FAIL: mismatch_error_then_job: m1 did not error or c1 was not served"; exit 1; } +grep -q 'full fallbacks' "$OUT/rb-select.log" || { echo "FAIL: no transfers line in the select run"; exit 1; } +fb="$(sed -n 's/.*(select, \([0-9]*\) full fallbacks).*/\1/p' "$OUT/rb-select.log" | tail -1)" +[ "$fb" = 2 ] || { echo "FAIL: all_hit_overflow: expected 2 full fallbacks (a1's two chunks), the select run reports '$fb'"; exit 1; } +echo "PASS: select = full over $(grep -c '^found ' "$OUT/rb-select.norm") found lines and 10 jobs (zero hits, partial, all-hit overflow with $fb full fallbacks, a 96-nonce tail, the high-32 rollover, two queued jobs, hits then zero, a mismatch error then a job); the fault run was flagged first" +echo "transfers: $(grep 'transfers per chunk' "$OUT/rb-select.log" | tail -1 | sed 's/^info //')" +echo "transfers: $(grep 'transfers per chunk' "$OUT/rb-full.log" | tail -1 | sed 's/^info //')" diff --git a/proto-cuda/nvrtc/emu/test.sh b/proto-cuda/nvrtc/emu/test.sh index 642ccb0cd..9e98d45d3 100755 --- a/proto-cuda/nvrtc/emu/test.sh +++ b/proto-cuda/nvrtc/emu/test.sh @@ -64,3 +64,6 @@ echo "flagged as NVRTC does: $(grep -o 'program.h([0-9]*): [^:]*' "$OUT/check-no echo "== --serve: two jobs on A, prepare B, a job on B (swap), a job on A after the swap (error), quit" "$HERE/serve-check.sh" "$OUT/pack-a" "$OUT/pack-b" "$OUT/serve.log" "$OUT/igneum-worker-cuda-emu" --serve --pack "$OUT/pack-a" --batch-log2 13 echo "NVRTC source check PASS for $(grep -c 'source check PASS' "$OUT/serve.log") files in --serve, $(grep -c 'source check PASS' "$OUT/check-a.log") in --check" + +echo "== the select pass (8 October 2026): --readback select equals the full read-back, known-failed first (emu/select-check.sh)" +"$HERE/select-check.sh" "$OUT/pack-a" "$OUT/select" "$OUT/igneum-worker-cuda-emu" --serve --pack "$OUT/pack-a" --batch-log2 10 --block-warps 2 diff --git a/proto-cuda/nvrtc/serve-bench.sh b/proto-cuda/nvrtc/serve-bench.sh new file mode 100755 index 000000000..bc2807f1d --- /dev/null +++ b/proto-cuda/nvrtc/serve-bench.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# Serving-mode measurement of igneum-worker-cuda (8 October 2026, review B finding F10): the production number beside the +# kernel timer, never interchangeable with it. The worker runs --serve exactly as the miner drives it: a stub pool here +# feeds jobs of 2^B nonces (one queued behind the one in flight, as the miner pipelines them), reads every found line +# (the miner's submit point) and every done line, and quits after N jobs. The clock starts before the worker process +# starts, so the setup (NVRTC compile, cache, dataset, self-test) is in the production number; the steady number runs +# from the ready line. Power is nvidia-smi's board reading at 4 Hz over the same windows (the pod exposes no host +# rail); the worker's own CPU seconds (utime + stime from /proc) stand in for the host-side cost of the read-back and +# the scan. The kernel timer is --bench on the same pack and batch, printed beside the rows. +# serve-bench.sh [jobs 32] [batch-log2 24] [device 0] +# Pid files: every process this script starts writes /pids/..pid (the fleet's rule: a job is +# stopped through its pid file, never by a name pattern). Output: /.row (one line, key=value) plus the +# worker log, the stub's timeline and the power samples. +set -euo pipefail +W="$1"; PACK="$2"; OUT="$3"; RUN="$4"; MODE="$5"; JOBS="${6:-32}"; B="${7:-24}"; DEV="${8:-0}" +[ "$MODE" = full ] || [ "$MODE" = select ] || { echo "readback must be full or select" >&2; exit 2; } +mkdir -p "$OUT/pids" +LOG="$OUT/$RUN.worker.log"; TL="$OUT/$RUN.timeline"; SMI="$OUT/$RUN.smi"; ROW="$OUT/$RUN.row" +: > "$TL" +now() { date +%s.%N; } +count=$((1 << B)) +target="00000fffffffffff" # one hit per 2^20 nonces: 16 found lines per 2^24-nonce job, the serving shape (a block target is far tighter) +seedline() { sed -n "s/^$2 //p" "$1/seeds.txt"; } +EPOCH="$(seedline "$PACK" epoch_seed_hex)"; DAY="$(seedline "$PACK" day_seed_hex)" +[ -n "$EPOCH" ] && [ -n "$DAY" ] || { echo "no seeds.txt in $PACK" >&2; exit 2; } +jobline() { printf 'job %d %064x %s %d %d %s %s\n' "$1" "$1" "$target" $(( $1 * count )) "$count" "$EPOCH" "$DAY"; } + +# power sampler first (its own pid file) +nvidia-smi -i "$DEV" --query-gpu=timestamp,power.draw,clocks.sm,temperature.gpu --format=csv,noheader,nounits -lms 250 > "$SMI" 2>/dev/null & +echo $! > "$OUT/pids/$RUN.smi.pid" +sleep 1 +t0=$(now) +coproc WK { IGNEUM_READBACK="$MODE" "$W" --serve --pack "$PACK" --device "$DEV" --batch-log2 "$B" --race off --readback "$MODE" 2>&1; } +echo "$WK_PID" > "$OUT/pids/$RUN.worker.pid" +sent=0; done_n=0; found=0; tready=""; tlast=""; cpu="" +: > "$LOG" +while IFS= read -r line <&"${WK[0]}"; do + t=$(now) + echo "$line" >> "$LOG" + case "$line" in + ready*) tready=$t; echo "$t ready" >> "$TL"; jobline $sent >&"${WK[1]}"; sent=$((sent + 1)); jobline $sent >&"${WK[1]}"; sent=$((sent + 1)) ;; + found*) found=$((found + 1)); echo "$t submit $line" >> "$TL" ;; + done*) done_n=$((done_n + 1)); tlast=$t; echo "$t $line" >> "$TL" + if [ "$sent" -lt "$JOBS" ]; then jobline $sent >&"${WK[1]}"; sent=$((sent + 1)); fi + if [ "$done_n" -ge "$JOBS" ]; then + cpu=$(awk '{ printf "%.2f", ($14 + $15) / 100.0 }' "/proc/$WK_PID/stat" 2>/dev/null || echo "") + echo "quit" >&"${WK[1]}" + fi ;; + error*) echo "$t $line" >> "$TL" ;; + esac +done +wait "$WK_PID" 2>/dev/null || true +t1=$(now) +sleep 1 +kill "$(cat "$OUT/pids/$RUN.smi.pid")" 2>/dev/null || true +[ -n "$tready" ] && [ -n "$tlast" ] || { echo "FAIL: no ready or no done line; see $LOG"; tail -5 "$LOG"; exit 1; } +[ "$done_n" = "$JOBS" ] || { echo "FAIL: $done_n of $JOBS jobs done; see $LOG"; exit 1; } + +# the power samples over the two windows: nvidia-smi stamps local time "YYYY/MM/DD HH:MM:SS.mmm" +meanw() { # : mean W of the samples inside the window, and their count + awk -F', *' -v a="$1" -v b="$2" 'BEGIN { n = 0; s = 0 } + { gsub("/", "-", $1); split($1, d, " "); cmd = "date -d \"" d[1] " " d[2] "\" +%s.%N"; cmd | getline ts; close(cmd); if (ts >= a && ts <= b) { s += $2; n++ } } + END { if (n) printf "%.1f %d", s / n, n; else printf "0 0" }' "$SMI" +} +read -r wProd nProd <<< "$(meanw "$t0" "$tlast")" +read -r wSteady nSteady <<< "$(meanw "$tready" "$tlast")" +hashes=$(( JOBS * count )) +wallProd=$(awk -v a="$t0" -v b="$tlast" 'BEGIN { printf "%.3f", b - a }') +wallSteady=$(awk -v a="$tready" -v b="$tlast" 'BEGIN { printf "%.3f", b - a }') +setup=$(awk -v a="$t0" -v b="$tready" 'BEGIN { printf "%.3f", b - a }') +mhsProd=$(awk -v h="$hashes" -v w="$wallProd" 'BEGIN { printf "%.2f", h / w / 1e6 }') +mhsSteady=$(awk -v h="$hashes" -v w="$wallSteady" 'BEGIN { printf "%.2f", h / w / 1e6 }') +jProd=$(awk -v w="$wProd" -v s="$wallProd" -v n="$JOBS" 'BEGIN { printf "%.1f", w * s / n }') +jSteady=$(awk -v w="$wSteady" -v s="$wallSteady" -v n="$JOBS" 'BEGIN { printf "%.1f", w * s / n }') +mhwProd=$(awk -v m="$mhsProd" -v w="$wProd" 'BEGIN { if (w > 0) printf "%.4f", m / w; else printf "n/a" }') +mhwSteady=$(awk -v m="$mhsSteady" -v w="$wSteady" 'BEGIN { if (w > 0) printf "%.4f", m / w; else printf "n/a" }') +card=$(nvidia-smi -i "$DEV" --query-gpu=name --format=csv,noheader | tr ' ' '_') +transfers=$(grep 'transfers per chunk' "$LOG" | tail -1 | sed 's/^info //') +ready=$(grep '^ready ' "$LOG" | head -1) +{ + printf 'card=%s mode=%s jobs=%d batch_log2=%d hashes=%d found=%d setup_s=%s ' "$card" "$MODE" "$JOBS" "$B" "$hashes" "$found" "$setup" + printf 'prod_wall_s=%s prod_mhs=%s prod_mean_w=%s prod_j_per_batch=%s prod_mh_per_w=%s samples=%s ' "$wallProd" "$mhsProd" "$wProd" "$jProd" "$mhwProd" "$nProd" + printf 'steady_wall_s=%s steady_mhs=%s steady_mean_w=%s steady_j_per_batch=%s steady_mh_per_w=%s samples=%s ' "$wallSteady" "$mhsSteady" "$wSteady" "$jSteady" "$mhwSteady" "$nSteady" + printf 'worker_cpu_s=%s worker_sha=%s\n' "${cpu:-n/a}" "$(sha256sum "$W" | cut -c1-16)" + printf 'ready: %s\n' "$ready" + printf 'transfers: %s\n' "$transfers" +} > "$ROW" +cat "$ROW" diff --git a/proto-cuda/nvrtc/worker.cpp b/proto-cuda/nvrtc/worker.cpp index af6976d74..f25d15382 100644 --- a/proto-cuda/nvrtc/worker.cpp +++ b/proto-cuda/nvrtc/worker.cpp @@ -1038,6 +1038,7 @@ struct Options { std::string pack, arch = "auto"; std::string race = "on", pinned, tuningPath; int raceBenchMs = 2000, raceBudgetS = 120, raceRounds = 0; // rounds 0 = 1 in --serve, 3 in --race + bool readbackFull = false; // --readback full / IGNEUM_READBACK=full: the pre-select path, 8 bytes per nonce over the bus }; static void usage() { @@ -1060,7 +1061,9 @@ static void usage() { " --race-budget-s N a race stops compiling and timing after this (default 120; base is kept)\n" " --race-rounds N interleaved rounds, best per variant (default 1 in --serve, 3 in --race)\n" " --variant use this variant without a race (also from the tuning file)\n" - " --tuning the per-card tuning file (default: IGNEUM_TUNING_FILE from the environment)\n", WORKER_VERSION); + " --tuning the per-card tuning file (default: IGNEUM_TUNING_FILE from the environment)\n" + " --readback select|full in --serve: the GPU selects the hits and 34 sentinel words come back (default), or every\n" + " 8-byte result comes back and the host scans it (the path before 8 October 2026; also IGNEUM_READBACK=full)\n", WORKER_VERSION); } static Options parseArgs(int argc, char** argv) { @@ -1087,6 +1090,7 @@ static Options parseArgs(int argc, char** argv) { else if (a == "--batch-log2") o.batchLog2 = std::atoi(next().c_str()); else if (a == "--block-warps") o.blockWarps = std::atoi(next().c_str()); else if (a == "--arch") o.arch = next(); + else if (a == "--readback") { std::string v = next(); if (v == "full") o.readbackFull = true; else if (v == "select") o.readbackFull = false; else { std::printf("--readback must be select or full\n"); std::exit(2); } } else if (a == "--no-prepare") { /* accepted for symmetry with the other workers; prepare is always on here */ } else if (a == "-h" || a == "--help") { usage(); std::exit(0); } else { std::printf("unknown argument %s\n", argv[i]); usage(); std::exit(2); } @@ -1098,6 +1102,7 @@ static Options parseArgs(int argc, char** argv) { if (o.raceBudgetS < 5 || o.raceBudgetS > 540) { std::printf("--race-budget-s must be between 5 and 540 (the prepare lead is 600 DAA)\n"); std::exit(2); } if (o.raceRounds == 0) o.raceRounds = o.raceOnly ? 3 : 1; if (o.tuningPath.empty()) if (const char* t = std::getenv("IGNEUM_TUNING_FILE")) o.tuningPath = t; + if (const char* rb = std::getenv("IGNEUM_READBACK")) if (std::strcmp(rb, "full") == 0) o.readbackFull = true; if (o.pack.empty() && !o.memprobe) { std::printf("--pack is required (igneum-miner export-pack writes one)\n"); std::exit(2); } while (o.pack.size() > 1 && (o.pack.back() == '/' || o.pack.back() == '\\')) o.pack.pop_back(); return o; @@ -1144,19 +1149,95 @@ static std::string findPackFor(const std::string& root, const std::string& epoch static std::string parentDir(const std::string& p) { size_t i = p.find_last_of("/\\"); return i == std::string::npos ? "." : p.substr(0, i); } +static uint64_t fnv1a64Bytes(const void* p, size_t n); + +// The select pass (8 October 2026, review B finding F10), the shape proto-opencl/host.c has carried since 5 October 2026. +// Before it every chunk read back 8 bytes per nonce (128 MiB for a 2^24-nonce dispatch) over the bus and the host scanned +// them under the GPU mutex. Now a tiny kernel built here by NVRTC (no pack involved, nothing in the hash path changes) +// writes the hits (index, hash word) behind an atomic counter plus 34 sentinel words (the first 32 outputs, the middle +// and the last), and the host reads back a few hundred bytes. The hash word printed is the kernel's own out[i], never +// recomputed. The found lines are printed in nonce order from the sorted hits, as the full scan printed them. A chunk +// with more hits than the table holds (a target that loose is a test or the P01 campaign, not a block) falls back to +// the full read of that chunk. The sentinels feed the stale-output detector the OpenCL worker has: two consecutive +// chunks never share the signature (different nonces or init words give different outputs), so a repeat means the +// kernel did not run. --readback full or IGNEUM_READBACK=full keeps the old path for a comparison; the select pass +// that fails to build falls back to it with an info line. +#define IG_MAX_HITS 256u +static const char* SELECT_SRC = + "// igneum-worker-cuda: the select pass (8 October 2026); the same shape as proto-opencl/host.c's igneum_select\n" + "extern \"C\" __global__ void igneum_select(const unsigned long long* out, unsigned int n, unsigned long long target, unsigned int* count,\n" + " unsigned long long* hits, unsigned int maxHits, unsigned long long* sentinel) {\n" + " unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n" + " if (i < n) {\n" + " unsigned long long h = out[i];\n" + " if (h <= target) { unsigned int k = atomicAdd(count, 1u); if (k < maxHits) { hits[2u * k] = (unsigned long long)i; hits[2u * k + 1u] = h; } }\n" + " if (i < 32u) sentinel[i] = h;\n" + " if (i == 0u) { sentinel[32] = out[n / 2u]; sentinel[33] = out[n - 1u]; }\n" + " }\n" + "}\n"; + +struct SelectPass { + bool on = false; + CUmodule mod = nullptr; + CUfunction fn = nullptr; + CUdeviceptr dCount = 0, dHits = 0, dSentinel = 0; + uint32_t hCount = 0; + uint64_t hHits[IG_MAX_HITS * 2]; + uint64_t hSentinel[34]; + unsigned long long bytesDown = 0, fullFallbacks = 0; + double kernelMsSum = 0, selectMsSum = 0, readMsSum = 0, scanMsSum = 0; + unsigned long chunks = 0; +}; + +static void releaseSelect(Ctx& c, SelectPass& s) { + if (s.dCount) c.drv.memFree(s.dCount); + if (s.dHits) c.drv.memFree(s.dHits); + if (s.dSentinel) c.drv.memFree(s.dSentinel); + if (s.mod) c.drv.moduleUnload(s.mod); + s.dCount = s.dHits = s.dSentinel = 0; s.mod = nullptr; s.fn = nullptr; s.on = false; +} + +// Builds the pass; on any failure the worker keeps the full read-back (an info line says why), never an error. +static void buildSelect(Ctx& c, SelectPass& s) { + Compiled cs; + std::string err; + if (!rtcCompile(c, SELECT_SRC, "igneum_select.cu", "", "", {}, cs, err)) { info("the select pass did not build (" + err + "); using the full read-back"); return; } + CUresult r = c.drv.moduleLoadData(&s.mod, cs.image.data()); + if (r == CUDA_SUCCESS) r = c.drv.moduleGetFunction(&s.fn, s.mod, "igneum_select"); + if (r == CUDA_SUCCESS) r = c.drv.memAlloc(&s.dCount, 4); + if (r == CUDA_SUCCESS) r = c.drv.memAlloc(&s.dHits, (size_t)IG_MAX_HITS * 2u * 8u); + if (r == CUDA_SUCCESS) r = c.drv.memAlloc(&s.dSentinel, 34u * 8u); + if (r != CUDA_SUCCESS) { info("the select pass did not load (" + c.err(r) + "); using the full read-back"); releaseSelect(c, s); return; } + s.on = true; +} + static int runServe(Ctx& c, const Options& o, Pair* cur) { const uint32_t batch = 1u << o.batchLog2; CUdeviceptr dOut = 0; std::string err; if (c.drv.memAlloc(&dOut, (size_t)batch * 8u) != CUDA_SUCCESS) { emit("error 0 cuMemAlloc out buffer"); return 2; } std::vector hOut(batch); + SelectPass sel; + if (!o.readbackFull) buildSelect(c, sel); + // IGNEUM_READBACK_FAULT_TEST=1 (test only): from the second chunk on the counter is not reset, so the hits of the + // previous chunk come back again; the equivalence check must flag it (the known-failed line of emu/select-check.sh). + const bool faultTest = std::getenv("IGNEUM_READBACK_FAULT_TEST") != nullptr; + uint64_t prevSig = 0; bool havePrevSig = false; + unsigned long jobsSeen = 0; Pair* prepared = nullptr; Pair* old = nullptr; PrepareTask* task = nullptr; std::string prepareRoot; // the parent of the last prepare's pack directory: where the miner writes its packs - emit(fmt("ready cuda %s pack %s dataset-log2 %u batch %u regs %d prepare 1 path nvrtc %d.%d driver %d.%d arch %s variant %s race %s worker %s", - c.name.c_str(), cur->seedString.c_str(), cur->datasetLog2, batch, cur->regs, c.rtcMajor, c.rtcMinor, c.driverVersion / 1000, (c.driverVersion % 100) / 10, c.archOpt.c_str(), cur->variant.c_str(), c.race.c_str(), WORKER_VERSION)); + emit(fmt("ready cuda %s pack %s dataset-log2 %u batch %u regs %d prepare 1 path nvrtc %d.%d driver %d.%d arch %s variant %s race %s readback %s worker %s", + c.name.c_str(), cur->seedString.c_str(), cur->datasetLog2, batch, cur->regs, c.rtcMajor, c.rtcMinor, c.driverVersion / 1000, (c.driverVersion % 100) / 10, c.archOpt.c_str(), cur->variant.c_str(), c.race.c_str(), sel.on ? "select" : "full", WORKER_VERSION)); + info(fmt("readback %s (per dispatch of %u nonces: %s)", sel.on ? "select" : "full", batch, sel.on ? "the hits and 34 sentinel words come back; the GPU scans" : "8 bytes per nonce come back and the host scans them")); info(fmt("first pack %s: %s", cur->dir.c_str(), pairSummary(cur).c_str())); + auto statsLine = [&]() { + if (sel.chunks == 0) return; + info(fmt("transfers per chunk: down %.0f B (%s, %llu full fallbacks); mean per chunk: kernel+sync %.2f ms, select %.3f ms, read-back %.3f ms, scan %.3f ms; %lu jobs %lu chunks", + (double)sel.bytesDown / (double)sel.chunks, sel.on ? "select" : "full", sel.fullFallbacks, + sel.kernelMsSum / (double)sel.chunks, sel.selectMsSum / (double)sel.chunks, sel.readMsSum / (double)sel.chunks, sel.scanMsSum / (double)sel.chunks, jobsSeen, sel.chunks)); + }; if (!cur->raceLine.empty()) emit(cur->raceLine); std::string line; while (std::getline(std::cin, line)) { @@ -1273,18 +1354,78 @@ static int runServe(Ctx& c, const Options& o, Pair* cur) { uint32_t block = 32u * (uint32_t)cur->blockWarps; uint32_t main = chunk - (chunk % block); CUresult r = CUDA_SUCCESS; + bool useSelect = sel.on; + double c0 = wallMs(), kernelMs = 0, selectMs = 0, readMs = 0, scanMs = 0, r0; + if (useSelect && !(faultTest && sel.chunks > 0)) { + const uint32_t zero = 0; + r = c.drv.memcpyHtoD(sel.dCount, &zero, 4); + if (r != CUDA_SUCCESS) { emit("error " + jobId + " dispatch failed: select count reset: " + c.err(r)); failed = true; break; } + } if (main > 0 && !launchHash(c, cur, dOut, lo, iw, main, block, nullptr, err)) { emit("error " + jobId + " dispatch failed: " + err); failed = true; break; } if (main < chunk) { for (uint32_t off = main; off < chunk && !failed; off += 32u) if (!launchHash(c, cur, dOut + (CUdeviceptr)off * 8u, lo + off, iw, 32u, 32u, nullptr, err)) { emit("error " + jobId + " dispatch failed: " + err); failed = true; } if (failed) break; } r = c.drv.streamSynchronize(nullptr); - if (r == CUDA_SUCCESS) r = c.drv.memcpyDtoH(hOut.data(), dOut, (size_t)chunk * 8u); - if (r != CUDA_SUCCESS) { emit("error " + jobId + " dispatch failed: " + c.err(r)); failed = true; break; } - for (uint32_t i = 0; i < chunk; ++i) if (hOut[i] <= target) { - uint64_t nonce = ((uint64_t)hi << 32) | (uint64_t)(uint32_t)(lo + i); - std::printf("found %s %llu %016llx\n", jobId.c_str(), (unsigned long long)nonce, (unsigned long long)hOut[i]); + kernelMs = wallMs() - c0; + if (r == CUDA_SUCCESS && useSelect) { + // the select pass on the same (null) stream, after every launch of the chunk, over the whole chunk including its tail + r0 = wallMs(); + uint32_t n = chunk, maxHits = IG_MAX_HITS; + unsigned long long t = target; + void* args[7] = { &dOut, &n, &t, &sel.dCount, &sel.dHits, &maxHits, &sel.dSentinel }; + r = c.drv.launchKernel(sel.fn, (n + 255u) / 256u, 1, 1, 256, 1, 1, 0, nullptr, args, nullptr); + if (r == CUDA_SUCCESS) r = c.drv.streamSynchronize(nullptr); + selectMs = wallMs() - r0; } + r0 = wallMs(); + if (r == CUDA_SUCCESS && useSelect) { + r = c.drv.memcpyDtoH(&sel.hCount, sel.dCount, 4); + sel.bytesDown += 4; + if (r == CUDA_SUCCESS) { + if (sel.hCount > IG_MAX_HITS) { + // more hits than the table holds: this chunk takes the full path (the test target case) + ++sel.fullFallbacks; + useSelect = false; + } else { + if (sel.hCount) { r = c.drv.memcpyDtoH(sel.hHits, sel.dHits, (size_t)sel.hCount * 16u); sel.bytesDown += (unsigned long long)sel.hCount * 16u; } + if (r == CUDA_SUCCESS) { r = c.drv.memcpyDtoH(sel.hSentinel, sel.dSentinel, 34u * 8u); sel.bytesDown += 34u * 8u; } + } + } + } + if (r == CUDA_SUCCESS && !useSelect) { r = c.drv.memcpyDtoH(hOut.data(), dOut, (size_t)chunk * 8u); sel.bytesDown += (unsigned long long)chunk * 8u; } + if (r != CUDA_SUCCESS) { emit("error " + jobId + " dispatch failed: " + c.err(r)); failed = true; break; } + readMs = wallMs() - r0; + // Stale output: the first, middle and last words plus an FNV of the first 32. Two chunks never share it. + // On the select path the same 34 words come from the sentinel buffer the select pass wrote. + if (chunk >= 64) { + uint64_t sig = useSelect ? (fnv1a64Bytes(sel.hSentinel, 32u * 8u) ^ sel.hSentinel[32] ^ sel.hSentinel[33]) + : (fnv1a64Bytes(hOut.data(), 32u * 8u) ^ hOut[chunk / 2] ^ hOut[chunk - 1]); + if (havePrevSig && sig == prevSig) { emit(fmt("error %s worker fault: the output buffer is unchanged since the previous dispatch (signature %016llx): the kernel did not run; exiting 3 so the miner restarts the worker", jobId.c_str(), (unsigned long long)sig)); std::exit(3); } + prevSig = sig; havePrevSig = true; + } + r0 = wallMs(); + if (useSelect) { + // nonce order, as the full scan printed them (the miner submits the first found of a job) + uint32_t nHits = sel.hCount; + for (uint32_t a = 1; a < nHits; ++a) { + uint64_t ki = sel.hHits[2 * a], kh = sel.hHits[2 * a + 1]; + uint32_t b = a; + for (; b > 0 && sel.hHits[2 * (b - 1)] > ki; --b) { sel.hHits[2 * b] = sel.hHits[2 * (b - 1)]; sel.hHits[2 * b + 1] = sel.hHits[2 * (b - 1) + 1]; } + sel.hHits[2 * b] = ki; sel.hHits[2 * b + 1] = kh; + } + for (uint32_t a = 0; a < nHits; ++a) { + uint64_t nonce = ((uint64_t)hi << 32) | (uint64_t)(uint32_t)(lo + (uint32_t)sel.hHits[2 * a]); + std::printf("found %s %llu %016llx\n", jobId.c_str(), (unsigned long long)nonce, (unsigned long long)sel.hHits[2 * a + 1]); + } + } else { + for (uint32_t i = 0; i < chunk; ++i) if (hOut[i] <= target) { + uint64_t nonce = ((uint64_t)hi << 32) | (uint64_t)(uint32_t)(lo + i); + std::printf("found %s %llu %016llx\n", jobId.c_str(), (unsigned long long)nonce, (unsigned long long)hOut[i]); + } + } + scanMs = wallMs() - r0; + sel.kernelMsSum += kernelMs; sel.selectMsSum += selectMs; sel.readMsSum += readMs; sel.scanMsSum += scanMs; ++sel.chunks; std::fflush(stdout); hashes += chunk; remaining -= chunk; @@ -1292,9 +1433,12 @@ static int runServe(Ctx& c, const Options& o, Pair* cur) { } if (failed) continue; emit(fmt("done %s %llu %.2f", jobId.c_str(), (unsigned long long)hashes, wallMs() - t0)); + if (++jobsSeen % 200 == 0) statsLine(); if (switched && old) { releasePair(c, old); old = nullptr; info("dropped the previous pair (its program, cache and dataset)"); } } + statsLine(); if (task) { task->thread.join(); if (task->result) releasePair(c, task->result); delete task; } + releaseSelect(c, sel); c.drv.memFree(dOut); if (old) releasePair(c, old); if (prepared) releasePair(c, prepared); From 342fd50aac1ea273289b2e3579b162bc6f6fd8d3 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:10:51 +0000 Subject: [PATCH 6/6] CUDA worker serve-bench: keep the coproc pid past its exit, IGNEUM_PID_DIR for the fleet pid directory Co-Authored-By: Claude Fable 5.1 --- proto-cuda/nvrtc/serve-bench.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/proto-cuda/nvrtc/serve-bench.sh b/proto-cuda/nvrtc/serve-bench.sh index bc2807f1d..62ada452e 100755 --- a/proto-cuda/nvrtc/serve-bench.sh +++ b/proto-cuda/nvrtc/serve-bench.sh @@ -8,13 +8,14 @@ # rail); the worker's own CPU seconds (utime + stime from /proc) stand in for the host-side cost of the read-back and # the scan. The kernel timer is --bench on the same pack and batch, printed beside the rows. # serve-bench.sh [jobs 32] [batch-log2 24] [device 0] -# Pid files: every process this script starts writes /pids/..pid (the fleet's rule: a job is +# Pid files: every process this script starts writes /pids/..pid (IGNEUM_PID_DIR overrides the directory) (the fleet's rule: a job is # stopped through its pid file, never by a name pattern). Output: /.row (one line, key=value) plus the # worker log, the stub's timeline and the power samples. set -euo pipefail W="$1"; PACK="$2"; OUT="$3"; RUN="$4"; MODE="$5"; JOBS="${6:-32}"; B="${7:-24}"; DEV="${8:-0}" [ "$MODE" = full ] || [ "$MODE" = select ] || { echo "readback must be full or select" >&2; exit 2; } -mkdir -p "$OUT/pids" +PIDDIR="${IGNEUM_PID_DIR:-$OUT/pids}" # the fleet keeps pid files under one directory per pod +mkdir -p "$PIDDIR" LOG="$OUT/$RUN.worker.log"; TL="$OUT/$RUN.timeline"; SMI="$OUT/$RUN.smi"; ROW="$OUT/$RUN.row" : > "$TL" now() { date +%s.%N; } @@ -27,11 +28,12 @@ jobline() { printf 'job %d %064x %s %d %d %s %s\n' "$1" "$1" "$target" $(( $1 * # power sampler first (its own pid file) nvidia-smi -i "$DEV" --query-gpu=timestamp,power.draw,clocks.sm,temperature.gpu --format=csv,noheader,nounits -lms 250 > "$SMI" 2>/dev/null & -echo $! > "$OUT/pids/$RUN.smi.pid" +echo $! > "$PIDDIR/$RUN.smi.pid" sleep 1 t0=$(now) coproc WK { IGNEUM_READBACK="$MODE" "$W" --serve --pack "$PACK" --device "$DEV" --batch-log2 "$B" --race off --readback "$MODE" 2>&1; } -echo "$WK_PID" > "$OUT/pids/$RUN.worker.pid" +wkpid=$WK_PID # bash clears WK_PID when the coproc ends; the copy outlives it +echo "$wkpid" > "$PIDDIR/$RUN.worker.pid" sent=0; done_n=0; found=0; tready=""; tlast=""; cpu="" : > "$LOG" while IFS= read -r line <&"${WK[0]}"; do @@ -43,16 +45,16 @@ while IFS= read -r line <&"${WK[0]}"; do done*) done_n=$((done_n + 1)); tlast=$t; echo "$t $line" >> "$TL" if [ "$sent" -lt "$JOBS" ]; then jobline $sent >&"${WK[1]}"; sent=$((sent + 1)); fi if [ "$done_n" -ge "$JOBS" ]; then - cpu=$(awk '{ printf "%.2f", ($14 + $15) / 100.0 }' "/proc/$WK_PID/stat" 2>/dev/null || echo "") + cpu=$(awk '{ printf "%.2f", ($14 + $15) / 100.0 }' "/proc/$wkpid/stat" 2>/dev/null || echo "") echo "quit" >&"${WK[1]}" fi ;; error*) echo "$t $line" >> "$TL" ;; esac done -wait "$WK_PID" 2>/dev/null || true +wait "$wkpid" 2>/dev/null || true t1=$(now) sleep 1 -kill "$(cat "$OUT/pids/$RUN.smi.pid")" 2>/dev/null || true +kill "$(cat "$PIDDIR/$RUN.smi.pid")" 2>/dev/null || true [ -n "$tready" ] && [ -n "$tlast" ] || { echo "FAIL: no ready or no done line; see $LOG"; tail -5 "$LOG"; exit 1; } [ "$done_n" = "$JOBS" ] || { echo "FAIL: $done_n of $JOBS jobs done; see $LOG"; exit 1; }