docs: publish Process multiselect verification and native correction evidence
This commit is contained in:
@@ -0,0 +1 @@
|
||||
* text eol=lf
|
||||
@@ -0,0 +1,21 @@
|
||||
# Process source identity tools
|
||||
|
||||
Adapted from the State source package. The Git comparator retains its exact filtered `ls-tree` inventory and `cat-file --batch` blob-byte comparison, with `GIT_NO_LAZY_FETCH=1`. Process scope always contains 742 inputs, including all 71 vendored files and both explicit compile-time fixtures. Commit IDs must be full, explicit IDs already available locally; neither captured HEAD, timestamps nor the current working tree substitutes for comparison.
|
||||
|
||||
Validate completed raw captures without writing:
|
||||
|
||||
```powershell
|
||||
python -B prepare.py --repo CHECKOUT --raw-gates CHECKOUT/.local/process-group-gates --gate full-desktop-1 1711bff650dabb1df3a9bc37f19060d5db297feb --gate lint-2 b15345123a7feaf630ef24d45f591c76c6715778 --check-only
|
||||
```
|
||||
|
||||
For the final gate, append `--gate full-desktop-2 FULL_FINAL_COMMIT` only after its result exists and the exact final source commit is available. No final commit is guessed or hardcoded. Other completed gates may be named explicitly. Failed, missing, changed-input or mismatching source gates refuse.
|
||||
|
||||
For portable preparation, supply the completed Process `--checks CHECKS_PACKAGE`, remove `--check-only`, and add `--output NEW_SOURCE_PACKAGE`. `--raw-gates` may be omitted when using the package; supplying both requires their selected captured maps/results/archives to be equal. The output is create-only. Preparation validates all captures and Git comparisons before writing pinned manifest, newly generated source receipts, tools and files.json, then performs portable readback. Existing historical receipt files are neither consumed nor rewritten.
|
||||
|
||||
```powershell
|
||||
python -B SOURCE_PACKAGE/verify.py --checks CHECKS_PACKAGE --repo CHECKOUT
|
||||
```
|
||||
|
||||
Without `--repo`, verification validates pinned receipt/map relationships and sibling archived source capsules, but explicitly reports that Git comparison was not rerun. The sibling defaults to ../checks. The checks package must use the existing `multiselect-cargo-gates` schema. All outer/member byte pins, exact ZIP inventory and source capsule mappings are checked; selected nested source archives are checked byte-for-byte against their maps. Run the sibling checks verifier separately for complete helper/process/stream relationships. No archived executable/helper is run or extracted.
|
||||
|
||||
`manifest.json` pins the explicitly selected run/commit/map/count/fixture/receipt relationships; files.json pins all package bytes. These are consistency evidence, not independent authentication, hermetic build proof, native usability or release acceptance. Package source checks should be run with `python -B` to avoid an extra __pycache__ directory violating exact package inventory.
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
".gitattributes": {
|
||||
"bytes": 14,
|
||||
"sha256": "a79691a93b46e49ce460c26ef22afcc03d6eca1e63bf2edbc20e96159510f6c9"
|
||||
},
|
||||
"README.md": {
|
||||
"bytes": 2695,
|
||||
"sha256": "7f20dc17395af4d5f7e08c2873788de9e6dffd0d0401b11efd8a9987cb78bdac"
|
||||
},
|
||||
"manifest.json": {
|
||||
"bytes": 2462,
|
||||
"sha256": "d4a958402395d806e037dcb236e2460329db42003e72d958939133a049da8bb4"
|
||||
},
|
||||
"prepare.py": {
|
||||
"bytes": 3493,
|
||||
"sha256": "da6a1c8da417b3caf5ba44a0848cbfd64e6d299ccf2d16f3e7ae742eed69f1c6"
|
||||
},
|
||||
"source-core-3.json": {
|
||||
"bytes": 570,
|
||||
"sha256": "c0ad71de62a092df89c851c2be6e466c1f24932e43db1b8a7a2b188401ec12cf"
|
||||
},
|
||||
"source-feedback-1.json": {
|
||||
"bytes": 574,
|
||||
"sha256": "b8688707c7661d22858b2b799f6c671509f8a438069085790a2e43f0fee4aa22"
|
||||
},
|
||||
"source-full-desktop-1.json": {
|
||||
"bytes": 578,
|
||||
"sha256": "7f2f7675dc11e649a3ac3e3ee834a7dc135436747feaa789d4d7c89c41300d73"
|
||||
},
|
||||
"source-full-desktop-2.json": {
|
||||
"bytes": 578,
|
||||
"sha256": "7d34865d642f40c865ff69be1c7d744bf1660dd8f5e7a7d421d3f05c45bd446a"
|
||||
},
|
||||
"verify.py": {
|
||||
"bytes": 10094,
|
||||
"sha256": "7805832d5f563ab2d7a50dd3de700792b5d6f459c68f7b1d8bcfcc9800fa0c3a"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"kind": "process-multiselect-source",
|
||||
"runs": {
|
||||
"core-3": {
|
||||
"commit": "b743a10d51032dc1655b94fed5e49fbbbcee83f4",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "f3fd180af294e0797f9dfdbff647274de30a907b685a4fe1a2b58027bfe7da95"
|
||||
},
|
||||
"receiptPin": {
|
||||
"bytes": 570,
|
||||
"sha256": "c0ad71de62a092df89c851c2be6e466c1f24932e43db1b8a7a2b188401ec12cf"
|
||||
}
|
||||
},
|
||||
"feedback-1": {
|
||||
"commit": "b15345123a7feaf630ef24d45f591c76c6715778",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "7f5b3de4d5bb70282e424fbe90211af2ac259965aef10b05438b46076467a767"
|
||||
},
|
||||
"receiptPin": {
|
||||
"bytes": 574,
|
||||
"sha256": "b8688707c7661d22858b2b799f6c671509f8a438069085790a2e43f0fee4aa22"
|
||||
}
|
||||
},
|
||||
"full-desktop-1": {
|
||||
"commit": "1711bff650dabb1df3a9bc37f19060d5db297feb",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "d5acfcf62fb4efd4efaf073abcc7e671644a6086e9e6cf105a06034c4a27daf8"
|
||||
},
|
||||
"receiptPin": {
|
||||
"bytes": 578,
|
||||
"sha256": "7f2f7675dc11e649a3ac3e3ee834a7dc135436747feaa789d4d7c89c41300d73"
|
||||
}
|
||||
},
|
||||
"full-desktop-2": {
|
||||
"commit": "ff712b24190342363d0275467e96f181872da6ad",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "1ba4ed414b3ccbc139ad4998af77370cba994f3edf4395b80acc69d3440ccc45"
|
||||
},
|
||||
"receiptPin": {
|
||||
"bytes": 578,
|
||||
"sha256": "7d34865d642f40c865ff69be1c7d744bf1660dd8f5e7a7d421d3f05c45bd446a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": 1
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
"""Bind explicitly named Process gate captures to Git commits; no builds or checkouts."""
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
import datetime
|
||||
import json
|
||||
import re
|
||||
from verify import (HERE, TOOLS, COMPARISON, EXPLICIT_FIXTURES, need, pin, parsed,
|
||||
compare_commit, verify_data, raw_captures, packaged, verify_package)
|
||||
|
||||
def encode(value):
|
||||
return (json.dumps(value, indent=2, sort_keys=True) + "\n").encode("utf-8")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--repo", required=True, type=Path, help="repository containing the explicitly named full commit IDs")
|
||||
parser.add_argument("--raw-gates", type=Path, help="completed raw captures; required unless --checks provided")
|
||||
parser.add_argument("--checks", type=Path, help="completed portable Process checks package; required for writing")
|
||||
parser.add_argument("--gate", nargs=2, action="append", required=True, metavar=("RUN", "COMMIT"))
|
||||
parser.add_argument("--check-only", action="store_true")
|
||||
parser.add_argument("--output", type=Path, help="new source package directory")
|
||||
args = parser.parse_args()
|
||||
pairs = {}
|
||||
for run, commit in args.gate:
|
||||
need(re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]*", run) is not None, "safe gate name")
|
||||
need(re.fullmatch(r"[0-9a-f]{40}", commit) is not None, "explicit full commit ID required")
|
||||
need(run not in pairs, "duplicate gate")
|
||||
pairs[run] = commit
|
||||
need(args.raw_gates is not None or args.checks is not None, "capture input required")
|
||||
captured = packaged(args.checks, pairs) if args.checks else raw_captures(args.raw_gates, pairs)
|
||||
if args.checks and args.raw_gates:
|
||||
need(captured == raw_captures(args.raw_gates, pairs), "raw and packaged captures differ")
|
||||
specs, receipts = {}, {}
|
||||
for run, commit in pairs.items():
|
||||
map_bytes, result, _archive = captured[run]
|
||||
spec = {"commit": commit, "inputCount": 742, "inputMap": pin(map_bytes),
|
||||
"explicitCompileTimeFixtures": sorted(EXPLICIT_FIXTURES)}
|
||||
# No receipt is written until every capture and exact commit comparison passes.
|
||||
receipts[run] = encode({**spec, "gate": run, "comparison": COMPARISON,
|
||||
"checked": datetime.datetime.now(datetime.timezone.utc).isoformat()})
|
||||
specs[run] = {**spec, "receiptPin": pin(receipts[run])}
|
||||
summary = verify_data(receipts, captured, specs, args.repo)
|
||||
if args.check_only:
|
||||
need(args.output is None, "--check-only does not write output")
|
||||
print("PASS source check-only; no package written:", summary)
|
||||
return
|
||||
need(args.checks is not None and args.output is not None, "writing requires completed --checks and new --output")
|
||||
out = args.output.resolve()
|
||||
need(not out.exists(), "existing output refused")
|
||||
payload = {name:(HERE/name).read_bytes() for name in TOOLS}
|
||||
payload["manifest.json"] = encode({"schema":1, "kind":"process-multiselect-source", "runs":specs})
|
||||
payload.update({"source-"+run+".json": value for run,value in receipts.items()})
|
||||
out.mkdir(parents=True)
|
||||
for name, value in payload.items():
|
||||
with (out/name).open("xb") as stream:
|
||||
stream.write(value)
|
||||
with (out/"files.json").open("xb") as stream:
|
||||
stream.write(encode({name:pin(value) for name,value in sorted(payload.items())}))
|
||||
print("PASS written package readback:", verify_package(out,args.checks), out)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"checked": "2026-09-23T13:41:55.911287+00:00",
|
||||
"commit": "b743a10d51032dc1655b94fed5e49fbbbcee83f4",
|
||||
"comparison": "Exact committed Git blobs equal every captured input; same complete filtered inventory",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"gate": "core-3",
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "f3fd180af294e0797f9dfdbff647274de30a907b685a4fe1a2b58027bfe7da95"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"checked": "2026-09-23T13:41:55.910110+00:00",
|
||||
"commit": "b15345123a7feaf630ef24d45f591c76c6715778",
|
||||
"comparison": "Exact committed Git blobs equal every captured input; same complete filtered inventory",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"gate": "feedback-1",
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "7f5b3de4d5bb70282e424fbe90211af2ac259965aef10b05438b46076467a767"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"checked": "2026-09-23T13:41:55.910110+00:00",
|
||||
"commit": "1711bff650dabb1df3a9bc37f19060d5db297feb",
|
||||
"comparison": "Exact committed Git blobs equal every captured input; same complete filtered inventory",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"gate": "full-desktop-1",
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "d5acfcf62fb4efd4efaf073abcc7e671644a6086e9e6cf105a06034c4a27daf8"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"checked": "2026-09-23T13:41:55.911287+00:00",
|
||||
"commit": "ff712b24190342363d0275467e96f181872da6ad",
|
||||
"comparison": "Exact committed Git blobs equal every captured input; same complete filtered inventory",
|
||||
"explicitCompileTimeFixtures": [
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia"
|
||||
],
|
||||
"gate": "full-desktop-2",
|
||||
"inputCount": 742,
|
||||
"inputMap": {
|
||||
"bytes": 124276,
|
||||
"sha256": "1ba4ed414b3ccbc139ad4998af77370cba994f3edf4395b80acc69d3440ccc45"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
"""Verify pinned Process source receipts against sibling capture capsules; optionally compare Git blobs."""
|
||||
from pathlib import Path, PurePosixPath
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import zipfile
|
||||
import io
|
||||
import stat
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
COMPARISON = "Exact committed Git blobs equal every captured input; same complete filtered inventory"
|
||||
EXPLICIT_FIXTURES = {
|
||||
"harness/experiments/edge-attachments-20260922/native-fixture.arcadia",
|
||||
"harness/experiments/textual-authoring-20260911/alarm-response.arcadia",
|
||||
}
|
||||
INCLUDE_FIXTURES = True
|
||||
|
||||
|
||||
def need(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def pin(data):
|
||||
return {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
|
||||
|
||||
|
||||
def parsed(data):
|
||||
def unique(items):
|
||||
result = {}
|
||||
for key, value in items:
|
||||
need(key not in result, "duplicate JSON key: " + key)
|
||||
result[key] = value
|
||||
return result
|
||||
return json.loads(data, object_pairs_hook=unique)
|
||||
|
||||
|
||||
def safe(name):
|
||||
return (isinstance(name, str) and bool(name) and "\\" not in name and ":" not in name
|
||||
and not PurePosixPath(name).is_absolute()
|
||||
and all(part not in ("", ".", "..") for part in name.split("/")))
|
||||
|
||||
|
||||
def relevant(path):
|
||||
return (INCLUDE_FIXTURES and path in EXPLICIT_FIXTURES) or path in ("Cargo.toml", "Cargo.lock", "rust-toolchain.toml") or path.startswith(
|
||||
("crates/", "build/", ".cargo/", "scripts/", "docs/", "examples/", "harness/fixtures/", "harness/prototypes/"))
|
||||
|
||||
|
||||
def git(repo, *arguments, data=None):
|
||||
environment = dict(os.environ, GIT_NO_LAZY_FETCH="1")
|
||||
return subprocess.run(["git", *arguments], cwd=repo, input=data, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, check=True, env=environment).stdout
|
||||
|
||||
|
||||
def compare_commit(repo, commit, inputs):
|
||||
need(git(repo, "rev-parse", "--verify", commit + "^{commit}").decode().strip() == commit, "named commit unavailable")
|
||||
entries = git(repo, "ls-tree", "-r", "--full-tree", "-z", commit).split(b"\0")
|
||||
blobs = {}
|
||||
for entry in filter(None, entries):
|
||||
header, path_bytes = entry.split(b"\t", 1)
|
||||
path = path_bytes.decode("utf-8")
|
||||
if relevant(path):
|
||||
_mode, kind, oid = header.split()
|
||||
need(kind == b"blob", "relevant non-blob tree entry: " + path)
|
||||
need(path not in blobs, "duplicate tree path")
|
||||
blobs[path] = oid
|
||||
need(set(blobs) == set(inputs), "complete filtered Git inventory differs; missing="
|
||||
+ repr(sorted(set(inputs) - set(blobs))) + "; additional=" + repr(sorted(set(blobs) - set(inputs))))
|
||||
# Object IDs avoid path quoting and commit:path interpretation in batch input.
|
||||
paths = sorted(blobs)
|
||||
data = git(repo, "cat-file", "--batch", data=b"".join(blobs[path] + b"\n" for path in paths))
|
||||
offset, actual = 0, {}
|
||||
for path in paths:
|
||||
end = data.index(b"\n", offset)
|
||||
oid, kind, size_bytes = data[offset:end].split()
|
||||
size = int(size_bytes)
|
||||
need(oid == blobs[path] and kind == b"blob" and size >= 0, "Git batch object relationship")
|
||||
content = data[end + 1:end + 1 + size]
|
||||
need(len(content) == size and data[end + 1 + size:end + 2 + size] == b"\n", "Git batch framing")
|
||||
actual[path] = pin(content)
|
||||
offset = end + 2 + size
|
||||
need(offset == len(data), "trailing Git batch bytes")
|
||||
different = [path for path in paths if actual[path] != inputs[path]]
|
||||
need(not different, "captured bytes differ from named commit: " + repr(different))
|
||||
|
||||
|
||||
|
||||
def inventory(archive, expected):
|
||||
names = archive.namelist()
|
||||
need(len(names) == len(set(names)) and set(names) == set(expected), "exact ZIP inventory")
|
||||
for item in archive.infolist():
|
||||
need(safe(item.filename) and not item.is_dir() and not stat.S_ISLNK(item.external_attr >> 16), "safe ZIP member")
|
||||
need(pin(archive.read(item.filename)) == expected[item.filename], "ZIP member pin: " + item.filename)
|
||||
|
||||
def verify_data(receipts, captured, specs, repo=None):
|
||||
need(set(receipts) == set(captured) == set(specs), "exact source run inventory")
|
||||
for run, spec in specs.items():
|
||||
receipt_bytes = receipts[run]
|
||||
need(pin(receipt_bytes) == spec["receiptPin"], run + ": exact historical receipt bytes")
|
||||
receipt = parsed(receipt_bytes)
|
||||
need(receipt["gate"] == run and receipt["comparison"] == COMPARISON, run + ": receipt identity")
|
||||
need(all(receipt[key] == spec[key] for key in ("commit", "inputCount", "inputMap", "explicitCompileTimeFixtures")), run + ": pinned receipt relationships")
|
||||
map_bytes, result, archive_bytes = captured[run]
|
||||
need(pin(map_bytes) == spec["inputMap"] == result["inputs"], run + ": exact captured input map")
|
||||
need(result["exitCode"] == 0 and result["inputsUnchanged"] is True, run + ": accepted unchanged gate")
|
||||
inputs = parsed(map_bytes)
|
||||
need(len(inputs) == 742, run + ": Process 742-input scope required")
|
||||
need(len(inputs) == spec["inputCount"] == result["inputCount"], run + ": input counts")
|
||||
need(spec["explicitCompileTimeFixtures"] == (sorted(EXPLICIT_FIXTURES) if INCLUDE_FIXTURES else []), run + ": exact fixture scope")
|
||||
need(all(safe(name) and relevant(name) for name in inputs), run + ": input scope")
|
||||
need((EXPLICIT_FIXTURES & set(inputs)) == (EXPLICIT_FIXTURES if INCLUDE_FIXTURES else set()), run + ": explicit fixture membership")
|
||||
need(sum(name.startswith("crates/vendor/iced_widget/") for name in inputs) == 71, run + ": vendor count")
|
||||
need(pin(archive_bytes) == result["archive"], run + ": source capsule pin")
|
||||
with zipfile.ZipFile(io.BytesIO(archive_bytes)) as archive:
|
||||
inventory(archive, inputs)
|
||||
if repo is not None:
|
||||
compare_commit(repo, spec["commit"], inputs)
|
||||
print("PASS", run, spec["commit"], len(inputs), "source pins" + (" and exact Git blobs" if repo is not None else " (Git comparison not rerun)"))
|
||||
return {"runs": len(specs), "gitCompared": repo is not None}
|
||||
|
||||
def raw_captures(gates, specs):
|
||||
return {run: ((gates/run/"inputs.json").read_bytes(), parsed((gates/run/"result.json").read_bytes()),
|
||||
(gates/run/"inputs.zip").read_bytes()) for run in specs}
|
||||
|
||||
def packaged(checks, specs):
|
||||
files = parsed((checks/"files.json").read_bytes())
|
||||
need(set(files) == {"prepare.py", "verify.py", "README.md", "manifest.json", "evidence.zip"}, "checks outer inventory")
|
||||
for name, expected in files.items():
|
||||
need(pin((checks/name).read_bytes()) == expected, "checks outer pin: " + name)
|
||||
manifest = parsed((checks/"manifest.json").read_bytes())
|
||||
need(manifest["schema"] == 1 and manifest["kind"] == "multiselect-cargo-gates", "checks kind")
|
||||
logical, members = manifest["logicalFiles"], manifest["members"]
|
||||
need(all(safe(name) and safe(target) for name,target in logical.items()) and set(logical.values()) == set(members), "checks logical inventory")
|
||||
captured = {}
|
||||
with zipfile.ZipFile(checks/"evidence.zip") as archive:
|
||||
inventory(archive, members)
|
||||
for run in specs:
|
||||
prefix = "cargo/" + run + "/"
|
||||
result = parsed(archive.read(logical[prefix + "result.json"]))
|
||||
spec = manifest["runs"][run]
|
||||
need(all(result[key] == spec[key] for key in ("command", "head", "exitCode", "inputCount")), run + ": checks relationships")
|
||||
for name in ("inputs.json", "inputs.zip"):
|
||||
member = logical[prefix+name]
|
||||
need(member == "capsules/" + members[member]["sha256"] + Path(name).suffix, run + ": source capsule mapping")
|
||||
captured[run] = (archive.read(logical[prefix+"inputs.json"]), result, archive.read(logical[prefix+"inputs.zip"]))
|
||||
return captured
|
||||
|
||||
|
||||
TOOLS = {".gitattributes", "prepare.py", "verify.py", "README.md"}
|
||||
|
||||
def specifications(manifest):
|
||||
import re
|
||||
need(manifest.get("schema") == 1 and manifest.get("kind") == "process-multiselect-source", "source manifest kind")
|
||||
specs = manifest["runs"]
|
||||
need(isinstance(specs, dict) and bool(specs), "nonempty explicit source run inventory")
|
||||
for run, spec in specs.items():
|
||||
need(isinstance(run, str) and re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]*", run), "safe source gate")
|
||||
need(isinstance(spec["commit"], str) and re.fullmatch(r"[0-9a-f]{40}", spec["commit"]), "full explicit commit required")
|
||||
need(spec["inputCount"] == 742 and spec["explicitCompileTimeFixtures"] == sorted(EXPLICIT_FIXTURES), "fixed Process input scope")
|
||||
return specs
|
||||
|
||||
def verify_package(package, checks, repo=None):
|
||||
files = parsed((package/"files.json").read_bytes())
|
||||
manifest = parsed((package/"manifest.json").read_bytes())
|
||||
specs = specifications(manifest)
|
||||
expected = TOOLS | {"manifest.json"} | {"source-"+run+".json" for run in specs}
|
||||
need(set(files) == expected, "source outer inventory")
|
||||
need({p.name for p in package.iterdir()} == expected | {"files.json"}, "source exact package inventory")
|
||||
for name, value in files.items():
|
||||
need((package/name).is_file() and not (package/name).is_symlink() and pin((package/name).read_bytes()) == value, "source outer pin: " + name)
|
||||
receipts = {run:(package/("source-"+run+".json")).read_bytes() for run in specs}
|
||||
return verify_data(receipts, packaged(checks, specs), specs, repo)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("package", nargs="?", type=Path, default=HERE)
|
||||
parser.add_argument("--checks", type=Path, help="completed sibling checks package; default ../checks")
|
||||
parser.add_argument("--repo", type=Path, help="repeat exact named-commit Git inventory/blob comparison")
|
||||
args = parser.parse_args()
|
||||
print("PASS source evidence:", verify_package(args.package, args.checks or args.package.parent/"checks", args.repo))
|
||||
print("No builds or archived helper execution. Run checks verifier separately for full process/log relationships.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user