Record matching navigation GUI build and focused coordination entrypoints
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
"""Prepare/launch the identified Windows GUI and preserve native trial checkpoints.
|
||||
|
||||
All actual GUI interaction is performed separately with Computer Use.
|
||||
"""
|
||||
import argparse
|
||||
import datetime
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
evidence = Path(__file__).resolve().parent
|
||||
trial = root / ".local/text-navigation-native-20260911"
|
||||
fixtures = root / ".local/text-navigation-native-20260911-preparation"
|
||||
runtime = root / ".local/toolchain/llvm-mingw-20260826-ucrt-x86_64/bin/libunwind.dll"
|
||||
oracle = root / ".local/staged-source-oracle-20260911/staged-source-authoring-contract.exe"
|
||||
runtime_sha = "f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4"
|
||||
oracle_sha = "967d9ba3c6fb3a7efb410833903ec94556ca2d48a67d5072c8bb160f40a00f9c"
|
||||
fixture_manifest_sha = "edd4157fc31823f4494dee91862728b87f12ef51c49b8d1fd86a954bc9ecc1ed"
|
||||
|
||||
def sha(path):
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
def now():
|
||||
return datetime.datetime.now(datetime.timezone.utc).isoformat()
|
||||
|
||||
def record(path, value):
|
||||
with path.open("x", encoding="utf-8", newline="\n") as out:
|
||||
json.dump(value, out, indent=2, ensure_ascii=False)
|
||||
out.write("\n")
|
||||
|
||||
def inventory(folder):
|
||||
result = {}
|
||||
for path in folder.rglob("*"):
|
||||
assert not path.is_symlink() and not (getattr(path.lstat(), "st_file_attributes", 0) & 0x400), path
|
||||
if path.is_file():
|
||||
result[path.relative_to(folder).as_posix()] = sha(path)
|
||||
return result
|
||||
|
||||
def environment():
|
||||
parent = {key.upper(): value for key, value in os.environ.items()}
|
||||
names = ("SystemRoot", "SystemDrive", "ProgramData", "ALLUSERSPROFILE", "PUBLIC")
|
||||
standard = {name: parent[name.upper()] for name in names}
|
||||
assert all("%" not in value for value in standard.values())
|
||||
system = standard["SystemRoot"]
|
||||
return {**standard, "WINDIR": system, "PATH": system + "\\System32;" + system,
|
||||
"USERPROFILE": str(trial / "profile"), "LOCALAPPDATA": str(trial / "profile/local"),
|
||||
"APPDATA": str(trial / "profile/roaming"), "TEMP": str(trial / "tmp"), "TMP": str(trial / "tmp")}
|
||||
|
||||
def verify_fixtures():
|
||||
manifest = fixtures / "fixture-manifest.json"
|
||||
assert sha(manifest) == fixture_manifest_sha
|
||||
for entry in json.loads(manifest.read_text(encoding="utf-8")):
|
||||
path = (fixtures / entry["path"]).resolve()
|
||||
assert path.is_relative_to(fixtures) and path.stat().st_size == entry["bytes"]
|
||||
assert sha(path) == entry["sha256"], entry["path"]
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("action", choices=("launch", "check", "closed"))
|
||||
parser.add_argument("--label")
|
||||
parser.add_argument("--model", choices=("valid", "release1"), default="valid")
|
||||
args = parser.parse_args()
|
||||
if args.action == "launch":
|
||||
verify_fixtures()
|
||||
receipt_path = evidence / "gui-build-v2.json"
|
||||
receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
|
||||
preserved = json.loads((evidence / "gui-preserved.json").read_text(encoding="utf-8"))
|
||||
assert preserved["buildReceiptSha256"] == sha(receipt_path)
|
||||
binary = Path(preserved["binary"]).resolve()
|
||||
assert binary == evidence / "gui-v2.exe"
|
||||
assert preserved["sha256"] == receipt["sha256"]
|
||||
assert sha(binary) == receipt["sha256"]
|
||||
assert sha(runtime) == runtime_sha and sha(oracle) == oracle_sha
|
||||
trial.mkdir(exist_ok=False)
|
||||
for folder in ("bin", "profile/local", "profile/roaming", "profile/Desktop", "tmp", "screenshots"):
|
||||
(trial / folder).mkdir(parents=True)
|
||||
shutil.copy2(binary, trial / "bin/arcadia-studio.exe")
|
||||
shutil.copy2(runtime, trial / "bin/libunwind.dll")
|
||||
for source, destination in (("valid-baseline", "valid"), ("release1-baseline", "release1"),
|
||||
("ambiguous-open", "ambiguous"), ("missing-include-open", "missing-include")):
|
||||
shutil.copytree(fixtures / source, trial / destination)
|
||||
before = inventory(trial / "bin")
|
||||
record(trial / "binary-before.json", before)
|
||||
record(trial / "source-before.json", {name: inventory(trial / name) for name in ("valid", "release1", "ambiguous", "missing-include")})
|
||||
env = environment()
|
||||
startup = subprocess.STARTUPINFO()
|
||||
startup.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
startup.wShowWindow = 0
|
||||
with (trial / "stdout.log").open("xb") as out, (trial / "stderr.log").open("xb") as err:
|
||||
process = subprocess.Popen([str(trial / "bin/arcadia-studio.exe")], cwd=trial / "bin",
|
||||
env=env, stdout=out, stderr=err, startupinfo=startup)
|
||||
launch = {"atUtc": now(), "pid": process.pid, "binarySha256": receipt["sha256"],
|
||||
"buildReceiptSha256": sha(receipt_path), "source": str(trial / "valid/project.arcadia"),
|
||||
"environment": env, "scope": "Identified local Windows GUI; native verification pending"}
|
||||
record(trial / "launch.json", launch)
|
||||
print(json.dumps(launch, ensure_ascii=False))
|
||||
elif args.action == "check":
|
||||
verify_fixtures()
|
||||
assert args.label and args.label.replace("-", "").isalnum()
|
||||
assert inventory(trial / "bin") == json.loads((trial / "binary-before.json").read_text(encoding="utf-8"))
|
||||
assert sha(oracle) == oracle_sha
|
||||
checkpoint = trial / (args.label + "-sources")
|
||||
shutil.copytree(trial / args.model, checkpoint)
|
||||
env = environment()
|
||||
env["PATH"] = str(trial / "bin") + ";" + env["PATH"]
|
||||
command = [str(oracle), "same", str(fixtures / (args.model + "-baseline") / "project.arcadia"), str(checkpoint / "project.arcadia")]
|
||||
result = subprocess.run(command, capture_output=True, env=env)
|
||||
(trial / (args.label + ".stdout.log")).write_bytes(result.stdout)
|
||||
(trial / (args.label + ".stderr.log")).write_bytes(result.stderr)
|
||||
receipt = {"atUtc": now(), "command": command, "exitCode": result.returncode,
|
||||
"oracleSha256": oracle_sha, "files": inventory(checkpoint),
|
||||
"binaryFilesUnchanged": True, "scope": "Complete saved Project/identity, reachable sources and physical Arcadia equality"}
|
||||
record(trial / (args.label + ".json"), receipt)
|
||||
print(result.stdout.decode("utf-8", errors="replace"))
|
||||
print(json.dumps({"label": args.label, "exitCode": result.returncode}))
|
||||
if result.returncode:
|
||||
print(result.stderr.decode("utf-8", errors="replace"))
|
||||
raise SystemExit(result.returncode)
|
||||
else:
|
||||
# The caller must observe process closure independently before this readback.
|
||||
before = json.loads((trial / "binary-before.json").read_text(encoding="utf-8"))
|
||||
after = inventory(trial / "bin")
|
||||
record(trial / "binary-after-close.json", {"atUtc": now(), "files": after, "unchanged": before == after})
|
||||
assert before == after
|
||||
print(json.dumps({"binaryFilesUnchanged": True, "files": len(after)}))
|
||||
Reference in New Issue
Block a user