Files
ARCADIA-Studio/harness/experiments/navigation-440-windows-20260913/archive-builder.py
T

121 lines
8.9 KiB
Python

from pathlib import Path
import ast, hashlib, json, re, subprocess
ORIGIN = Path('C:/Users/User/Documents/Git/ARCADIA-Studio')
ROOT = Path('C:/ar-nav440-evidence-956atf')
SOURCE = '44095f78c28b79d6d085863dc928adba8e24d955'
BASE = '355f6d4d244e6b57fd89a8afd80a2dacdea69ba1'
REL = Path('harness/experiments/navigation-440-windows-20260913')
ARCHIVE = ROOT / REL
assert not ARCHIVE.exists()
GATES = ORIGIN / '.local/navigation-palette-gates-20260913'
def sha(raw): return hashlib.sha256(raw).hexdigest()
def read(path): return json.loads(path.read_bytes())
def git(*args): return subprocess.check_output(['git','-c','core.longpaths=true',*args],cwd=ROOT)
assert git('rev-parse','HEAD').decode().strip() == BASE
raws = sorted(p for p in GATES.glob('*-44095f7.*') if p.is_file())
assert len(raws) == 43, len(raws)
raws += [GATES/'artifacts-44095f7'/n for n in ('result.json','inputs.json','environment.json','cargo.jsonl','cargo.stderr.log')]
raws += [ORIGIN/n for n in ('.local/run-navigation-palette-gate.py', '.local/run-navigation-service-gate.py',
'.local/build-navigation-palette-artifacts.py', '.local/admit-navigation-selection-gate.py',
'.local/navigation-palette-required-tests-20260913.json', '.local/audit-navigation-service-gates-44095f7.py',
'.local/navigation-service-gates-44095f7-audit.json', '.local/navigation-service-gates-44095f7-review.md',
'.local/toolchain/env.ps1')]
assert len(raws) == len(set(raws))
desktop = {}
manual = [
'app::source_rename::timing_tests::accepted_release1_prepare_commit_sync_and_confirm_timing',
'app::source_rename::timing_tests::layout_timing_tests::accepted_release1_constructor_vs_reuse_through_next_highlight',
'app::source_symbols::tests::source_symbols_100_modules_1000_definitions_10000_uses']
listed = read(GATES/'list-44095f7.result.json')
names = listed['listing_members']; assert len(names) == len(set(names)) == 1098
required = read(ORIGIN/'.local/navigation-palette-required-tests-20260913.json')['groups']
new_names = None
for node in ast.walk(ast.parse((ORIGIN/'.local/admit-navigation-selection-gate.py').read_text())):
if isinstance(node,ast.Assign) and any(isinstance(t,ast.Name) and t.id=='new_names' for t in node.targets):
new_names = ast.literal_eval(node.value)
assert len(new_names)==16
baseline_rel = Path('harness/experiments/navigation-palette-e124029-windows-20260913/gates/list-e124029.result.json')
baseline = read(ROOT/baseline_rel)
assert len(baseline['listing_members'])==1082 and set(names)==set(baseline['listing_members'])|set(new_names)
selectors = {'full':None,'navigation':'navigation_union','scroll':'preview_scroll_tests',
'symbols':'app::source_symbols','rename-escape':'actual_captured_escape_closes_only_its_priority_owner_and_retains_worker'}
for mode in ('list','full','strict','navigation','scroll','symbols','rename-escape'):
r=read(GATES/f'{mode}-44095f7.result.json')
assert r['source']==r['head_after']==SOURCE and r['exit']==0 and not r['changed_inputs']
log=(GATES/f'{mode}-44095f7.log').read_text()
assert not re.search(r'^(error|warning)(\[|:)',log,re.M)
prefix=['cargo','test','--locked','-p','oa-desktop','--bin','arcadia-studio']
expected = ['cargo','clippy','--locked','-p','oa-desktop','--all-targets','--','-D','warnings'] if mode=='strict' else prefix+(['--','--list'] if mode=='list' else ([selectors[mode]] if selectors[mode] else [])+['--','--test-threads=1'])
assert r['command']==expected
outcomes=None
if mode!='strict':
assert r['artifacts']==listed['artifacts']
if mode!='list':
rows=re.findall(r'^test ([^\r\n]+) \.\.\. (ok|FAILED|ignored)(?:, [^\r\n]*)?$',log,re.M)
outcomes=dict(rows); assert len(rows)==len(outcomes)
wanted=[n for n in names if selectors[mode] is None or selectors[mode] in n]
assert [n for n,_ in rows]==wanted
assert all(v==('ignored' if n in manual else 'ok') for n,v in rows)
totals=[sum(v==status for _,v in rows) for status in ('ok','FAILED','ignored')]
assert re.findall(r'^test result: ok\. (\d+) passed; (\d+) failed; (\d+) ignored; 0 measured; (\d+) filtered out;',log,re.M)==[tuple(map(str,totals+[1098-len(rows)]))]
if mode=='full': assert all(outcomes[n]=='ok' for n in new_names)
if mode in ('navigation','scroll'): assert set(outcomes)==set(required[selectors[mode]])
desktop[mode]={'result_file':f'raw/.local/navigation-palette-gates-20260913/{mode}-44095f7.result.json','outcomes':outcomes,'command':r['command'],'start':r['start'],'end':r['end']}
build=read(GATES/'artifacts-44095f7/result.json')
assert build['source']==build['head_after']==SOURCE and build['exit']==0 and build['outcome']=='passed' and build['failure'] is None and not build['changed_inputs']
assert build['command'][1:]==['build','--locked','--offline','-p','oa-desktop','-p','oa-server','--bins','--message-format=json-render-diagnostics']
for key,filename in [('inputs','inputs.json'),('environment','environment.json'),('stdout','cargo.jsonl'),('stderr','cargo.stderr.log')]:
data=(GATES/'artifacts-44095f7'/filename).read_bytes(); assert build[key]=={'bytes':len(data),'sha256':sha(data)}
assert build['launcher']=={'bytes':(ORIGIN/'.local/build-navigation-palette-artifacts.py').stat().st_size,'sha256':sha((ORIGIN/'.local/build-navigation-palette-artifacts.py').read_bytes())}
cargo=[json.loads(line) for line in (GATES/'artifacts-44095f7/cargo.jsonl').read_text().splitlines()]
assert cargo[-1]=={'reason':'build-finished','success':True}
assert {a['name'] for a in build['artifacts']}=={'arcadia-studio','arcadia-server'}
for a in build['artifacts']:
raw=Path(a['preserved']).read_bytes(); assert len(raw)==a['bytes'] and sha(raw)==a['sha256']
assert a['cargo_artifact'] in cargo
assert a['cargo_artifact']['profile']=={'opt_level':'0','debuginfo':0,'debug_assertions':True,'overflow_checks':True,'test':False}
for path in raws:
if path.name.endswith('.admission.json'):
a=read(path); stem=path.name.removesuffix('.admission.json')
assert a['source']==SOURCE and a['verified_inputs']==581
for key,suffix in [('result_sha256','.result.json'),('log_sha256','.log'),('inputs_sha256','.inputs.json')]:
assert a[key]==sha((GATES/(stem+suffix)).read_bytes())
maps=[]
for path in raws:
if path.name.endswith('.inputs.json') or path==GATES/'artifacts-44095f7/inputs.json':
m=read(path); assert m['source']==SOURCE
assert len(m['inputs'])==(615 if path.name=='inputs.json' else 581)
maps.append(m)
for m in maps:
assert all(item in maps[0]['inputs'] for item in m['inputs']) if len(m['inputs'])==581 else True
unique={i['path']:i for m in maps for i in m['inputs']};assert len(unique)==615
scopes=['Cargo.toml','Cargo.lock','rust-toolchain.toml','.cargo','build','crates','assets','docs','examples','harness/fixtures','scripts']
assert sorted(unique)==git('ls-tree','-r','--name-only',SOURCE,*scopes).decode().splitlines()
assert not git('diff','--name-only',SOURCE,BASE,'--',*scopes)
specs=[f'{SOURCE}:{p}' for p in sorted(unique)]
blobs=subprocess.check_output(['git','cat-file','--batch'],cwd=ROOT,input=('\n'.join(specs)+'\n').encode());offset=0
for p in sorted(unique):
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
assert kind==b'blob' and unique[p]=={'path':p,'bytes':len(raw),'sha256':sha(raw)} and (ROOT/p).read_bytes()==raw
assert offset==len(blobs)
ARCHIVE.mkdir(parents=True)
entries=[]
def write(rel,raw,origin):
dst=ROOT/rel;dst.parent.mkdir(parents=True,exist_ok=True)
with dst.open('xb') as f:f.write(raw)
assert dst.read_bytes()==raw
entries.append({'path':rel.as_posix(),'bytes':len(raw),'sha256':sha(raw),'origin':origin})
for path in raws:
original=path.relative_to(ORIGIN)
write(REL/'raw'/original,path.read_bytes(),{'kind':'verbatim original','repository_relative_local_path':original.as_posix()})
audit={'source':SOURCE,'publication_base':BASE,'source_scope_identical_to_base':scopes,'unique_build_inputs':615,'gate_inputs':581,
'desktop':desktop,'desktop_listing':names,'new_16_passed':new_names,'manual_desktop_cases':manual,
'baseline_listing':{'path':baseline_rel.as_posix(),'sha256':sha((ROOT/baseline_rel).read_bytes())},
'build_artifacts_omitted':build['artifacts'],'service_audit':'raw/.local/navigation-service-gates-44095f7-audit.json',
'scope':'Actual closed 440 Windows gates only; not native/package/release acceptance or a later source correction.'}
write(REL/'runtime-audit.json',(json.dumps(audit,indent=2)+'\n').encode(),{'kind':'generated readback from original records'})
write(REL/'.gitattributes',b'* -text\n',{'kind':'generated byte-preservation policy'})
(ROOT/'.local/archive-entries.json').write_text(json.dumps(entries,indent=2)+'\n')
print(json.dumps({'originals':len(raws),'raw_bytes':sum(p.stat().st_size for p in raws),'entries':len(entries),'unique_inputs':len(unique)}))