igneum/tools/ci/test-map-merge.py
igneum-labs 8b55835a7d 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 <noreply@anthropic.com>
2026-10-08 19:06:04 +00:00

44 lines
2.7 KiB
Python
Executable file

#!/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 <base.json> <master.json> <branch.json> <out.json>; --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")