Remaster twenty-one original pictures and preserve complete review evidence

This commit is contained in:
raptorreplica committed 2026-10-18 12:46:27 +11:00
1 parent 6b1a2629a0
commit e0d114e657
237 files changed
+576164 -73

No files matched your search

+180
View File
@@ -0,0 +1,180 @@
"""Replay a checked batch of existing boss cleanup recipes without new pixel math.
Each frame is passed to the hash-bound hd_boss_cleanup.run_recipe unchanged.
This dispatcher records actual subruns and binds one outer portable recipe.
It does not approve artwork or register assets.
"""
from __future__ import annotations
import argparse
import hashlib
import importlib
import json
from pathlib import Path
import sys
METHOD = "derived-generated-boss-source-geometry-batch-v1"
def sha(path):
return hashlib.sha256(Path(path).read_bytes()).hexdigest()
def digest(value):
return (type(value) is str and len(value) == 64
and all(c in "0123456789abcdef" for c in value))
def contained(base, value):
if type(value) is not str or not value or "\\" in value:
raise ValueError("expected portable relative path")
path = Path(value)
if path.is_absolute() or any(part in (".", "..") for part in path.parts):
raise ValueError("expected contained relative path")
result = (base / path).resolve()
if not result.is_relative_to(base.resolve()) or not result.is_file():
raise ValueError("missing or escaped input")
return result
def checked_ref(base, value):
if type(value) is not dict or set(value) != {"path", "sha256"} or not digest(value["sha256"]):
raise ValueError("expected path/sha256 binding")
path = contained(base, value["path"])
if sha(path) != value["sha256"]:
raise ValueError("input hash mismatch")
return path
def plan(recipe_path, project):
recipe_path = Path(recipe_path).resolve()
recipe = json.loads(recipe_path.read_bytes())
if (type(recipe) is not dict or set(recipe) != {
"format_version", "kind", "method", "cleanup_tool", "decoder", "frames"}
or type(recipe["format_version"]) is not int or recipe["format_version"] != 1
or recipe["kind"] != "boss_cleanup_reproduce_batch" or recipe["method"] != METHOD):
raise ValueError("unsupported batch recipe")
project = Path(project).resolve()
for field, expected in [("cleanup_tool", "tools/hd_boss_cleanup.py"),
("decoder", "tools/hd_frame_policy.py")]:
if type(recipe[field]) is not dict or recipe[field].get("path") != expected:
raise ValueError("unsupported cleanup implementation")
checked_ref(project, recipe[field])
frames = recipe["frames"]
if type(frames) is not list or not 1 <= len(frames) <= 32:
raise ValueError("expected bounded nonempty frame list")
planned, seen = [], set()
for frame in frames:
if type(frame) is not dict or set(frame) != {"asset", "recipe", "expected_output_sha256"}:
raise ValueError("invalid batch frame")
asset = frame["asset"]
if (type(asset) is not str or not 1 <= len(asset) <= 8
or any(c not in "0123456789abcdef" for c in asset) or asset in seen
or not digest(frame["expected_output_sha256"])):
raise ValueError("invalid or duplicate asset/output binding")
seen.add(asset)
subpath = checked_ref(recipe_path.parent, frame["recipe"])
sub = json.loads(subpath.read_bytes())
if type(sub) is not dict or sub.get("asset") != asset:
raise ValueError("subrecipe asset mismatch")
# Validate all declared input bodies before creating any output directory.
for key in ("source", "palette", "parent_raw"):
value = sub.get(key)
if type(value) is not dict or set(value) != {"path", "sha256"} or not digest(value["sha256"]):
raise ValueError("invalid subrecipe input binding")
p = Path(value["path"])
if not p.is_absolute():
p = subpath.parent / p
if not p.is_file() or sha(p) != value["sha256"]:
raise ValueError("subrecipe input hash mismatch")
planned.append((frame, subpath, sub))
return recipe, planned
def run_batch(recipe_path, output, project):
recipe_path, output, project = Path(recipe_path).resolve(), Path(output), Path(project).resolve()
if output.exists():
raise ValueError("output exists; do not overwrite old outputs")
initial_recipe_sha256 = sha(recipe_path)
recipe, planned = plan(recipe_path, project)
if sha(recipe_path) != initial_recipe_sha256:
raise ValueError("batch recipe changed during planning")
sys.path.insert(0, str(project / "tools"))
cleanup = importlib.import_module("hd_boss_cleanup")
decoder = importlib.import_module("hd_frame_policy")
if (Path(cleanup.__file__).resolve() != project / "tools/hd_boss_cleanup.py"
or Path(decoder.__file__).resolve() != project / "tools/hd_frame_policy.py"
or sha(cleanup.__file__) != recipe["cleanup_tool"]["sha256"]
or sha(decoder.__file__) != recipe["decoder"]["sha256"]):
raise ValueError("loaded implementation differs from bound tools")
output.mkdir(parents=True)
subruns, sources, parents, outputs = [], {}, set(), {}
def verify_pinned_inputs():
if sha(recipe_path) != initial_recipe_sha256:
raise ValueError("batch recipe changed during execution")
checked_ref(project, recipe["cleanup_tool"])
checked_ref(project, recipe["decoder"])
for pinned_frame, pinned_path, pinned_sub in planned:
if sha(pinned_path) != pinned_frame["recipe"]["sha256"]:
raise ValueError("subrecipe changed during execution")
for key in ("source", "palette", "parent_raw"):
value = pinned_sub[key]
path = Path(value["path"])
if not path.is_absolute():
path = pinned_path.parent / path
if sha(path) != value["sha256"]:
raise ValueError("subrecipe input changed during execution")
verify_pinned_inputs()
for frame, subpath, sub in planned:
verify_pinned_inputs()
asset = frame["asset"]
destination = output / asset
report = cleanup.run_recipe(subpath, destination)
png = destination / f"{asset}-derived.png"
actual = sha(png)
if actual != frame["expected_output_sha256"]:
raise ValueError(f"accepted PNG not reproduced: {asset}")
expected_execution = {"status": "success",
"method": "derived-generated-boss-source-geometry-rgb-preserved-v1",
"recipe_sha256": frame["recipe"]["sha256"],
"tool_sha256": recipe["cleanup_tool"]["sha256"],
"source_sha256": {asset: sub["source"]["sha256"]},
"parent_raw_sha256": [sub["parent_raw"]["sha256"]],
"output_sha256": {asset: actual}}
if type(report) is not dict or report.get("execution") != expected_execution:
raise ValueError("subrun execution receipt differs from pinned inputs")
verify_pinned_inputs()
sources[asset] = sub["source"]["sha256"]
parents.add(sub["parent_raw"]["sha256"])
outputs[asset] = actual
provenance = destination / "derived-provenance.json"
subruns.append({"asset": asset, "recipe": frame["recipe"],
"execution": report["execution"],
"provenance": {"path": f"{asset}/derived-provenance.json", "sha256": sha(provenance)}})
verify_pinned_inputs()
result = {"format_version": 1, "kind": "boss_cleanup_actual_batch_execution",
"execution": {"status": "success", "method": METHOD,
"recipe_sha256": initial_recipe_sha256, "tool_sha256": sha(__file__),
"source_sha256": sources, "parent_raw_sha256": sorted(parents),
"output_sha256": outputs},
"actual_dispatcher_calls": 1, "actual_cleanup_subruns": len(subruns),
"subruns": subruns, "cleanup_tool": recipe["cleanup_tool"], "decoder": recipe["decoder"],
"scope": "Bookkeeping replay only; existing cleanup pixel algorithm unchanged; no approval/registration."}
(output / "batch-execution.json").write_text(json.dumps(result, indent=2, sort_keys=True) + "\n")
return result
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("recipe", type=Path)
parser.add_argument("output_new_directory", type=Path)
parser.add_argument("project", type=Path)
args = parser.parse_args()
report = run_batch(args.recipe, args.output_new_directory, args.project)
print(json.dumps(report["execution"], sort_keys=True))
if __name__ == "__main__":
main()
+105
View File
@@ -0,0 +1,105 @@
"""Private derived-RGB singleton cleanup with declared Original functional cells.
The reviewed DSHP renderer preserves broad parent RGB and supplies SourceScale4
coverage. Only explicitly listed painted logical cells then receive actual
Original Scale4 RGBA. This is derived artwork, never untouched generation.
"""
import argparse
import hashlib
import io
import json
import sys
from pathlib import Path
import numpy as np
from PIL import Image
R = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(R / 'tools'))
import hd_dshp20_cleanup as base
BASE_SHA = 'c6123e9591f0a169846677019ddcb944bf9c2b4c9184a7d8ab02a08546de409b'
DECODER_SHA = '66184a4758027dadbadb5e20fe90b2add2b9fc218b7810304b1a1ea2de74f58e'
METHOD = 'derived-parent-full-RGB-SourceScale4-geometry-explicit-functional-Original-v1'
def digest(b): return hashlib.sha256(b).hexdigest()
def dependency_pins():
tool = Path(base.__file__).resolve()
decoder = Path(base.hd_frame_policy.__file__).resolve()
assert digest(tool.read_bytes()) == BASE_SHA
assert digest(decoder.read_bytes()) == DECODER_SHA
return dict(RGB_geometry_tool=dict(path=str(tool), sha256=BASE_SHA),
Source_decoder=dict(path=str(decoder), sha256=DECODER_SHA))
def retain_functional_original(rgba, source, palette, cells):
"""Copy the whole actual Scale4 kernel footprint, including transparency."""
h, w = source.shape
if not isinstance(cells, list) or not 1 <= len(cells) <= 64:
raise ValueError('need1..64 explicit functional Original cells')
for xy in cells:
if (not isinstance(xy, list) or len(xy) != 2 or any(type(v) is not int for v in xy)
or not 0 <= xy[0] < w or not 0 <= xy[1] < h or not 0 <= source[xy[1], xy[0]] < 256):
raise ValueError('functional cell must be exact integer inbounds painted Source')
if cells != sorted(cells) or len({tuple(xy) for xy in cells}) != len(cells):
raise ValueError('functional cells must be sorted and unique')
if rgba.shape != (h*4, w*4, 4) or rgba.dtype != np.uint8:
raise ValueError('need complete native-times4 uint8 RGBA canvas')
s4 = base.scale2(base.scale2(source))
mask = np.zeros(s4.shape, bool)
for x, y in cells: mask[y*4:(y+1)*4, x*4:(x+1)*4] = True
original = np.zeros_like(rgba)
painted = s4 < 256
original[:,:,:3][painted] = palette[s4[painted]]
original[:,:,3][painted] = 255
out = rgba.copy()
out[mask] = original[mask]
assert np.array_equal(out[~mask], rgba[~mask])
assert np.array_equal(out[mask], original[mask])
return out, dict(cells=cells, Source_indices=[int(source[y,x]) for x,y in cells],
actual_Original_Scale4_RGBA_samples=int(mask.sum()),
actual_Original_transparent_samples=int((mask & ~painted).sum()),
RGBA_changes=int(np.any(out != rgba, axis=2).sum()),
outside_explicit_footprints_RGBA_exact=True,
retained_Original_not_generated_HD=True)
def run_recipe(recipe_path, output):
recipe_path, output = Path(recipe_path), Path(output)
if output.exists(): raise ValueError('fresh absent output directory required')
dependencies = dependency_pins()
rb = recipe_path.read_bytes(); recipe = json.loads(rb)
if (not isinstance(recipe, dict) or set(recipe) != {'format_version','geometry_recipe','functional_original_cells'}
or type(recipe['format_version']) is not int or recipe['format_version'] != 1):
raise ValueError('exact wrapper recipe fields/version required')
geometry = recipe['geometry_recipe']
if not isinstance(geometry, dict) or not isinstance(geometry.get('frames'), list) or len(geometry['frames']) != 1:
raise ValueError('this private wrapper supports one complete singleton per recipe')
arrays, report = base.render_family(geometry, recipe_path.resolve().parent)
frame = geometry['frames'][0]
_, payload = base.checked(frame['source'], recipe_path.resolve().parent)
w,h,cells = base._indices(payload)
source = np.asarray(cells,np.uint16).reshape(h,w)
_, pb = base.checked(geometry['palette'], recipe_path.resolve().parent)
p6 = np.frombuffer(pb,np.uint8).reshape(256,3).astype(np.uint16)
palette = ((p6 << 2) | (p6 >> 4)).astype(np.uint8)
rgba, functional = retain_functional_original(arrays[0], source, palette, recipe['functional_original_cells'])
encoded = io.BytesIO(); Image.fromarray(rgba).save(encoded, format='PNG', compress_level=9)
png = encoded.getvalue(); asset = frame['asset']
execution = dict(status='success', method=METHOD, recipe_sha256=digest(rb),
tool_sha256=digest(Path(__file__).read_bytes()), source_sha256={asset:frame['source']['sha256']},
parent_raw_sha256=[frame['raw_png']['sha256']], output_sha256={asset:digest(png)})
report.update(method=METHOD, geometry_method=base.METHOD, dependencies=dependencies,
functional_Original=functional, execution=execution,
output=dict(asset=asset, file=asset+'-derived.png', sha256=digest(png),
RGBA_sha256=digest(rgba.tobytes()), size=[w*4,h*4]),
scope='DERIVED broad generated RGB, SourceScale4 geometry and explicit retained Original functional cells; no game-context or art acceptance.')
output.mkdir(parents=True)
(output/(asset+'-derived.png')).write_bytes(png)
(output/'derived-provenance.json').write_text(json.dumps(report,indent=2,sort_keys=True)+'\n')
(output/'normalized-execution.json').write_text(json.dumps(execution,indent=2,sort_keys=True)+'\n')
return report
if __name__ == '__main__':
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('recipe',type=Path);parser.add_argument('output_new_directory',type=Path)
args=parser.parse_args(); result=run_recipe(args.recipe,args.output_new_directory)
print(json.dumps(result['execution'],sort_keys=True))
+142
View File
@@ -0,0 +1,142 @@
"""Synthetic dispatcher tests; never execute cleanup pixel processing."""
import importlib.util
import json
from pathlib import Path
import tempfile
from types import SimpleNamespace
import unittest
from unittest.mock import patch
spec = importlib.util.spec_from_file_location("batch", Path(__file__).with_name("hd_boss_cleanup_reproduce.py"))
batch = importlib.util.module_from_spec(spec)
spec.loader.exec_module(batch)
class BatchTests(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.addCleanup(self.tmp.cleanup)
self.root = Path(self.tmp.name)
self.project = self.root / "project"
(self.project / "tools").mkdir(parents=True)
self.base = self.root / "job"
self.base.mkdir()
for n in ["hd_boss_cleanup.py", "hd_frame_policy.py"]:
(self.project / "tools" / n).write_text("# synthetic bound implementation\n")
for n in ["source", "raw", "palette"]:
(self.base / n).write_bytes(n.encode())
def ref(p, base): return {"path": str(p.relative_to(base)), "sha256": batch.sha(p)}
self.doc = {"format_version": 1, "kind": "boss_cleanup_reproduce_batch", "method": batch.METHOD,
"cleanup_tool": ref(self.project / "tools/hd_boss_cleanup.py", self.project),
"decoder": ref(self.project / "tools/hd_frame_policy.py", self.project), "frames": []}
for asset in ["abc", "abd"]:
sub = {"asset": asset, "source": ref(self.base / "source", self.base),
"parent_raw": ref(self.base / "raw", self.base), "palette": ref(self.base / "palette", self.base)}
p = self.base / f"{asset}.json"
p.write_text(json.dumps(sub))
self.doc["frames"].append({"asset": asset, "recipe": ref(p, self.base),
"expected_output_sha256": __import__('hashlib').sha256(asset.encode()).hexdigest()})
self.recipe = self.base / "batch.json"
self.save()
def save(self): self.recipe.write_text(json.dumps(self.doc))
def test_preflight_rejects_bad_tool_before_any_output(self):
self.doc["cleanup_tool"]["sha256"] = "0" * 64
self.save()
with self.assertRaises(ValueError): batch.run_batch(self.recipe, self.base / "out", self.project)
self.assertFalse((self.base / "out").exists())
def test_duplicate_asset_rejected(self):
self.doc["frames"][1] = self.doc["frames"][0].copy()
self.save()
with self.assertRaises(ValueError): batch.plan(self.recipe, self.project)
def test_escaped_recipe_rejected(self):
self.doc["frames"][0]["recipe"]["path"] = "../outside.json"
self.save()
with self.assertRaises(ValueError): batch.plan(self.recipe, self.project)
def test_wrong_subrecipe_asset_rejected(self):
self.doc["frames"][0]["asset"] = "abe"
self.save()
with self.assertRaises(ValueError): batch.plan(self.recipe, self.project)
def test_changed_source_rejected_before_output(self):
(self.base / "source").write_bytes(b"changed")
with self.assertRaises(ValueError): batch.run_batch(self.recipe, self.base / "out", self.project)
self.assertFalse((self.base / "out").exists())
def fake_cleanup(self, subpath, output):
sub = json.loads(subpath.read_text()); asset = sub["asset"]
output.mkdir()
(output / f"{asset}-derived.png").write_bytes(asset.encode())
result = {"execution": {"status": "success", "method": "derived-generated-boss-source-geometry-rgb-preserved-v1", "recipe_sha256": batch.sha(subpath),
"tool_sha256": self.doc["cleanup_tool"]["sha256"], "source_sha256": {asset: sub["source"]["sha256"]},
"parent_raw_sha256": [sub["parent_raw"]["sha256"]],
"output_sha256": {asset: batch.sha(output / f"{asset}-derived.png")}}}
(output / "derived-provenance.json").write_text(json.dumps(result))
return result
def fake_import(self, name):
return SimpleNamespace(__file__=str(self.project / "tools" / f"{name}.py"), run_recipe=self.fake_cleanup)
def test_actual_aggregate_uses_unique_parent_and_per_asset_outputs(self):
with patch.object(batch.importlib, "import_module", side_effect=self.fake_import):
result = batch.run_batch(self.recipe, self.base / "out", self.project)
e = result["execution"]
self.assertEqual(result["actual_cleanup_subruns"], 2)
self.assertEqual(e["recipe_sha256"], batch.sha(self.recipe))
self.assertEqual(e["tool_sha256"], batch.sha(batch.__file__))
self.assertEqual(e["parent_raw_sha256"], [batch.sha(self.base / "raw")])
self.assertEqual(set(e["source_sha256"]), {"abc", "abd"})
self.assertEqual(e["output_sha256"], {r["asset"]: r["expected_output_sha256"] for r in self.doc["frames"]})
def test_wrong_accepted_png_does_not_write_success_receipt(self):
self.doc["frames"][0]["expected_output_sha256"] = "0" * 64
self.save()
with patch.object(batch.importlib, "import_module", side_effect=self.fake_import):
with self.assertRaises(ValueError): batch.run_batch(self.recipe, self.base / "out", self.project)
self.assertFalse((self.base / "out/batch-execution.json").exists())
def test_existing_output_is_never_overwritten(self):
output = self.base / "out"; output.mkdir(); sentinel = output / "old"; sentinel.write_text("old")
with self.assertRaises(ValueError): batch.run_batch(self.recipe, output, self.project)
self.assertEqual(sentinel.read_text(), "old")
def test_all_subrun_execution_fields_must_match_pinned_inputs(self):
original = self.fake_cleanup
fields = ["status", "method", "recipe_sha256", "tool_sha256", "source_sha256", "parent_raw_sha256", "output_sha256"]
for number, field in enumerate(fields):
with self.subTest(field=field):
def contradictory(path, output):
report = original(path, output)
report['execution'][field] = "contradiction"
return report
with patch.object(batch.importlib, "import_module", side_effect=self.fake_import), patch.object(self, "fake_cleanup", side_effect=contradictory):
output = self.base / f"bad-{number}"
with self.assertRaises(ValueError): batch.run_batch(self.recipe, output, self.project)
self.assertFalse((output / 'batch-execution.json').exists())
def test_batch_recipe_edit_during_subrun_prevents_success(self):
original = self.fake_cleanup
def changed(path, output):
report = original(path, output)
self.recipe.write_text(self.recipe.read_text() + ' ')
return report
with patch.object(batch.importlib, "import_module", side_effect=self.fake_import), patch.object(self, "fake_cleanup", side_effect=changed):
with self.assertRaises(ValueError): batch.run_batch(self.recipe, self.base / "out", self.project)
self.assertFalse((self.base / 'out/batch-execution.json').exists())
def test_subrecipe_edit_during_subrun_prevents_success(self):
original = self.fake_cleanup
def changed(path, output):
report = original(path, output)
path.write_text(path.read_text() + ' ')
return report
with patch.object(batch.importlib, "import_module", side_effect=self.fake_import), patch.object(self, "fake_cleanup", side_effect=changed):
with self.assertRaises(ValueError): batch.run_batch(self.recipe, self.base / "out", self.project)
self.assertFalse((self.base / 'out/batch-execution.json').exists())
if __name__ == "__main__": unittest.main()
+69
View File
@@ -0,0 +1,69 @@
import hashlib
import importlib.util
import json
from pathlib import Path
import struct
import tempfile
import unittest
import numpy as np
from PIL import Image
spec=importlib.util.spec_from_file_location('other_cleanup',Path(__file__).with_name('hd_other_functional_cleanup.py'))
c=importlib.util.module_from_spec(spec);spec.loader.exec_module(c)
class FunctionalOriginalTests(unittest.TestCase):
def palette(self):
p=np.arange(768,dtype=np.uint16).reshape(256,3)%64
return ((p<<2)|(p>>4)).astype(np.uint8)
def pattern(self,h,w):
y,x=np.indices((h*4,w*4));a=np.zeros((h*4,w*4,4),np.uint8)
a[:,:,:3]=np.stack([(x//4)*33+25,(y//4)*27+40,(x*7+y*3)%230],axis=-1);a[:,:,3]=255
return a
def test_only_declared_ordinary31_and_gray15_footprints_replace_full_RGB(self):
s=np.full((4,5),15,np.uint16);s[:,:2]=31;a=self.pattern(4,5);p=self.palette()
out,report=c.retain_functional_original(a,s,p,[[1,1],[3,2]])
mask=np.zeros((16,20),bool);mask[4:8,4:8]=True;mask[8:12,12:16]=True
self.assertTrue(np.array_equal(out[~mask],a[~mask]));self.assertTrue(np.array_equal(a,self.pattern(4,5)))
self.assertTrue(np.all(out[4:8,4:8,:3]==p[31]));self.assertTrue(np.all(out[8:12,12:16,:3]==p[15]))
self.assertEqual(report['actual_Original_Scale4_RGBA_samples'],32)
def test_kernel_footprint_retains_real_Original_transparency_not_NN_point_color(self):
s=np.array([[256,256,1],[256,31,1],[1,1,1]],np.uint16);a=self.pattern(3,3)
out,r=c.retain_functional_original(a,s,self.palette(),[[1,1]])
s4=c.base.scale2(c.base.scale2(s));expected=np.zeros((4,4,4),np.uint8);q=s4[4:8,4:8];painted=q<256
expected[:,:,:3][painted]=self.palette()[q[painted]];expected[:,:,3][painted]=255
self.assertTrue(np.array_equal(out[4:8,4:8],expected));self.assertGreater(r['actual_Original_transparent_samples'],0)
self.assertLess(int((out[4:8,4:8,3]>0).sum()),16)
def test_zero_typed_out_of_bounds_transparent_duplicate_or_unsorted_selectors_rejected(self):
s=np.full((4,5),10,np.uint16);s[0,0]=256;a=self.pattern(4,5)
invalid=[[],[[True,1]],[[1.0,1]],[[5,1]],[[-1,1]],[[1,4]],[[0,0]],[[1,1],[1,1]],[[3,2],[1,1]]]
for cells in invalid:
with self.subTest(cells=cells),self.assertRaises(ValueError):c.retain_functional_original(a,s,self.palette(),cells)
self.assertTrue(np.array_equal(a,self.pattern(4,5)))
def test_broad_gradient_and_panel_edges_are_exact_outside_small_retention(self):
s=np.full((10,12),10,np.uint16);s[9,2]=31;a=self.pattern(10,12)
out,_=c.retain_functional_original(a,s,self.palette(),[[2,9]])
self.assertTrue(np.array_equal(out[:36],a[:36]));self.assertTrue(np.array_equal(out[36:,:8],a[36:,:8]))
self.assertGreater(len(np.unique(out[:36,:,:3].reshape(-1,3),axis=0)),100)
def test_reviewed_base_and_decoder_dependencies_are_bound(self):
d=c.dependency_pins();self.assertEqual(d['RGB_geometry_tool']['sha256'],c.BASE_SHA);self.assertEqual(d['Source_decoder']['sha256'],c.DECODER_SHA)
def test_once_output_normalized_lineage_input_immutability_and_deterministic_PNG(self):
with tempfile.TemporaryDirectory() as td:
root=Path(td);source=np.full((3,4),10,np.uint16);source[1,1]=31
b=bytearray(struct.pack('<5i',0,1,31,4,3))
for y in range(3):b.extend(struct.pack('<4i',0,y,y*4,4));b.extend(bytes(source[y].tolist()))
b.extend(struct.pack('<4i',0,0,-1,0));(root/'source.pic').write_bytes(b)
(root/'palette').write_bytes(bytes((np.arange(768)%64).astype(np.uint8)))
Image.fromarray(self.pattern(3,4)).save(root/'parent.png')
def bind(n):return dict(path=n,sha256=hashlib.sha256((root/n).read_bytes()).hexdigest())
geometry=dict(format_version=1,palette=bind('palette'),output_scale=4,max_fill_distance_pixels=12,shared_backing_anchor=0,
frames=[dict(asset='102f7',source=bind('source.pic'),raw_png=bind('parent.png'),viewport=[0,0,16,12],sampling_offset_native=[0,0],origin=[0,0])])
recipe=dict(format_version=1,geometry_recipe=geometry,functional_original_cells=[[1,1]])
rp=root/'recipe.json';rp.write_text(json.dumps(recipe));before={p:p.read_bytes()for p in root.iterdir()}
report=c.run_recipe(rp,root/'out1');c.run_recipe(rp,root/'out2')
self.assertEqual((root/'out1/102f7-derived.png').read_bytes(),(root/'out2/102f7-derived.png').read_bytes())
self.assertEqual(set(report['execution']),{'status','method','recipe_sha256','tool_sha256','source_sha256','parent_raw_sha256','output_sha256'})
self.assertEqual(report['functional_Original']['Source_indices'],[31])
for p,data in before.items():self.assertEqual(p.read_bytes(),data)
with self.assertRaisesRegex(ValueError,'fresh absent'):c.run_recipe(rp,root/'out1')
if __name__=='__main__':unittest.main(verbosity=2)