119 lines
8.6 KiB
Diff
119 lines
8.6 KiB
Diff
--- rename-scroll-native-bebf9f5.py
|
|
+++ rename-scroll-native-feab202.py
|
|
@@ -1,4 +1,4 @@
|
|
-"""Narrow one-launch Windows trial; prepare/launch require actual closed bebf gates."""
|
|
+"""Narrow one-launch Windows trial; prepare/launch require actual closed feab202 gates."""
|
|
from pathlib import Path
|
|
from datetime import datetime, timezone
|
|
import argparse, hashlib, json, os, re, subprocess, sys
|
|
@@ -9,9 +9,9 @@
|
|
|
|
require(__debug__, 'Python -O is forbidden')
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
-SOURCE = 'bebf9f594c6722200e95e92be2734acbea0dd700'
|
|
-PENDING_FINAL_SOURCE = True # Actual bebf preview gate failed; await reviewed test-only correction and fresh gates.
|
|
-CONFIG = ROOT / '.local/rename-scroll-native-bebf9f5.config.json'
|
|
+SOURCE = 'feab2020d8e5b6bfdb59c86ab4aee161617b8b6f'
|
|
+PENDING_FINAL_SOURCE = False # Reviewed feab202 test-only correction; actual gate admission remains mandatory.
|
|
+CONFIG = ROOT / '.local/rename-scroll-native-feab202.config.json'
|
|
def now(): return datetime.now(timezone.utc).isoformat()
|
|
def digest(raw): return {'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()}
|
|
def save(path, value):
|
|
@@ -28,7 +28,7 @@
|
|
return result
|
|
|
|
def admission():
|
|
- require(not PENDING_FINAL_SOURCE, 'Pending reviewed final source and fresh gates; bebf preview failed 4 passed / 1 failed')
|
|
+ require(not PENDING_FINAL_SOURCE, 'Pending final source admission')
|
|
watched = {}
|
|
def read(path):
|
|
raw = path.read_bytes()
|
|
@@ -51,7 +51,7 @@
|
|
gate_specs = [('list','list',None), ('preview','focused','preview_scroll_tests'), ('rename','focused','app::source_rename::tests::'), ('navigation','focused','navigation_union'), ('source-navigation','focused','source_navigation::'), ('full','full',None), ('strict','clippy',None)]
|
|
manifests, test_artifact = [], None
|
|
for stem, mode, selector in gate_specs:
|
|
- name = stem + '-bebf9f5'
|
|
+ name = stem + '-feab202'
|
|
record = value(gates / (name + '.result.json'))
|
|
admitted = value(gates / (name + '.admission.json'))
|
|
require(record['source'] == record['head_after'] == admitted['source'] == SOURCE, 'Wrong gate source: ' + name)
|
|
@@ -91,7 +91,7 @@
|
|
totals = re.findall(r'^test result: ok\. (\d+) passed; (\d+) failed; (\d+) ignored; (\d+) measured; (\d+) filtered out;', log, re.M)
|
|
require(totals == [(str(len(names)-len(ignored)), '0', str(len(ignored)), '0', str(1099-len(names)))], 'Runtime totals differ')
|
|
require(digest(read(Path(test_artifact['path']))) == {k:test_artifact[k] for k in ('bytes','sha256')}, 'Test executable changed')
|
|
- gui = gates / 'gui-bebf9f5'
|
|
+ gui = gates / 'gui-feab202'
|
|
build = value(gui / 'result.json'); environment = value(gui / 'environment.json')
|
|
require(build['source'] == build['head_after'] == SOURCE and type(build['exit']) is int and build['exit'] == 0 and build['outcome'] == 'passed' and build['failure'] is None and not build['changed_inputs'] and build['status_after'] == '', 'GUI build not closed PASS')
|
|
require(datetime.fromisoformat(build['end']) >= datetime.fromisoformat(build['start']), 'Invalid GUI closure')
|
|
@@ -125,7 +125,9 @@
|
|
blobs = git(work, 'cat-file','--batch',data=''.join(f'{SOURCE}:{p}\n' for p in paths).encode()); offset=0
|
|
entries = {i['path']:i for i in manifests[-1]['inputs']}
|
|
for path in paths:
|
|
- end=blobs.index(b'\n',offset); _,kind,size=blobs[offset:end].split(); size=int(size); raw=blobs[end+1:end+1+size]; offset=end+size+2
|
|
+ end=blobs.index(b'\n',offset); _,kind,size=blobs[offset:end].split(); size=int(size); raw=blobs[end+1:end+1+size]
|
|
+ require(blobs[end+1+size:end+2+size] == b'\n', 'Missing Git blob terminator: '+path)
|
|
+ offset=end+size+2
|
|
require(kind == b'blob' and digest(raw) == {k:entries[path][k] for k in ('bytes','sha256')} and read(work/path) == raw, 'Source bytes differ: '+path)
|
|
require(offset == len(blobs) and all(entries[i['path']] == i for i in manifests[0]['inputs']), 'Gate/GUI source disagreement')
|
|
require(not git(work,'status','--porcelain','--untracked-files=all','--',*scopes,'scripts'), 'Source worktree dirty')
|
|
@@ -135,6 +137,28 @@
|
|
attestation = {'source':SOURCE,'config':digest(read(CONFIG)),'helper':digest(Path(__file__).read_bytes()),'records':{str(p.relative_to(ROOT)):digest(raw) for p,raw in watched.items() if p.is_relative_to(ROOT) and not p.name.endswith('.exe') and not p.is_relative_to(work)},'gui':digest(executable),'runtime':digest(read(runtime_origin)),'baseline':baseline,'scope':'Closed source/build admission only; native outcome remains manual. No semantic oracle reuse.'}
|
|
return cfg, attestation, executable, read(runtime_origin)
|
|
|
|
+def capture_checkpoint_files(work, snapshot):
|
|
+ # Record every observed map, including failures; never describe an unchecked copy.
|
|
+ def observe(directory):
|
|
+ try: return files(directory), None
|
|
+ except Exception as error: return None, repr(error)
|
|
+ before, before_error = observe(work)
|
|
+ copy_error = None
|
|
+ snapshot.mkdir()
|
|
+ if before is not None:
|
|
+ try:
|
|
+ for name in before:
|
|
+ path=snapshot/name;path.parent.mkdir(parents=True,exist_ok=True)
|
|
+ with path.open('xb') as stream: stream.write((work/name).read_bytes())
|
|
+ except Exception as error:
|
|
+ copy_error=repr(error)
|
|
+ copied, snapshot_error = observe(snapshot)
|
|
+ after, after_error = observe(work)
|
|
+ consistent = before is not None and before == copied == after and not any((before_error,copy_error,snapshot_error,after_error))
|
|
+ return {'before':before,'snapshot':copied,'after':after,'before_error':before_error,
|
|
+ 'copy_error':copy_error,'snapshot_error':snapshot_error,'after_error':after_error,
|
|
+ 'copy_consistent':consistent}
|
|
+
|
|
def checkpoint(trial, stage, label):
|
|
require(re.fullmatch(r'[a-z0-9-]+',label) is not None, 'Invalid checkpoint label')
|
|
require((trial/'launch.json').is_file(), 'No owned launch')
|
|
@@ -143,11 +167,15 @@
|
|
require(preparation['source']==launch['source']==SOURCE and launch['helper']==digest(Path(__file__).read_bytes()) and launch['config']==digest(CONFIG.read_bytes()), 'Checkpoint source/helper/config changed')
|
|
destination=trial/'checkpoints'/label
|
|
destination.mkdir(parents=True,exist_ok=False)
|
|
- actual=files(trial/'source-work')
|
|
- for name in actual:
|
|
- path=destination/'snapshot'/name;path.parent.mkdir(parents=True,exist_ok=True);path.write_bytes((trial/'source-work'/name).read_bytes())
|
|
- unchanged=actual==preparation['baseline'] and files(trial/'source-baseline')==preparation['baseline']
|
|
- result={'utc':now(),'source':SOURCE,'label':label,'actual':actual,'expected':preparation['baseline'],'exact_disk_bytes_equal':unchanged,'stage_unchanged':stage_payload(stage)==preparation['payloads'],'scope':'Disk membership and complete-byte equality only; does not assert transient model/history or UI acceptance.'}
|
|
+ capture=capture_checkpoint_files(trial/'source-work',destination/'snapshot')
|
|
+ verification_error=None
|
|
+ try:
|
|
+ baseline_unchanged=files(trial/'source-baseline')==preparation['baseline']
|
|
+ stage_unchanged=stage_payload(stage)==preparation['payloads']
|
|
+ except Exception as error:
|
|
+ baseline_unchanged=stage_unchanged=False;verification_error=repr(error)
|
|
+ unchanged=capture['copy_consistent'] and capture['before']==preparation['baseline'] and baseline_unchanged
|
|
+ result={'utc':now(),'source':SOURCE,'label':label,**capture,'expected':preparation['baseline'],'baseline_unchanged':baseline_unchanged,'verification_error':verification_error,'exact_disk_bytes_equal':unchanged,'stage_unchanged':stage_unchanged,'scope':'Disk membership and complete-byte equality only; does not assert transient model/history or UI acceptance.'}
|
|
save(destination/'result.json',result);print(json.dumps(result),flush=True)
|
|
require(unchanged and result['stage_unchanged'], 'Checkpoint byte mismatch retained')
|
|
|
|
@@ -157,7 +185,7 @@
|
|
def main():
|
|
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('mode',choices=['check','prepare','launch','checkpoint']);parser.add_argument('--label');args=parser.parse_args()
|
|
cfg=json.loads(CONFIG.read_bytes());trial=ROOT/cfg['trial'];stage=ROOT/cfg['stage']
|
|
- require(not PENDING_FINAL_SOURCE, 'Pending reviewed source correction and fresh gates; no native trial admitted')
|
|
+ require(not PENDING_FINAL_SOURCE, 'Pending final source admission')
|
|
require(trial.parent == ROOT/'.local/native-qa' and stage.parent == trial.parent and trial != stage, 'Unexpected output containment')
|
|
if args.mode=='checkpoint': checkpoint(trial,stage,args.label or '');return
|
|
cfg,attestation,executable,runtime=admission()
|