45 lines
4.0 KiB
Python
45 lines
4.0 KiB
Python
from pathlib import Path
|
|
import datetime
|
|
import hashlib
|
|
import json
|
|
import shutil
|
|
|
|
source = Path(__file__).resolve().parent
|
|
root = source.parent.parent
|
|
destination = root / '.local/canvas-union-ytr83r-20260911/harness/experiments/repair-union-windows-33e30c1-20260912'
|
|
assert not destination.exists(), 'Archive destination already exists'
|
|
destination.mkdir(parents=True)
|
|
files = [(p, p.name) for p in sorted(source.iterdir()) if p.is_file() and p.suffix in ('.json', '.log', '.ps1', '.py')]
|
|
files.extend([
|
|
(root / '.local/repair-union-windows-gates-report.md', 'REPORT.md'),
|
|
(root / '.local/run-gate.ps1', 'run-gate.ps1'),
|
|
(root / '.local/toolchain/env.ps1', 'env.ps1'),
|
|
(root / '.local/repair-union-inputs.py', 'repair-union-inputs.py'),
|
|
])
|
|
entries = []
|
|
for path, name in files:
|
|
before = path.read_bytes()
|
|
shutil.copyfile(path, destination / name)
|
|
copied = (destination / name).read_bytes()
|
|
assert before == copied == path.read_bytes(), name
|
|
entries.append({'file': name, 'source': str(path), 'bytes': len(copied), 'sha256': hashlib.sha256(copied).hexdigest()})
|
|
readme = '''# Windows saved-destination repair gate receipts
|
|
|
|
Source code: `33e30c1cd7a6c99513a0ebd02ba68fccbad8f58d` on the canvas/grapheme union. [REPORT.md](REPORT.md) is the exact original closed local report. All four serial gates passed: five focused repair tests (included within the 761 desktop all-target tests), strict all-target Clippy, and final GUI build. These counts must not be added as distinct tests.
|
|
|
|
This archive preserves exact logs, closed gate status, environment, the frozen 530-file input manifest, verification receipts, binary provenance, and the helper scripts. [archive-manifest.json](archive-manifest.json) identifies the original local sources and hashes; [archive-readback.json](archive-readback.json) records verification after copying. The original `receipt-hashes.json` predates this archive and is preserved unchanged.
|
|
|
|
No source ZIP, executable, or DLL is included. The local immutable GUI and DLL paths and hashes remain in [binary-manifest.json](binary-manifest.json); the original frozen ZIP hash is retained in [receipt-hashes.json](receipt-hashes.json). Absolute local paths in reports/status/helpers are historical evidence and are not portable published artifact links. Helpers are exact historical copies, not a standalone runnable toolchain.
|
|
|
|
Frozen input verification passed before every gate and after the build; after the parent committed the same bytes, verification additionally checked each frozen input against worktree HEAD. Parent metadata/instruction integration advanced HEAD without changing those input bytes. Native GUI interaction, packaged acceptance, and release publication were not performed by this worker and require separate evidence.
|
|
'''
|
|
(destination / 'README.md').write_text(readme, encoding='utf-8')
|
|
entries.append({'file': 'README.md', 'source': 'Authored archive navigation and scope', 'bytes': (destination / 'README.md').stat().st_size, 'sha256': hashlib.sha256((destination / 'README.md').read_bytes()).hexdigest()})
|
|
manifest = {'archived_utc': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'source_commit': '33e30c1cd7a6c99513a0ebd02ba68fccbad8f58d', 'scope': 'Exact receipt copies only; no ZIP or binaries', 'files': entries}
|
|
(destination / 'archive-manifest.json').write_text(json.dumps(manifest, indent=2) + '\n', encoding='utf-8')
|
|
for item in entries:
|
|
data = (destination / item['file']).read_bytes()
|
|
assert len(data) == item['bytes'] and hashlib.sha256(data).hexdigest() == item['sha256'], item['file']
|
|
(destination / 'archive-readback.json').write_text(json.dumps({'verified_utc': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'files': len(entries), 'pass': True, 'archive_manifest_sha256': hashlib.sha256((destination / 'archive-manifest.json').read_bytes()).hexdigest()}, indent=2) + '\n', encoding='utf-8')
|
|
print(json.dumps({'archive': str(destination), 'copied_files': len(files), 'verified_files': len(entries), 'pass': True}))
|