diff --git a/.gitattributes b/.gitattributes index 60b6b35b..7d134b81 100644 --- a/.gitattributes +++ b/.gitattributes @@ -103,3 +103,4 @@ harness/experiments/default-policy-20260913/**/*.log -whitespace harness/experiments/default-fidelity-20260913/** -text whitespace=cr-at-eol harness/experiments/default-fidelity-20260913/**/*.log -whitespace harness/experiments/default-production-20260913/** -text whitespace=cr-at-eol +harness/experiments/default-followup-20260913/** -text whitespace=cr-at-eol diff --git a/harness/experiments/default-followup-20260913/README.md b/harness/experiments/default-followup-20260913/README.md new file mode 100644 index 00000000..34049e61 --- /dev/null +++ b/harness/experiments/default-followup-20260913/README.md @@ -0,0 +1,49 @@ +# Production follow-up verification + +Two closed native Windows captures test published source commit +`7bb366f66a8c6f8b6f66fc9b04c9e3b39f84b78e`: + +| Capture | Executed scope | Result | +| --- | --- | --- | +| `production-followup-1` | Core unit tests plus eight named source/omission integration targets | 180 passed, 0 failed, 0 ignored | +| `production-core-2` | Full `oa-core`, including its doctests | 511 passed, 0 failed, 1 ignored | + +The ignored test is `inheritance_chain_validation_scaling_probe`, an explicitly +opt-in scaling probe. These runs used Rust/Cargo 1.98.1 and the native Windows +gnullvm toolchain, locked offline dependencies and incremental compilation off. +The focused run inherited Cargo's jobs setting; the full core run set one job. +UTC execution intervals on 2026-09-13 were 11:32:40–11:36:22 and +11:36:51–11:40:23. Complete commands and environment receipts are retained. + +Both captures contain the same 613 unchanged input files. Their original +`inputs.json` SHA256 is +`b9a161be8aca264a6dcf4e7df5cbb7a4f9d999411f1da97430ec0eb3a9929566`. +The original source ZIP SHA256 is +`79dfd5167779094f30f0ee7bdcd678935f7471b294fa2193cfcfd4a5a843459c`. +These are executed snapshots, not a new inventory of the current working tree. +Later uncommitted consumer-test changes are not included in this evidence. + +`evidence.zip` preserves each gate's six original files: input manifest, source +ZIP, stdout, stderr, start receipt and result receipt. It also preserves the +exact `gate-policy.py` producer. `capture-files.json` inside that archive pins +all 13 original payloads. Outer `files.json` pins every other package file; +the publishing Git commit identifies the outer manifest. + +Run the following from this directory with Python 3.10 or newer: + +```text +python -B verify.py +``` + +Verification reads only: it checks exact memberships, duplicate ZIP entries, +hashes, fixed source/helper pins, all archived input bytes, start/result and time +consistency, commands, raw named outcomes and suite totals, compiler receipts, +and identical inputs across both runs. It never extracts files, builds code, +looks for historical binaries on the machine, or recaptures current sources. +The producer has machine-specific paths and needs adaptation for a new run. + +No binaries are distributed. The 9 and 49 compiler-artifact entries are +historical receipts, not independently rehashed runnable artifacts in this +package. This verifies core source behavior on native Windows; it does not +establish Linux, graphical workflows, public service/CLI consumers, strict +Clippy, packaging or release acceptance. diff --git a/harness/experiments/default-followup-20260913/evidence.zip b/harness/experiments/default-followup-20260913/evidence.zip new file mode 100644 index 00000000..112a58d0 Binary files /dev/null and b/harness/experiments/default-followup-20260913/evidence.zip differ diff --git a/harness/experiments/default-followup-20260913/files.json b/harness/experiments/default-followup-20260913/files.json new file mode 100644 index 00000000..f64de055 --- /dev/null +++ b/harness/experiments/default-followup-20260913/files.json @@ -0,0 +1,14 @@ +{ + "evidence.zip": { + "bytes": 4922825, + "sha256": "7f6bd834a87724db23c94ccc7f28d940c444e86d3b554f9b03aa6ab60ad38e5a" + }, + "README.md": { + "bytes": 2599, + "sha256": "06fde8da42531fb335bf9eb2f8f5ce11f561cd8fccb0a049fb2be945116c66cc" + }, + "verify.py": { + "bytes": 8631, + "sha256": "d3fb4877f05b9f8d0dd5e50f0859377c910f6862e1fa930d93852deed9afd0dd" + } +} diff --git a/harness/experiments/default-followup-20260913/verify.py b/harness/experiments/default-followup-20260913/verify.py new file mode 100644 index 00000000..efd9068c --- /dev/null +++ b/harness/experiments/default-followup-20260913/verify.py @@ -0,0 +1,128 @@ +"""Read-only verification of the two frozen production follow-up captures.""" +from pathlib import Path, PurePosixPath +from datetime import datetime +import hashlib +import io +import json +import math +import re +import zipfile + +ROOT = Path(__file__).resolve().parent +HEAD = "7bb366f66a8c6f8b6f66fc9b04c9e3b39f84b78e" +INPUTS = {"bytes": 102567, "sha256": "b9a161be8aca264a6dcf4e7df5cbb7a4f9d999411f1da97430ec0eb3a9929566"} +SOURCE_ZIP = {"bytes": 2482727, "sha256": "79dfd5167779094f30f0ee7bdcd678935f7471b294fa2193cfcfd4a5a843459c"} +HELPER = {"bytes": 3097, "sha256": "f14928bb472fc160e0a100a98139cf537380ec232626b0a7bb66f72bfc06128b"} +GATES = {"production-followup-1": (180, 0, 0, 9), "production-core-2": (511, 0, 1, 49)} +GATE_FILES = {"inputs.json", "inputs.zip", "started.json", "result.json", "stdout.log", "stderr.log"} +FOCUSED = ["language", "port_anchors", "source_project", "default_omission_fidelity", "default_omission_output", "default_omission_updates", "default_omission_preservation", "default_omission_admission"] + + +def require(condition, message): + if not condition: + raise SystemExit(message) + + +def digest(data): + return {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()} + + +def membership(archive, expected, label): + names = archive.namelist() + require(len(names) == len(set(names)), f"{label}: duplicate ZIP members") + require(set(names) == set(expected), f"{label}: ZIP membership mismatch") + require(all(not PurePosixPath(name).is_absolute() and ".." not in PurePosixPath(name).parts and "\\" not in name for name in names), f"{label}: unsafe member name") + + +manifest = json.loads((ROOT / "files.json").read_text(encoding="utf-8")) +actual = {path.relative_to(ROOT).as_posix() for path in ROOT.rglob("*") if path.is_file() and path.name != "files.json" and "__pycache__" not in path.parts} +require(actual == set(manifest) == {"README.md", "verify.py", "evidence.zip"}, "Outer membership mismatch") +for name, expected in manifest.items(): + require(digest((ROOT / name).read_bytes()) == expected, f"Outer hash mismatch: {name}") + +with zipfile.ZipFile(ROOT / "evidence.zip") as evidence: + def read_json(name): + return json.loads(evidence.read(name)) + + payloads = read_json("capture-files.json") + expected_members = {f"{gate}/{name}" for gate in GATES for name in GATE_FILES} | {"gate-policy.py"} + require(set(payloads) == expected_members, "Captured file inventory mismatch") + membership(evidence, expected_members | {"capture-files.json"}, "Evidence") + for name, expected in payloads.items(): + require(digest(evidence.read(name)) == expected, f"Capture hash mismatch: {name}") + require(digest(evidence.read("gate-policy.py")) == HELPER, "Frozen helper pin mismatch") + + snapshots = [] + times = [] + for gate, (passed, failed, ignored, artifact_count) in GATES.items(): + result = read_json(f"{gate}/result.json") + started = read_json(f"{gate}/started.json") + require(all(key in result and result[key] == value for key, value in started.items()), f"{gate}: start/result mismatch") + require(result["head"] == HEAD and result["cwd"] == "C:\\ar-default-9e8r6t", f"{gate}: source identity mismatch") + require(result["exitCode"] == 0 and result["inputsUnchanged"] is True, f"{gate}: failed or changed input receipt") + require(result["inputs"] == INPUTS and result["archive"] == SOURCE_ZIP and result["helper"] == HELPER, f"{gate}: frozen pins mismatch") + for key, name in [("inputs", "inputs.json"), ("archive", "inputs.zip"), ("stdout", "stdout.log"), ("stderr", "stderr.log")]: + require(digest(evidence.read(f"{gate}/{name}")) == result[key], f"{gate}: {key} receipt mismatch") + + start, finish = (datetime.fromisoformat(result[key]) for key in ["start", "finish"]) + duration = result["seconds"] + require(start.tzinfo is not None and finish.tzinfo is not None, f"{gate}: unzoned timestamps") + require(math.isfinite(duration) and duration >= 0 and 0 <= (finish - start).total_seconds() - duration < 30, f"{gate}: time consistency") + times.append((start, finish)) + environment = result["environment"] + require(environment["RUSTUP_TOOLCHAIN"] == "stable-x86_64-pc-windows-gnullvm" and environment["CARGO_INCREMENTAL"] == "0", f"{gate}: native Windows environment mismatch") + require(result["cargo"] == "cargo 1.98.1 (797e8a9bc 2026-08-05)" and result["rustc"] == "rustc 1.98.1 (48a229cea 2026-09-01)", f"{gate}: tool versions mismatch") + command = ["cargo", "test", "--locked", "--offline", "-p", "oa-core"] + if gate == "production-followup-1": + command += ["--lib"] + [part for target in FOCUSED for part in ["--test", target]] + require(environment["CARGO_BUILD_JOBS"] is None, f"{gate}: jobs receipt mismatch") + else: + command += ["--no-fail-fast"] + require(environment["CARGO_BUILD_JOBS"] == "1", f"{gate}: jobs receipt mismatch") + command += ["--message-format=json", "--", "--nocapture"] + require(result["command"] == command, f"{gate}: command mismatch") + + inputs = read_json(f"{gate}/inputs.json") + require(len(inputs) == result["inputCount"] == 613, f"{gate}: input count mismatch") + require({"crates/oa-core/src/source_defaults.rs", "crates/oa-core/src/source_defaults_tests.rs", "crates/oa-core/tests/default_omission_updates.rs"} <= set(inputs), f"{gate}: production inputs missing") + with zipfile.ZipFile(io.BytesIO(evidence.read(f"{gate}/inputs.zip"))) as sources: + membership(sources, inputs, f"{gate} source") + for name, expected in inputs.items(): + require(digest(sources.read(name)) == expected, f"{gate}: source hash mismatch: {name}") + snapshots.append(inputs) + + stdout = evidence.read(f"{gate}/stdout.log").decode("utf-8") + rows = [tuple(map(int, row)) for row in re.findall(r"^test result: ok\. (\d+) passed; (\d+) failed; (\d+) ignored; (\d+) measured; (\d+) filtered out;", stdout, re.M)] + totals = tuple(sum(row[index] for row in rows) for index in range(5)) + require(totals == (passed, failed, ignored, 0, 0), f"{gate}: raw summary totals mismatch: {totals}") + runs = [int(count) for count in re.findall(r"^running (\d+) tests?$", stdout, re.M)] + require(runs == [sum(row[:4]) for row in rows], f"{gate}: suite sizes mismatch") + named = re.findall(r"^test (.+?) \.\.\. (ok|FAILED|ignored(?:, [^\r\n]*)?)\r?$", stdout, re.M) + named_totals = (sum(status == "ok" for _, status in named), sum(status == "FAILED" for _, status in named), sum(status.startswith("ignored") for _, status in named)) + require(named_totals == (passed, failed, ignored), f"{gate}: raw named totals mismatch: {named_totals}") + if ignored: + require([(name, status) for name, status in named if status.startswith("ignored")] == [("inheritance_chain_validation_scaling_probe", "ignored, explicit inheritance scaling probe; run with --ignored --nocapture")], f"{gate}: ignored test mismatch") + artifacts, finished = [], [] + for line in stdout.splitlines(): + try: + item = json.loads(line) + except json.JSONDecodeError: + continue + if not isinstance(item, dict): + continue + if item.get("reason") == "compiler-artifact" and item.get("executable"): + artifacts.append(item) + if item.get("reason") == "build-finished": + finished.append(item.get("success")) + require(finished == [True], f"{gate}: successful build record mismatch") + require(len(artifacts) == len(result["artifacts"]) == artifact_count and artifacts == [entry["cargo"] for entry in result["artifacts"]], f"{gate}: compiler receipt mismatch") + for entry in result["artifacts"]: + receipt = entry["readback"] + require(isinstance(receipt, dict) and receipt.get("bytes", 0) > 0 and re.fullmatch(r"[0-9a-f]{64}", receipt.get("sha256", "")) is not None, f"{gate}: invalid historical binary receipt") + + require(snapshots[0] == snapshots[1], "Gate inputs differ") + require(times[0][1] <= times[1][0], "Gate chronology mismatch") + +print("Verified 13 captured files, two identical 613-input source captures at " + HEAD + ".") +print("Native Windows: focused 180 passed; full oa-core 511 passed, 0 failed, 1 explicitly ignored scaling probe.") +print("Recorded source/test evidence only; no binary distribution, Linux, GUI/public-consumer, Clippy or release claim.") diff --git a/harness/text-default-omission-followup-20260913.md b/harness/text-default-omission-followup-20260913.md index 4eb7da77..d4585291 100644 --- a/harness/text-default-omission-followup-20260913.md +++ b/harness/text-default-omission-followup-20260913.md @@ -1,5 +1,7 @@ # Ordinary default omission: reviewed follow-up +Subsequent [core verification](text-default-omission-followup-verified-20260913.md) now closes the compilation and core runtime gaps for published `7bb366f`. The original review boundary below is retained as historical context. + This branch-specific follow-up is based on production checkpoint `adffd19bbcf55c7cbfbf7a3937629db4c593e387`. It changes insertion storage and two language-test expectations. It is **not compiled, runtime-verified, integrated, or release-ready**. Previous runtime results in the [production report](text-default-omission-production-20260913.md) apply only to their captured inputs. ## Changes and independent review diff --git a/harness/text-default-omission-followup-verified-20260913.md b/harness/text-default-omission-followup-verified-20260913.md new file mode 100644 index 00000000..9f37eaf6 --- /dev/null +++ b/harness/text-default-omission-followup-verified-20260913.md @@ -0,0 +1,34 @@ +# Ordinary default omission: core verification recovered + +The ordinary source formatter and lossless updater at `7bb366f66a8c6f8b6f66fc9b04c9e3b39f84b78e` now pass the complete core test suite on Windows. This closes the compilation and core runtime gaps identified in the [reviewed follow-up](text-default-omission-followup-20260913.md). It does **not** establish consumer, native GUI, source8 integration, Linux, or release acceptance. + +## Evidence + +| Closed gate | Result | Scope and UTC interval | +| --- | --- | --- | +| `production-followup-1` | 180 passed, 0 failed, 0 ignored | Core library and eight selected integration targets; 11:32:40–11:36:22, 221.4 seconds | +| `production-core-2` | 511 passed, 0 failed, 1 ignored | Complete `oa-core` Cargo test invocation, including doc-tests; 11:36:51–11:40:23, 211.7 seconds | + +The selected run is a subset of the full run, not an additional 180 distinct cases. The sole ignored test is the existing opt-in `inheritance_chain_validation_scaling_probe`; it was not executed by these gates. Both commands exited successfully and recorded 613 unchanged inputs at the same published code commit. Neither stream reports a compiler warning or error. + +The private module's 22 default-policy/parser tests passed. The repaired External/MixedLegacy language expectations and guarded invalid mutations passed. The corrected port-anchor reset test reached and passed its previously unexecuted re-add checks. All three former authored-default erasure witnesses passed as ordinary enabled tests. The borrowed insertion spans therefore have compilation and affected core runtime evidence in addition to the earlier independent static review; no memory or timing improvement is inferred from whole-suite duration. + +Both captures have input-manifest SHA-256 `b9a161be8aca264a6dcf4e7df5cbb7a4f9d999411f1da97430ec0eb3a9929566` and source ZIP SHA-256 `79dfd5167779094f30f0ee7bdcd678935f7471b294fa2193cfcfd4a5a843459c`. The [portable evidence archive](experiments/default-followup-20260913/README.md) retains the original inputs, raw streams, start/end receipts and capture helper. Its read-only verifier checks membership, hashes, source contents, command outcomes and raw totals. Executable hashes are historical execution receipts; the archive does not distribute binaries. + +## Reproduction + +Environment: native Windows, Rust/Cargo 1.98.1, `stable-x86_64-pc-windows-gnullvm`, LLVM-MinGW 20260826 UCRT, locked offline dependencies, `CARGO_INCREMENTAL=0`. The full run used `CARGO_BUILD_JOBS=1`; the selected run did not set that environment variable. Use the established Windows toolchain environment setup documented by the project. + +```text +cargo test --locked --offline -p oa-core --lib --test language --test port_anchors --test source_project --test default_omission_fidelity --test default_omission_output --test default_omission_updates --test default_omission_preservation --test default_omission_admission --message-format=json -- --nocapture +cargo test --locked --offline -p oa-core --no-fail-fast --message-format=json -- --nocapture +python harness/experiments/default-followup-20260913/verify.py +``` + +The original disk-exhaustion failure remains preserved in the [earlier production archive](experiments/default-production-20260913/README.md). These successful runs follow manual disk cleanup; they do not rewrite that failed result. + +## Acceptance boundary + +Strict production Clippy and actual desktop, CLI and server consumer gates remain necessary. Static review mapped those consumers to the shared formatter/updater and identified a useful HTTP witness: an authored empty port-anchor field and comment must survive an unrelated move and restart, while canonical export omits the default. A separately reviewed test draft is outside these captured execution inputs; it is not covered by the core pass. + +The source8 ownership partition, integration decision and live work remain in Gitea issues 7 and 11. Linux checks remain user-paused. Existing native evidence for the earlier diagnostic contribution does not validate this new formatter in a GUI workflow. No release or integration completion is claimed here.