Files

26 lines
2.6 KiB
Python

from pathlib import Path
import hashlib,json,os,shutil,tarfile,time
R=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部');S=R/'artifacts/original-completion-2026-10-02/p23-03-native-impact-19fc3f5-r01';E=R/'docs/plans/original-completion-2026-10-02/execution/drive-offload-p23-impact-r11-20261016';E.mkdir(exist_ok=False);T=Path('/private/tmp/thetree-p23-impact-cold-r11.tar.gz');assert not T.exists();sha=lambda p:hashlib.file_digest(p.open('rb'),'sha256').hexdigest();result=json.loads((S/'runner-ended.json').read_text());assert result['error']is None and not result['cleanup_errors']and all(z['engine_ended']for z in result['cleanup']);rows=[];dirs=[]
for p in [S]+sorted(S.rglob('*')):
assert not p.is_symlink();st=p.stat();n='.'if p==S else str(p.relative_to(S));meta={'path':n,'mode':st.st_mode&0o777,'mtime_ns':st.st_mtime_ns}
if p.is_dir():dirs.append(meta)
elif p.is_file():rows.append(dict(meta,bytes=st.st_size,sha256=sha(p)))
else:raise RuntimeError('special file')
free=shutil.disk_usage(S).free;budget=free-400*1024**2;assert budget>350*1024**2
class Guard:
def __init__(self,f):self.f=f
def write(self,b):
assert self.f.tell()+len(b)<budget,'archive bounded by measured free-space budget'
return self.f.write(b)
def __getattr__(self,n):return getattr(self.f,n)
with T.open('wb') as f:
with tarfile.open(fileobj=Guard(f),mode='w:gz',compresslevel=2)as out:
for d in dirs:out.add(S if d['path']=='.'else S/d['path'],arcname=d['path'],recursive=False)
for row in rows:out.add(S/row['path'],arcname=row['path'],recursive=False)
with tarfile.open(T,'r:gz')as archive:
for row in rows:
f=archive.extractfile(row['path']);assert f and hashlib.file_digest(f,'sha256').hexdigest()==row['sha256']
record={'scope':'Ended historical P23 native impact 19fc3f5 local remainder. Preserve all raw/image/save/lifecycle bytes. Its stage was previously verified in cloud r03; existing pointer preserved, not duplicated. Restore both layers before any complete raw review. No new acceptance credit.','source':str(S),'files':rows,'directories':dirs,'archive':{'path':str(T),'bytes':T.stat().st_size,'sha256':sha(T)},'local_roundtrip_verified':True,'ended_result_sha256':sha(S/'runner-ended.json'),'free_before_archive':free,'retirement_pending_cloud_readback':True};import gzip
with gzip.open(E/'MANIFEST.json.gz','wt')as f:json.dump(record,f,ensure_ascii=False,separators=(',',':'))
(E/'PREPARATION.json').write_text(json.dumps({k:v for k,v in record.items()if k not in ['files','directories']},indent=2)+'\n');print({'files':len(rows),'logical_bytes':sum(z['bytes']for z in rows),'archive':record['archive'],'manifest':str(E/'MANIFEST.json.gz')})