CHAT_OUTPUT_BEGIN
COMMAND_ID=NEWFI-260920-NEWFDOM-MESSENGERS214-BASE213
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=newfi-newfdom-messengers214-backupv2-base-release-authority-aware-readonly
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
COMMAND_SHA256=65d18e767349b7319c7197b07d4122dae093e606f12244bfd676798e5606e937
DUPLICATE_FAILED_COMMAND_BLOCKED=false
EXECUTION_STARTED=true
CHANGE_DECLARED=false
RESULT_CONTRACT_VALID=true
RESULT_CONTRACT_STATUS=NOT_APPLICABLE
RESULT_CONTRACT_ERROR=NONE
COMMAND_RC=0
CHANGES_MADE=false
ROLLBACK_STARTED=false
ROLLBACK_RESTORED=null
MUTATION_OUTCOME=NO_MUTATION
SANITIZED=yes
SECRETS_INCLUDED=no
PRIVATE_ADDRESSES_INCLUDED=no
RAW_EVIDENCE_SHA256=417d54bc3ee03b085ea2894f80cd2f3c4e8df0652fe89b0f35fa9f5df73e61c3
SANITIZED_OUTPUT_SHA256=c2da47960582cda8715a7fd595b714f908f504dd277254ed2b277fdb5c900bf3
OUTPUT_BEGIN
NEWFI213_BEGIN=true
MODE=read-only
IMMUTABLE_PLAN_CHECK=PASS
CHANGES_MADE=false
MUTATION_OUTCOME=NO_MUTATION
RUNNER_SHA256=b248a4c32c9cc64e5747e7dce6c7fc0a23f5124a77c71ce72e27a81aceae9d2d
RUNNER_PIN_MATCH=true
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
ERROR_REGISTER_PIN_MATCH=true
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
REFERENCE_PIN_MATCH=true
WRAPPER_SHA256=5077444065c732451cb84898680f62361b21a24ef9eb4f191253e82ead524ea2
WRAPPER_PIN_MATCH=true
OVERLAY_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793
OVERLAY_PIN_MATCH=true
PRODUCTION_ACCEPTANCE_SHA256=708a481f6719ff1ed8d0afec1902650ed36ac631e980611b015419f504f16df0
PRODUCTION_ACCEPTANCE_PIN_MATCH=true
AUTHORITY_PIN_MATCH=true
BACKUP_SOURCE_PIN_MATCH=true
ACCEPTED_RELEASE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1
BASE_RELEASE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1
MATCHING_FILE_COUNT=26
FILE_1_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/ACCEPTANCE.json
FILE_1_BYTES=517
FILE_1_SHA256=904dfccad43b55ad0b53cfbd29fb45fee36fd0fbfa5afa58da5c3cca0ee7153b
FILE_1_CONTEXT_LINE_COUNT=1
FILE_1_L1={"command_id":"SUPPORT-260916-INFRA-DR-BACKUPV2-FINAL-REPLACEMENT-PLAN-STABILITY-SCHEMA-RCA-FIX-VALIDATE-PROMOTE-CUTOVER-SEAL-486R1","ct112_manifest_sha256":"1ac4f16a54bcdd8b896c9a131abef966d315256aa56da3f83ed0b30845c4fcb0","ct112_payload_bytes":223875308,"ct112_payload_sha256":"d443b85e76e806830fd9c372d0a09fc5b91ca9c9d35c44fb0ad7968cc996d01d","legacy_ids":["node-pve01","md-relay","spb-ingress","us-netbird","router-netcraze","xf-codevipe","xf-zakrutim","control-bootstrap-v2"],"representative_pass":9,"schema":1}
FILE_2_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/RELEASE_MANIFEST.json
FILE_2_BYTES=3301
FILE_2_SHA256=a36dd0db88592ec3d355ef43e6b218da6c9ad649e9ccf8c8f680b96eb23a156e
FILE_2_CONTEXT_LINE_COUNT=1
FILE_2_L1={"files":{"ACCEPTANCE.json":{"bytes":517,"mode":256,"sha256":"904dfccad43b55ad0b53cfbd29fb45fee36fd0fbfa5afa58da5c3cca0ee7153b"},"candidate411/CONTRACT.json":{"bytes":2077,"mode":256,"sha256":"a414715f1b91b3701c52073709a80c38218f76e3961618e8af61489211e50c01"},"candidate411/PLAN265_REFERENCE.json":{"bytes":7210,"mode":256,"sha256":"8d36e82080be93a8c929a9211191fa868166b9e7b6152c4c7689fa52b6720757"},"candidate411/PROVENANCE.json":{"bytes":4310,"mode":256,"sha256":"303f44dc8e91c8e6a675f9ea406ce4b7532ed98440a9b6807fa593ede9d33254"},"candidate411/adapter.py":{"bytes":2989,"mode":320,"sha256":"18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3"},"candidate411/guest266.py":{"bytes":7385,"mode":256,"sha256":"86433bc424d5fa5017c20f7a237c82874b02357a3283660d8a6b0039ef2bc868"},"candidate411/large264.py":{"bytes":16514,"mode":256,"sha256":"5cc4641fc35e4dd554495a36146da7dbbb7f142d1450e04cc5d3c89678b8497a"},"candidate411/nodeplan263.py":{"bytes":4603,"mode":256,"sha256":"db5c16ee24d25aa
FILE_3_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/ct112_handler.py
FILE_3_BYTES=10955
FILE_3_SHA256=8cac6e627d5e7abe5d3163cdd24911995a1e3f45c776f9373c2aa68784f5ec6c
FILE_3_CONTEXT_LINE_COUNT=98
FILE_3_L1=#!/usr/bin/env python3
FILE_3_L2=from __future__ import annotations
FILE_3_L3=import hashlib,json,os,secrets,shutil,stat,subprocess,sys,time
FILE_3_L4=from pathlib import Path
FILE_3_L5=ROOT=Path(__file__).resolve().parent
FILE_3_L6=CAND=ROOT/'candidate411'
FILE_3_L7=if str(CAND) not in sys.path:sys.path.insert(0,str(CAND))
FILE_3_L8=import guest266,large264 as large,pve265,pve282,transport261 as t,v2core as core
FILE_3_L9=CT_ID='guest-pve01-lxc-112'
FILE_3_L10=PLAN=CAND/'PLAN265_REFERENCE.json'
FILE_3_L11=PLAN_SHA='8d36e82080be93a8c929a9211191fa868166b9e7b6152c4c7689fa52b6720757'
FILE_3_L12=RCLONE=Path('/usr/bin/rclone'); RCLONE_SHA='20df3d5eac5d4e187ce638e4216354e7fa6778c3c51f0caf48c48acca9686354'
FILE_3_L13=RCLONE_CFG=Path('/root/.config/rclone/[SENSITIVE_FILE]')
FILE_3_L14=BINDING_FP='ed48c1345771c3e0f50db9516f13f26bb66047283e2f883d5df272f15e2282b8'
FILE_3_L15=VZDUMP=Path('/usr/bin/vzdump'); VZDUMP_SHA='21339d009afd55cb7ec613b64c1f493b2a7dbd18b85b4d712909ef6d6710f4ea'
FILE_3_L16=ZSTD=Path('/usr/bin/zstd'); ZSTD_SHA='3eb7744cf8fd1ecd46d617098ee870b3e7911fe570ffaba662c1c5b7d6456020'
FILE_3_L26=    p=subprocess.run(argv,stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=45,check=False,env=ENV)
FILE_3_L27=    if p.returncode!=0 or len(p.stdout)>4*1024*1024:raise RuntimeError('PVESH_READ_FAILED')
FILE_3_L28=    try:return json.loads(p.stdout.decode('utf-8','strict'))
FILE_3_L29=    except (ValueError,UnicodeError):raise RuntimeError('PVESH_JSON') from None
FILE_3_L30=
FILE_3_L31=def _baseline():
FILE_3_L32=    b=t.read_secure(PLAN,1024*1024,private=True)[0]
FILE_3_L33=    if t.sha(b)!=PLAN_SHA:raise RuntimeError('PLAN_REFERENCE_IDENTITY')
FILE_3_L34=    try:return json.loads(b.decode('utf-8','strict'))
FILE_3_L35=    except (ValueError,UnicodeError):raise RuntimeError('PLAN_REFERENCE_JSON') from None
FILE_3_L36=
FILE_3_L37=def _defaults():
FILE_3_L38=    p=Path('/etc/vzdump.conf');st=os.stat(p,follow_symlinks=False)
FILE_3_L100=    return {'path':str(path),'sha256':want}
FILE_3_L101=
FILE_3_L102=def _private_config():
FILE_3_L103=    b,identity=t.read_secure(RCLONE_CFG,t.MAX_CONFIG_BYTES,private=True)
FILE_3_L104=    text=b.decode('utf-8-sig','strict');entries=core.inventory_from_config(text);binding=t.binding(text)
FILE_3_L105=    if len(entries)!=13 or len({x['account_id'] for x in entries})!=13:raise RuntimeError('RCLONE_INVENTORY')
FILE_3_L106=    if hashlib.sha256(binding.encode()).hexdigest()!=BINDING_FP:raise RuntimeError('RCLONE_BINDING')
FILE_3_L107=    return b,entries,binding
FILE_3_L108=
FILE_3_L109=def _write_private(path,data):
FILE_3_L118=class LazyReader:
FILE_3_L119=    def __init__(self,work,entries,binding,guard,deadline,logical_id):
FILE_3_L120=        self.work=Path(work);self.entries=entries;self.binding=binding;self.guard=guard;self.deadline=deadline;self.logical_id=logical_id
FILE_3_L121=        self.snapshot=self.work/'rclone.snapshot';self.inner=None
FILE_3_L122=    def _ensure(self):
FILE_3_L123=        if self.inner is not None:return self.inner
FILE_3_L124=        b,e,bind=_private_config()
FILE_3_L125=        if e!=self.entries or bind!=self.binding:raise RuntimeError('RCLONE_SEMANTIC_DRIFT')
FILE_3_L126=        _write_private(self.snapshot,b)
FILE_3_L127=        self.inner=large.ReadOnlyLarge(str(RCLONE),self.snapshot,e,bind,self.guard,self.work,self.deadline,self.logical_id)
FILE_3_L128=        return self.inner
FILE_3_L129=    def list_generations(self,*a,**k):return self._ensure().list_generations(*a,**k)
FILE_3_L130=    def get(self,*a,**k):return self._ensure().get(*a,**k)
FILE_3_L131=    def read_stream(self,*a,**k):return self._ensure().read_stream(*a,**k)
FILE_3_L132=    def close(self):
FILE_3_L135=
FILE_3_L136=def selftest():
FILE_3_L137=    if _sha(PLAN,1024*1024)!=PLAN_SHA:return False
FILE_3_L138=    for p,h in ((RCLONE,RCLONE_SHA),(VZDUMP,VZDUMP_SHA),(ZSTD,ZSTD_SHA)):
FILE_3_L139=        if _sha(p)!=h:return False
FILE_3_L140=    return True
FILE_3_L141=
FILE_3_L142=def run_target(target,state_writer=None):
FILE_3_L143=    if not isinstance(target,dict) or target.get('logical_id')!=CT_ID or target.get('vmid')!=112:return (_ for _ in ()).throw(RuntimeError('CT112_DESCRIPTOR'))
FILE_3_L144=    if _sha(PLAN,1024*1024)!=PLAN_SHA:raise RuntimeError('PLAN_REFERENCE_IDENTITY')
FILE_3_L145=    tools={'vzdump':_tool(VZDUMP,VZDUMP_SHA),'zstd':_tool(ZSTD,ZSTD_SHA)};_tool(RCLONE,RCLONE_SHA)
FILE_3_L146=    pvesh_sha=_sha(PVESH);now=int(time.time());current=_fresh_plan(now);job=_select_live_ct112(current,now)
FILE_3_L147=    expected=job['config_sha256'];mapping=_canonical_host_mapping()
FILE_3_L148=    def producer_guard():
FILE_3_L153=        pve282.live_gate(fresh,str(PVESH),pvesh_sha,expected)
FILE_3_L154=    producer_guard()
FILE_3_L155=    cfg,entries,binding=_private_config()
FILE_3_L156=    generation='V2-'+time.strftime('%Y%m%dT%H%M%SZ',time.gmtime())+'-'+secrets.token_hex(6)
FILE_3_L157=    work=STAGING/('backup-v2-'+generation);work.mkdir(mode=0o700,parents=False,exist_ok=False)
FILE_3_L158=    deadline=time.monotonic()+21600
FILE_3_L159=    def cloud_guard():
FILE_3_L160=        _,e,b=_private_config()
FILE_3_L161=        if e!=entries or b!=binding:raise RuntimeError('RCLONE_SEMANTIC_DRIFT')
FILE_3_L162=    writer=large.CloudLarge(str(RCLONE),RCLONE_CFG,entries,binding,cloud_guard,work/'upload',deadline)
FILE_3_L163=    reader=LazyReader(work/'restore',entries,binding,cloud_guard,deadline,CT_ID)
FILE_3_L164=    def produce(j,w):return pve282.produce(j,w,tools,producer_guard,mapping=mapping,expected_config=expected,seconds=14400,emit=lambda k,v:None)
FILE_3_L165=    def compression(path):
FILE_3_L166=        p=subprocess.run([str(ZSTD),'--test','--quiet','--',str(path)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL,timeout=3600,check=False,env=ENV)
FILE_3_L167=        return p.returncode==0
FILE_3_L168=    try:
FILE_3_L169=        r=guest266.run_flow(job,work,entries,writer,reader,produce,producer_guard,cloud_guard,compression,generation,lambda k,v:None)
FILE_3_L170=        reps=r.get('replicas')
FILE_3_L171=        if not isinstance(reps,list) or len(reps)!=2 or len({x.get('account_id') for x in reps})!=2:raise RuntimeError('REPLICA_PHYSICAL_INDEPENDENCE')
FILE_3_L172=        if r.get('archive_cloud_restore_verified') is not True or r.get('local_payload_files_remaining')!=0:raise RuntimeError('CT112_RESTORE_CONTRACT')
FILE_3_L173=        out={**r,'status':'OK','cloud_only_independent_restore_verified':True,'local_payload_files_remaining':0}
FILE_3_L174=        reader.close();shutil.rmtree(work)
FILE_3_L175=        if work.exists():raise RuntimeError('CT112_WORKSPACE_CLEANUP')
FILE_3_L176=        if state_writer is not None:
FILE_3_L177=            state_writer(CT_ID,'SUCCESS',generation=r['generation'],payload_sha256=r['payload_sha256'],manifest_sha256=r['manifest_sha256'],replicas=r['replicas'],green_verified=True)
FILE_3_L178=        return out
FILE_3_L179=    except BaseException:
FILE_3_L180=        try:reader.close()
FILE_3_L181=        except BaseException:pass
FILE_3_L182=        raise
FILE_4_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py
FILE_4_BYTES=59719
FILE_4_SHA256=b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7
FILE_4_CONTEXT_LINE_COUNT=180
FILE_4_L1=#!/usr/bin/python3
FILE_4_L2=import ast, base64, datetime as dt, hashlib, io, json, os, pathlib, random, re, select, shlex, shutil, stat, subprocess, sys, tarfile, tempfile, time
FILE_4_L3=
FILE_4_L4=PART_SIZE=536870912
FILE_4_L5=RESERVE_BYTES=536870912
FILE_4_L6=STATE_ROOT=pathlib.Path('/var/lib/homelab-backup-v2')
FILE_4_L7=CONFIG_ROOT=pathlib.Path('/etc/homelab-backup-v2')
FILE_4_L8=TARGETS_PATH=CONFIG_ROOT/'targets.json'
FILE_4_L9=WORK_ROOT=pathlib.Path('/mnt/staging/homelab-backup-v2')
FILE_4_L10=ENGINE_PATH=pathlib.Path('/usr/local/sbin/homelab-backup-v2')
FILE_4_L11=RCLONE=shutil.which('rclone') or '/usr/bin/rclone'
FILE_4_L12=SSH=shutil.which('ssh') or '/usr/bin/ssh'
FILE_4_L13=SCP=shutil.which('scp') or '/usr/bin/scp'
FILE_4_L14=SSH_KEYSCAN=shutil.which('ssh-keyscan') or '/usr/bin/ssh-keyscan'
FILE_4_L30=P282_SHA='73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012'
FILE_4_L31=P265=pathlib.Path('/opt/homelab-backup-v2/releases/pve-producer-265r1/pve265.py')
FILE_4_L32=P265_SHA='cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be'
FILE_4_L33=RESULT_CLASSES=('SUCCESS','DEFER','PARTIAL_VALID','FAIL')
FILE_4_L34=HISTORICAL_RELEASE_GRAPH=[
FILE_4_L35= (pathlib.Path('/opt/homelab-backup-v2/releases/core-260r1/v2core.py'),'e285bf9a5678d07dcbb90261f9f93e7826ff524e04cfec780bf5a3c4b0dc29f2'),
FILE_4_L36= (pathlib.Path('/opt/homelab-backup-v2/releases/transport-261r1/transport261.py'),'b9b92f957bf441cb5d1702f4881897328e6c0338f8c3f6d41d27d9a349b37688'),
FILE_4_L51= pathlib.Path('/opt/homelab-backup-v2/releases/large-cloud-264r1'),
FILE_4_L52= pathlib.Path('/opt/homelab-backup-v2/releases/stream-263r1'),
FILE_4_L53= pathlib.Path('/opt/homelab-backup-v2/releases/transport-261r1'),
FILE_4_L54= pathlib.Path('/opt/homelab-backup-v2/releases/restore-262r1'),
FILE_4_L55= pathlib.Path('/opt/homelab-backup-v2/releases/core-260r1'),
FILE_4_L56= pathlib.Path('/opt/homelab-backup-v2/releases/vm-backup-283r1'),
FILE_4_L57=]
FILE_4_L58=_HISTORICAL_HELPER = r'''import importlib,importlib.util,json,pathlib,sys
FILE_4_L59=mode=sys.argv[1]
FILE_4_L60=if mode=='import_all':
FILE_4_L61= out={}
FILE_4_L74='''
FILE_4_L75=os.umask(0o077)
FILE_4_L76=
FILE_4_L77=REMOTES=[
FILE_4_L78= ('pve01-mail-01-crypt','pve01-mail-01'),('pve01-mail-02-crypt','pve01-mail-02'),('pve01-mail-03-crypt','pve01-mail-03'),('pve01-mail-04-crypt','pve01-mail-04'),('pve01-mail-05-crypt','pve01-mail-05'),
FILE_4_L79= ('pve02-mail-01-crypt','pve02-mail-01'),('pve02-mail-02-crypt','pve02-mail-02'),('pve02-mail-03-crypt','pve02-mail-03'),('pve02-mail-04-crypt','pve02-mail-04'),
FILE_4_L80= ('pve03-mail-01-crypt','pve03-mail-01'),('pve03-mail-02-crypt','pve03-mail-02'),('pve03-mail-03-crypt','pve03-mail-03'),('pve03-mail-04-crypt','pve03-mail-04')]
FILE_4_L81=
FILE_4_L82=class BackupError(RuntimeError):
FILE_4_L83=    def __init__(self, code, detail=''):
FILE_4_L102=            if not b: break
FILE_4_L103=            h.update(b); n+=len(b)
FILE_4_L104=            if remain is not None: remain-=len(b)
FILE_4_L105=    if length is not None and n!=length: raise BackupError('LOCAL_PART_SHORT_READ')
FILE_4_L106=    return h.hexdigest()
FILE_4_L107=
FILE_4_L108=def part_plan(n):
FILE_4_L109=    if not isinstance(n,int) or n<=0: raise BackupError('PAYLOAD_SIZE_INVALID')
FILE_4_L110=    out=[]; off=0; idx=1
FILE_4_L111=    while off<n:
FILE_4_L112=        size=min(PART_SIZE,n-off)
FILE_4_L113=        out.append({'name':f'part-{idx:06d}','offset':off,'bytes':size})
FILE_4_L114=        off+=size; idx+=1
FILE_4_L115=    return out
FILE_4_L116=
FILE_4_L117=def select_replicas(rows,payload_bytes,reserve_bytes=RESERVE_BYTES):
FILE_4_L118=    eligible=[]
FILE_4_L119=    for r in rows:
FILE_4_L120=        if not isinstance(r.get('free'),int): continue
FILE_4_L121=        if r['free'] < payload_bytes + reserve_bytes: continue
FILE_4_L122=        eligible.append(dict(r))
FILE_4_L123=    eligible.sort(key=lambda r:(-r['free'],r['physical'],r['crypt']))
FILE_4_L124=    out=[]; phys=set()
FILE_4_L125=    for r in eligible:
FILE_4_L126=        if r['physical'] in phys: continue
FILE_4_L127=        out.append(r); phys.add(r['physical'])
FILE_4_L128=        if len(out)==2: break
FILE_4_L129=    if len(out)!=2: raise BackupError('ALLOCATOR_TWO_DISTINCT_ACCOUNTS_UNAVAILABLE')
FILE_4_L130=    return out
FILE_4_L131=
FILE_4_L132=def remote_generation_path(scope,logical_id,generation):
FILE_4_L133=    safe=re.compile(r'^[A-Za-z0-9._-]+$')
FILE_4_L134=    for x in (scope,logical_id,generation):
FILE_4_L135=        if not safe.fullmatch(x): raise BackupError('UNSAFE_CLOUD_COMPONENT')
FILE_4_L136=    return f'homelab-backups/v2/{scope}/{logical_id}/generations/{generation}'
FILE_4_L137=
FILE_4_L138=def make_manifest(scope,logical_id,generation,payload_bytes,payload_sha256,parts,replicas,source_meta):
FILE_4_L139=    if len(replicas)!=2 or len({r['physical'] for r in replicas})!=2: raise BackupError('MANIFEST_REPLICA_PHYSICAL_DUPLICATE')
FILE_4_L140=    if not re.fullmatch(r'[0-9a-f]{64}',payload_sha256): raise BackupError('MANIFEST_PAYLOAD_SHA_INVALID')
FILE_4_L141=    if sum(int(p['bytes']) for p in parts)!=payload_bytes: raise BackupError('MANIFEST_PART_TOTAL_MISMATCH')
FILE_4_L142=    return {'schema':2,'scope':scope,'logical_id':logical_id,'generation':generation,'created_at_utc':utcnow(),
FILE_4_L143=            'payload_bytes':payload_bytes,'payload_sha256':payload_sha256,'part_size':PART_SIZE,'parts':parts,
FILE_4_L144=            'replicas':[{'crypt':r['crypt'],'physical':r['physical']} for r in replicas],'source_meta':source_meta}
FILE_4_L145=
FILE_4_L146=def utcnow(): return dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace('+00:00','Z')
FILE_4_L147=def epoch(): return int(time.time())
FILE_4_L225=
FILE_4_L226=def atomic_write(path,data,mode=0o600):
FILE_4_L227=    path=pathlib.Path(path); ensure_dir(path.parent,0o700)
FILE_4_L228=    fd,tmp=tempfile.mkstemp(prefix='.'+path.name+'.',dir=str(path.parent))
FILE_4_L229=    try:
FILE_4_L230=        with os.fdopen(fd,'wb') as f: f.write(data); f.flush(); os.fsync(f.fileno())
FILE_4_L231=        os.chmod(tmp,mode); os.replace(tmp,path)
FILE_4_L235=
FILE_4_L236=def load_targets():
FILE_4_L237=    j=json.loads(TARGETS_PATH.read_text())
FILE_4_L238=    if j.get('schema')!=1 or not isinstance(j.get('targets'),list): raise BackupError('TARGET_MANIFEST_SCHEMA')
FILE_4_L239=    ids=[x.get('logical_id') for x in j['targets']]
FILE_4_L240=    if len(ids)!=len(set(ids)): raise BackupError('TARGET_MANIFEST_DUPLICATE')
FILE_4_L241=    return j['targets']
FILE_4_L242=
FILE_4_L243=def load_state_all():
FILE_4_L257=    atomic_write(STATE_ROOT/'state'/(logical_id+'.json'),canonical_json(j)+b'\n',0o600)
FILE_4_L258=    return j
FILE_4_L259=
FILE_4_L260=def rclone_base_args():
FILE_4_L261=    return [RCLONE]
FILE_4_L262=
FILE_4_L263=def rclone_about(remote):
FILE_4_L264=    p=run(rclone_base_args()+['about',remote+':','--json','--contimeout','15s','--timeout','45s'],timeout=60)
FILE_4_L265=    try:j=json.loads(p.stdout)
FILE_4_L266=    except Exception: raise BackupError('RCLONE_ABOUT_JSON')
FILE_4_L267=    free=j.get('free')
FILE_4_L268=    if not isinstance(free,int): raise BackupError('RCLONE_FREE_UNKNOWN')
FILE_4_L269=    return free
FILE_4_L270=
FILE_4_L271=def allocator(payload_bytes):
FILE_4_L272=    rows=[]; bad=0
FILE_4_L273=    for crypt,physical in REMOTES:
FILE_4_L274=        try: free=rclone_about(crypt)
FILE_4_L275=        except BackupError: bad+=1; continue
FILE_4_L276=        rows.append({'crypt':crypt,'physical':physical,'free':free})
FILE_4_L277=    reps=select_replicas(rows,payload_bytes,RESERVE_BYTES)
FILE_4_L278=    return reps,bad,len(rows)
FILE_4_L279=
FILE_4_L280=def remote_exists_any(scope,logical_id,generation):
FILE_4_L281=    rel=remote_generation_path(scope,logical_id,generation)
FILE_4_L282=    for crypt,_physical in REMOTES:
FILE_4_L283=        p=run(rclone_base_args()+['lsf',crypt+':'+rel,'--max-depth','1'],timeout=45,check=False)
FILE_4_L284=        if p.returncode==0 and p.stdout.strip(): return True
FILE_4_L285=    return False
FILE_4_L286=
FILE_4_L287=def rclone_rcat(remote_path, source_path=None, offset=0, length=None, data=None, timeout=3600):
FILE_4_L288=    argv=rclone_base_args()+['rcat',remote_path,'--retries','3','--low-level-retries','5','--contimeout','20s','--timeout','5m']
FILE_4_L289=    p=subprocess.Popen(argv,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
FILE_4_L290=    try:
FILE_4_L291=        if data is not None:
FILE_4_L304=        try:p.kill()
FILE_4_L305=        except Exception:pass
FILE_4_L306=        raise
FILE_4_L307=    if p.returncode!=0: raise BackupError('RCLONE_RCAT_FAILED',str(p.returncode))
FILE_4_L308=
FILE_4_L309=def rclone_cat_hash(remote_path, expected_bytes=None, timeout=3600):
FILE_4_L310=    h=hashlib.sha256(); n=0; start=time.time()
FILE_4_L311=    with subprocess.Popen(rclone_base_args()+['cat',remote_path,'--contimeout','20s','--timeout','5m'],stdout=subprocess.PIPE,stderr=subprocess.PIPE) as p:
FILE_4_L312=        while True:
FILE_4_L313=            if time.time()-start>timeout:
FILE_4_L314=                p.kill(); p.wait(); raise BackupError('RCLONE_CAT_TIMEOUT')
FILE_4_L315=            b=p.stdout.read(1024*1024)
FILE_4_L316=            if not b: break
FILE_4_L317=            h.update(b); n+=len(b)
FILE_4_L318=        p.stderr.read(); rc=p.wait()
FILE_4_L319=    if rc!=0: raise BackupError('RCLONE_CAT_FAILED',str(rc))
FILE_4_L320=    if expected_bytes is not None and n!=expected_bytes: raise BackupError('RCLONE_CAT_SIZE_MISMATCH')
FILE_4_L321=    return h.hexdigest(),n
FILE_4_L322=
FILE_4_L323=def rclone_cat_bytes(remote_path,max_bytes=4*1024*1024):
FILE_4_L324=    p=run(rclone_base_args()+['cat',remote_path,'--contimeout','20s','--timeout','60s'],timeout=90)
FILE_4_L325=    if len(p.stdout)>max_bytes: raise BackupError('RCLONE_SMALL_OBJECT_TOO_LARGE')
FILE_4_L326=    return p.stdout
FILE_4_L327=
FILE_4_L328=def generation_id(logical_id):
FILE_4_L329=    ts=dt.datetime.now(dt.timezone.utc).strftime('%Y%m%dT%H%M%SZ')
FILE_4_L330=    return f'v2-{logical_id}-{ts}-{os.urandom(6).hex()}'
FILE_4_L331=
FILE_4_L332=def upload_and_seal(t,payload_path,source_meta):
FILE_4_L333=    payload_path=pathlib.Path(payload_path); n=payload_path.stat().st_size
FILE_4_L334=    psha=sha256_file(payload_path); reps,bad,healthy=allocator(n)
FILE_4_L335=    gen=source_meta['generation']; rel=remote_generation_path(t['scope'],t['logical_id'],gen)
FILE_4_L336=    if remote_exists_any(t['scope'],t['logical_id'],gen): raise BackupError('GENERATION_COLLISION')
FILE_4_L337=    parts=part_plan(n)
FILE_4_L338=    for p in parts: p['sha256']=sha256_file(payload_path,p['offset'],p['bytes'])
FILE_4_L339=    manifest=make_manifest(t['scope'],t['logical_id'],gen,n,psha,parts,reps,source_meta)
FILE_4_L340=    mb=canonical_json(manifest)+b'\n'; msha=sha256_bytes(mb)
FILE_4_L341=    for rep in reps:
FILE_4_L342=        base=rep['crypt']+':'+rel
FILE_4_L343=        for part in parts:
FILE_4_L344=            rp=base+'/parts/'+part['name']
FILE_5_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/representative_driver.py
FILE_5_BYTES=4214
FILE_5_SHA256=b3050a8f95e6d9826a4f0786cd3ca32012b6ab10486d10e4981b50b8a0affff2
FILE_5_CONTEXT_LINE_COUNT=60
FILE_5_L3=
FILE_5_L4=This module does not discover credentials, modify scheduler state, or implement the
FILE_5_L5=CT112 producer/cloud path. It routes CT112 to an explicitly supplied callback and
FILE_5_L6=isolates legacy engine state writes into a candidate-owned state directory.
FILE_5_L7="""
FILE_5_L8=from __future__ import annotations
FILE_5_L9=
FILE_5_L10=import json
FILE_5_L11=import os
FILE_5_L12=from pathlib import Path
FILE_5_L13=from typing import Callable, Iterable, Mapping, Any
FILE_5_L14=
FILE_5_L15=LEGACY_IDS=(
FILE_5_L16=    'node-pve01',
FILE_5_L24=)
FILE_5_L25=CT112_ID='guest-pve01-lxc-112'
FILE_5_L26=REPRESENTATIVE_IDS=(CT112_ID,)+LEGACY_IDS
FILE_5_L27=CANDIDATE_ROOT=Path(__file__).resolve().parent
FILE_5_L28=STATE_ROOT=CANDIDATE_ROOT/'state'
FILE_5_L29=
FILE_5_L30=class ContractError(RuntimeError):
FILE_5_L31=    pass
FILE_5_L36=        raise ContractError('TARGET_LOGICAL_ID')
FILE_5_L37=    return value
FILE_5_L38=
FILE_5_L39=def partition_targets(targets: Iterable[Mapping[str, Any]]):
FILE_5_L40=    selected={}
FILE_5_L41=    wanted=set(REPRESENTATIVE_IDS)
FILE_5_L42=    for target in targets:
FILE_5_L62=        with os.fdopen(fd,'wb',closefd=True) as f:
FILE_5_L63=            f.write(data);f.flush();os.fsync(f.fileno())
FILE_5_L64=        os.replace(tmp,path)
FILE_5_L65=    except BaseException:
FILE_5_L66=        try: os.unlink(tmp)
FILE_5_L67=        except FileNotFoundError: pass
FILE_5_L68=        raise
FILE_5_L72=    def write_state(logical_id,result,**kw):
FILE_5_L73=        if logical_id not in LEGACY_IDS:
FILE_5_L74=            raise ContractError('STATE_TARGET_FORBIDDEN')
FILE_5_L75=        payload={'logical_id':logical_id,'result':result,'meta':kw,'schema_version':1}
FILE_5_L76=        _atomic_json(root/(logical_id+'.json'),payload)
FILE_5_L77=    return write_state
FILE_5_L78=
FILE_5_L79=def run_legacy_lane(engine, target: Mapping[str, Any]):
FILE_5_L97=        raise ContractError('CT112_RESULT_SCHEMA')
FILE_5_L98=    if result.get('logical_id')!=CT112_ID or result.get('status')!='OK':
FILE_5_L99=        raise ContractError('CT112_RESULT_STATUS')
FILE_5_L100=    if result.get('cloud_only_independent_restore_verified') is not True:
FILE_5_L101=        raise ContractError('CT112_RESTORE_NOT_VERIFIED')
FILE_5_L102=    if result.get('local_payload_files_remaining')!=0:
FILE_5_L103=        raise ContractError('CT112_LOCAL_PAYLOAD_REMAINS')
FILE_5_L104=    return result
FILE_5_L105=
FILE_5_L106=def run_representative(engine, targets, ct112_callback: Callable[[Mapping[str, Any]], Any]):
FILE_5_L107=    if not callable(ct112_callback):
FILE_5_L108=        raise ContractError('CT112_CALLBACK_REQUIRED')
FILE_5_L109=    legacy,ct112=partition_targets(targets)
FILE_5_L110=    results=[_validate_ct112_result(ct112_callback(ct112))]
FILE_5_L111=    for target in legacy:
FILE_5_L112=        results.append(run_legacy_lane(engine,target))
FILE_6_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py
FILE_6_BYTES=5055
FILE_6_SHA256=2b5eb4fc0f6f466a0d3e5a007af987092b6c17baa3ff9241a6afc2c2e97df1d5
FILE_6_CONTEXT_LINE_COUNT=43
FILE_6_L1=#!/usr/bin/env python3
FILE_6_L2=from __future__ import annotations
FILE_6_L3=import errno,fcntl,importlib.util,os,sys
FILE_6_L4=from pathlib import Path
FILE_6_L5=ROOT=Path(__file__).resolve().parent
FILE_6_L6=CT_ID='guest-pve01-lxc-112'
FILE_6_L7=LEGACY_IDS=('node-pve01','md-relay','spb-ingress','us-netbird','router-netcraze','xf-codevipe','xf-zakrutim','control-bootstrap-v2')
FILE_6_L35=            'guest_type':'lxc','due_seconds':due,'enabled':True,'green1':True}
FILE_6_L36=
FILE_6_L37=def load_targets():
FILE_6_L38=    base=canonical_targets();return base+[_ct_descriptor(base)]
FILE_6_L39=
FILE_6_L40=def backup_target(t,green_verify=False):
FILE_6_L41=    if not isinstance(t,dict) or t.get('logical_id')!=CT_ID:
FILE_6_L42=        return _legacy_backup_target(t,green_verify)
FILE_6_L43=    try:
FILE_6_L44=        r=ct112.run_target(t,state_writer=legacy.write_state)
FILE_6_L45=        return {'logical_id':CT_ID,'generation':r['generation'],'result':'SUCCESS','payload_bytes':r['payload_bytes'],
FILE_6_L46=                'replicas':2,'manifest_sha256':r['manifest_sha256'],'payload_sha256':r['payload_sha256']}
FILE_6_L47=    except BaseException:
FILE_6_L48=        try: legacy.write_state(CT_ID,'FAIL',reason='CT112_PIPELINE_FAILED')
FILE_6_L49=        except BaseException: pass
FILE_6_L50=        raise legacy.BackupError('CT112_PIPELINE_FAILED') from None
FILE_6_L51=
FILE_6_L52=legacy.load_targets=load_targets
FILE_6_L53=legacy.backup_target=backup_target
FILE_6_L54=
FILE_6_L55=def _legacy_reused_boundary_selftest():
FILE_6_L56=    if legacy.PART_SIZE!=536870912: raise RuntimeError('LEGACY_PART_SIZE')
FILE_6_L57=    if len(legacy.REMOTES)!=13 or len({p for _,p in legacy.REMOTES})!=13: raise RuntimeError('LEGACY_REMOTES')
FILE_6_L58=    d=legacy.default_targets()
FILE_6_L59=    if not isinstance(d,list) or len(d)<28: raise RuntimeError('LEGACY_DEFAULT_TARGET_COUNT')
FILE_6_L60=    want={'ct112',*LEGACY_IDS}
FILE_6_L67=
FILE_6_L68=def selftest():
FILE_6_L69=    _legacy_reused_boundary_selftest()
FILE_6_L70=    base=canonical_targets(); eff=load_targets()
FILE_6_L71=    if len(eff)!=29 or sum(1 for x in eff if x.get('logical_id')==CT_ID)!=1: raise RuntimeError('EFFECTIVE_TARGETS')
FILE_6_L72=    legacy_rows,ct=driver.partition_targets(eff)
FILE_6_L73=    if [x['logical_id'] for x in legacy_rows]!=list(LEGACY_IDS) or ct.get('vmid')!=112: raise RuntimeError('REPRESENTATIVE_PARTITION')
FILE_6_L74=    if ct112.selftest() is not True: raise RuntimeError('CT112_HANDLER_SELFTEST')
FILE_6_L75=    print('SELFTEST_REPLACEMENT486=PASS',flush=True);return 0
FILE_6_L76=
FILE_7_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/CONTRACT.json
FILE_7_BYTES=2077
FILE_7_SHA256=a414715f1b91b3701c52073709a80c38218f76e3961618e8af61489211e50c01
FILE_7_CONTEXT_LINE_COUNT=1
FILE_7_L1={"candidate":"pve-lxc-adapter-411r1","next_gate":"PVE_LXC_REAL_ENVIRONMENT_DRY_RUN","owner":{"MappedScratch":"pve270","capture_archive":"pve270","dump_argv":"pve265","pve282.old":"pve265","pve282.proven":"pve270","validate_mapping":"pve270"},"schema":1,"signatures":{"pve265":{"dump_argv":{"args":["job","executable","tmpdir","now"],"defaults":0,"kw_defaults":[],"kwarg":null,"kwonly":[],"posonly":[],"vararg":null},"make_plan":{"args":["rows","configs","storage_rows","defaults","staging_free","now","node"],"defaults":1,"kw_defaults":[],"kwarg":null,"kwonly":[],"posonly":[],"vararg":null},"produce":{"args":["job","work","tools","guard","seconds"],"defaults":1,"kw_defaults":[],"kwarg":null,"kwonly":[],"posonly":[],"vararg":null},"validate_job":{"args":["job","now"],"defaults":0,"kw_defaults":[],"kwarg":null,"kwonly":[],"posonly":[],"vararg":null}},"pve270":{"capture_archive":{"args":["argv","destination","cap","seconds","check"],"defaults":0,"kw_defaults":[],"kwarg":null,"kwonly":[],"posonl
FILE_8_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/PLAN265_REFERENCE.json
FILE_8_BYTES=7210
FILE_8_SHA256=8d36e82080be93a8c929a9211191fa868166b9e7b6152c4c7689fa52b6720757
FILE_8_CONTEXT_LINE_COUNT=1
FILE_8_L1={"all_guest_coverage_eligible":true,"backup_executed":false,"capacity_policy":"four archive copies plus 4GiB; capped producer; actual compressed size still unknown","collected_at_utc":"2026-09-12T06:57:40.611329+00:00","full_host_coverage":false,"global_blockers":[],"global_defaults":{"blockers":[],"keys":[],"present":true,"sha256":"cf34c8e3812547954bb1d08b50212b6e148ee9cf2b629e895a843ed49d623b38"},"guest_membership_and_configs_stable":true,"jobs":[{"application_consistency_verified":false,"archive_cap_bytes":9516036916,"blockers":[],"cdrom_count":0,"cdrom_media_included":false,"compression_dependent":false,"config_sha256":"09957aacd41ba9eeaf5fd4eda13936d580c9082a46895433379aa9dd0bad5969","configured_archive_bound_bytes":9516036916,"configured_disk_bytes":8589934592,"configured_full_cycle_fits":true,"coverage_eligible":true,"disks":[{"backup_setting":"included_default_rootfs","class":"managed-volume","configured_size_bytes":8589934592,"slot":"rootfs","storage":"local-lvm"}],"global_def
FILE_9_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/PROVENANCE.json
FILE_9_BYTES=4310
FILE_9_SHA256=303f44dc8e91c8e6a675f9ea406ce4b7532ed98440a9b6807fa593ede9d33254
FILE_9_CONTEXT_LINE_COUNT=1
FILE_9_L1={"anchors":{"SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-EXACT-CALL-GRAPH-PROOF-401R1":"840b3f1e8b023899c0554305a97af2d55dc71cf9","SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-IMMUTABLE-ADAPTER-CANDIDATE-STAGE-FIXTURE-RCA-FIX-407R1":"0261475cdd35d3b762de0a29e46f3acd0b9af229","SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-IMMUTABLE-ADAPTER-CANDIDATE-STAGE-RCA-FIX-403R1":"e3f753ce9cf95e21750e9ad7f9574cafc199b3ce","SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-PERL270-HISTORICAL-TEST-RCA-404R1":"58f61ce62c3b6a57d8c5fc2465d2537d6728f9d5","SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-PERLPIN-EXEC-FS-RCA-409R1":"0db666a5a1f4796b567663adfc5568817e87efa5","SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-PERLPIN-NEED-TRACE-RCA-408R1":"44cdff7dab9e60aff1d69c12d2c32a4b26d04de8","SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-PERLPIN-PRODUCTION-VS-FIXTURE-RCA-406R1":"4c5836ff0ef73cb2ef306857be713383ba5e85f4","SUPPORT-260915-INFRA-DR-BACKUPV2-PVE-LXC-PERLPIN-ROOT-SUITE-STRUCTURED-RCA-410R1":"4673bfaf04877370bc4ac02fef37885eb82cb1eb
FILE_10_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/adapter.py
FILE_10_BYTES=2989
FILE_10_SHA256=18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3
FILE_10_CONTEXT_LINE_COUNT=30
FILE_10_L1=#!/usr/bin/python3
FILE_10_L2=import hashlib,inspect,json,pathlib,sys
FILE_10_L3=BASE=pathlib.Path(__file__).resolve().parent
FILE_10_L4=EXPECTED={
FILE_10_L5='v2core.py':'e285bf9a5678d07dcbb90261f9f93e7826ff524e04cfec780bf5a3c4b0dc29f2',
FILE_10_L6='transport261.py':'b9b92f957bf441cb5d1702f4881897328e6c0338f8c3f6d41d27d9a349b37688',
FILE_10_L7='restore262.py':'56d1b961c8d5654d5e2ee2755268db46bd2202bca11e69788febf991cfaa79f1',
FILE_10_L8='stream263.py':'a83d03a86b93a855716658652dd073fcb281cd387fc6200fe4bc2a922f39ea16',
FILE_10_L9='nodeplan263.py':'db5c16ee24d25aa1694530332d3190ab7cc5d4f8eb69067d025e27ad5c995060',
FILE_10_L10='large264.py':'5cc4641fc35e4dd554495a36146da7dbbb7f142d1450e04cc5d3c89678b8497a',
FILE_10_L19= return h.hexdigest()
FILE_10_L20=def verify_sources():
FILE_10_L21= for name,want in EXPECTED.items():
FILE_10_L22=  p=BASE/name
FILE_10_L23=  if not p.is_file() or p.is_symlink() or sha(p)!=want:raise RuntimeError('SOURCE_IDENTITY_'+name)
FILE_10_L24=def load_graph():
FILE_10_L25= import guest266,pve265,pve270,pve282
FILE_10_L26= if hasattr(guest266,'dump_argv'):raise RuntimeError('GUEST266_UNEXPECTED_DUMP_ARGV')
FILE_10_L27= if not hasattr(pve265,'dump_argv'):raise RuntimeError('PVE265_DUMP_ARGV_MISSING')
FILE_10_L28= if getattr(pve270,'old',None) is not pve265:raise RuntimeError('PVE270_OLD_NOT_PVE265')
FILE_10_L35=def describe():
FILE_10_L36= _,p265,p270,p282=load_graph()
FILE_10_L37= funcs={'pve265.dump_argv':p265.dump_argv,'pve265.validate_job':p265.validate_job,'pve265.make_plan':p265.make_plan,'pve270.validate_mapping':p270.validate_mapping,'pve270.capture_archive':p270.capture_archive,'pve270.produce':p270.produce,'pve282.select112':p282.select112,'pve282.produce':p282.produce}
FILE_10_L38= return {'schema':1,'bundle':'pve-lxc-adapter-411r1','source_sha256':EXPECTED,'signatures':{k:str(inspect.signature(v)) for k,v in funcs.items()},'owner':{'dump_argv':'pve265','MappedScratch':'pve270','capture_archive':'pve270','validate_mapping':'pve270','pve282.old':'pve265','pve282.proven':'pve270'}}
FILE_10_L39=def main():
FILE_10_L40= verify_sources(); mode=sys.argv[1] if len(sys.argv)>1 else 'selftest'; d=describe()
FILE_10_L41= if mode not in ('selftest','describe'):raise SystemExit(2)
FILE_10_L42= print(json.dumps(d,sort_keys=True,separators=(',',':')))
FILE_10_L43= if mode=='selftest':print('ADAPTER_SELFTEST=PASS')
FILE_10_L44=if __name__=='__main__':main()
FILE_11_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/guest266.py
FILE_11_BYTES=7385
FILE_11_SHA256=86433bc424d5fa5017c20f7a237c82874b02357a3283660d8a6b0039ef2bc868
FILE_11_CONTEXT_LINE_COUNT=75
FILE_11_L1="""266R1 bounded real-guest orchestration. Import has no side effects.
FILE_11_L2=
FILE_11_L3=One small LXC rootfs, no compression-dependent admission. No node-wide approval,
FILE_11_L4=no guest restore/start/delete, no cloud deletion. Archive CRC/SHA is not boot proof.
FILE_11_L5="""
FILE_11_L6=import copy,os,time
FILE_11_L7=from pathlib import Path
FILE_11_L8=import v2core as core
FILE_11_L9=import transport261 as t
FILE_11_L10=import stream263 as stream
FILE_11_L11=import large264 as large
FILE_11_L12=import pve265 as producer
FILE_11_L13=
FILE_11_L14=MAX_CONFIGURED_BYTES=8*1024**3
FILE_11_L15=RESERVE_BYTES=536870912
FILE_11_L25=
FILE_11_L26=def choose(plan,now):
FILE_11_L27=    rows=plan_rows(plan);t.need(plan.get('global_blockers')==[],'GLOBAL_DEFAULT_BLOCK')
FILE_11_L28=    candidates=[]
FILE_11_L29=    for job in rows:
FILE_11_L30=        if not (job.get('type')=='lxc' and job.get('coverage_eligible') is True and
FILE_11_L31=                job.get('blockers')==[] and job.get('compression_dependent') is False and
FILE_11_L35=                disks[0].get('class')=='managed-volume' and disks[0].get('backup_setting') in ('included','included_default_rootfs')):continue
FILE_11_L36=        n=job.get('configured_disk_bytes')
FILE_11_L37=        if type(n) is not int or not 0<n<=MAX_CONFIGURED_BYTES:continue
FILE_11_L38=        producer.validate_job(job,now);candidates.append(job)
FILE_11_L39=    t.need(bool(candidates),'NO_SMALL_NONCOMPRESSED_DEPENDENT_LXC')
FILE_11_L40=    chosen=min(candidates,key=lambda j:(j['configured_disk_bytes'],j['vmid']))
FILE_11_L41=    stores={s['storage']:s for s in plan.get('storages',[])}
FILE_11_L42=    disk=chosen['disks'][0];st=stores.get(disk['storage'],{})
FILE_11_L43=    t.need(st.get('active') is True and st.get('enabled') is True and st.get('type') in ('lvmthin','zfspool'),'SNAPSHOT_STORAGE_UNAVAILABLE')
FILE_11_L44=    t.need(type(st.get('free_bytes')) is int and st['free_bytes']>=max(1024**3,chosen['configured_disk_bytes']),'SNAPSHOT_HEADROOM_UNPROVEN')
FILE_11_L45=    return copy.deepcopy(chosen)
FILE_11_L46=
FILE_11_L47=def same_state(before,after,vmid):
FILE_11_L48=    old=plan_rows(before);new=plan_rows(after)
FILE_11_L64=        if type(task.get('endtime')) is int and task.get('status') not in (None,'RUNNING'):continue
FILE_11_L65=        kind=task['type'];target=str(task.get('id',''))
FILE_11_L66=        if kind in ('vncshell','vncterm','vncproxy','spiceproxy'):continue
FILE_11_L67=        t.need(target!=str(vmid) and not any(x in kind.lower() for x in ('dump','restore','migrat','snapshot','clone','move_disk','resize')),'COMPETING_PVE_TASK')
FILE_11_L68=
FILE_11_L69=def check_result(result,job,work):
FILE_11_L70=    t.need(type(result) is dict,'PRODUCER_RESULT_SCHEMA')
FILE_11_L80=    finally:os.close(fd)
FILE_11_L81=    return expected
FILE_11_L82=
FILE_11_L83=def run_flow(job,work,entries,cloud,reader,produce,state_guard,guard,compression_check,generation,say,clock=lambda:int(time.time())):
FILE_11_L84=    """Caller provides real fresh PVE guards; simulation callbacks live in tests only."""
FILE_11_L85=    producer.validate_job(job,clock());core.validate_inventory(entries)
FILE_11_L86=    t.need(job['type']=='lxc' and job.get('compression_dependent') is False,'FIRST_GUEST_POLICY')
FILE_11_L87=    t.need(core.valid_name(generation),'GENERATION_ID')
FILE_11_L88=    t.need(all(callable(f) for f in (produce,state_guard,guard,compression_check,say,clock)),'CALLBACKS_REQUIRED')
FILE_11_L89=    work=Path(work);state_guard();guard()
FILE_11_L90=    for sub in ('producer','upload','restore'):t.make_dir(work/sub,exclusive=True)
FILE_11_L91=    say('PHASE','REAL_SINGLE_GUEST_SNAPSHOT')
FILE_11_L92=    produced=produce(job,work/'producer')
FILE_11_L93=    source=check_result(produced,job,work/'producer');state_guard();guard()
FILE_11_L94=    t.create(work/'PRODUCER.json',core.canonical_bytes(produced))
FILE_11_L95=    say('PRODUCER_RC',0);say('PAYLOAD_BYTES',produced['size']);say('ARCHIVE_SHA256',produced['sha256'])
FILE_11_L96=    logical='guest-%s-%s-%d'%(job['node'],job['type'],job['vmid'])
FILE_11_L97=    say('PHASE','TWO_REPLICA_UPLOAD_AND_READBACK')
FILE_11_L98=    up=large.upload(source,work/'upload',entries,cloud,generation,logical,RESERVE_BYTES,guard,clock=clock)
FILE_11_L99=    t.need(up['manifest']['payload_bytes']==produced['size'] and up['manifest']['payload_sha256']==produced['sha256'],'MANIFEST_PRODUCER_MISMATCH')
FILE_11_L100=    say('SEALED_QUORUM_VERIFIED','YES');mh=core.manifest_hash(up['manifest']);say('MANIFEST_SHA256',mh)
FILE_11_L101=    say('PHASE','CLOUD_DISCOVERY_AND_ARCHIVE_RECONSTRUCTION')
FILE_11_L102=    found=large.discover(reader,entries,logical,mh)
FILE_11_L103=    restored=large.restore(work/'restore',reader,found)
FILE_11_L104=    t.need(compression_check(work/'restore/restored.bin') is True,'RECONSTRUCTED_COMPRESSION_FAILED')
FILE_11_L105=    state_guard();guard();say('PHASE','GUARDED_LOCAL_PAYLOAD_CLEANUP')
FILE_11_L106=    count=large.cleanup(up,restored,reader,guard)
FILE_11_L107=    return {'state':'SINGLE_GUEST_ARCHIVE_SEALED_AND_CLOUD_RECONSTRUCTED','vmid':job['vmid'],'type':job['type'],'node':job['node'],
FILE_11_L108=        'generation':generation,'logical_id':logical,'manifest_sha256':mh,'payload_bytes':produced['size'],'payload_sha256':produced['sha256'],
FILE_11_L109=        'replicas':up['manifest']['replicas'],'parts_count':len(up['manifest']['parts']),'archive_cloud_restore_verified':True,
FILE_11_L110=        'guest_restore_verified':False,'application_consistency_verified':False,'whole_node_backup':False,'local_payload_files_remaining':0,
FILE_11_L111=        'files_deleted':count,'accounts_scanned':found['accounts_scanned'],'config_sha256':job['config_sha256']}
FILE_12_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/large264.py
FILE_12_BYTES=16514
FILE_12_SHA256=5cc4641fc35e4dd554495a36146da7dbbb7f142d1450e04cc5d3c89678b8497a
FILE_12_CONTEXT_LINE_COUNT=180
FILE_12_L1="""264R1 streaming cloud adapter and synthetic boundary proof.
FILE_12_L2=
FILE_12_L3=No work on import. No guest/backup producer and no cloud deletion. Existing
FILE_12_L4=small-canary adapters are not modified. Only caller-owned local payload is removed,
FILE_12_L5=after two cloud seals and a separately cloud-discovered restore have been checked.
FILE_12_L6="""
FILE_12_L7=import hashlib
FILE_12_L8=import os
FILE_12_L9=from pathlib import Path
FILE_12_L10=import selectors
FILE_12_L11=import signal
FILE_12_L12=import subprocess
FILE_12_L13=import time
FILE_12_L14=import v2core as core
FILE_12_L15=import transport261 as t
FILE_12_L16=import restore262 as r
FILE_12_L17=import stream263 as s
FILE_12_L18=
FILE_12_L19=BOUNDARY_BYTES=536870929
FILE_12_L20=LOGICAL_ID='stream-canary-pve01'
FILE_12_L21=
FILE_12_L22=
FILE_12_L23=def process_stream(argv,env,size,digest,consume,seconds):
FILE_12_L24=    """Drain both pipes, hashing stdout incrementally; never retain the whole part."""
FILE_12_L25=    t.need(type(argv) is list and argv and seconds>0,'STREAM_PROCESS_ARGUMENTS')
FILE_12_L26=    sink=s.DigestSink(size,digest)
FILE_12_L27=    p=subprocess.Popen(argv,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
FILE_12_L38=        remaining=deadline-time.monotonic();t.need(remaining>0,'STREAM_TIMEOUT')
FILE_12_L39=        rc=p.wait(timeout=remaining);t.need(rc==0,'STREAM_PROCESS_RC_FAILED')
FILE_12_L40=        result=sink.finish();complete=True;return result
FILE_12_L41=    except subprocess.TimeoutExpired:raise t.Stop('STREAM_TIMEOUT') from None
FILE_12_L42=    finally:
FILE_12_L43=        if not complete or p.poll() is None:
FILE_12_L44=            try:os.killpg(p.pid,signal.SIGKILL)
FILE_12_L53=            '--cache-dir',str(Path(work)/'cache')]+args
FILE_12_L54=
FILE_12_L55=
FILE_12_L56=class CloudLarge(t.RcloneIO):
FILE_12_L57=    """Reuse the existing crypt inventory/namespace guards, not its in-memory payload I/O."""
FILE_12_L58=    def call(self,args,limit):
FILE_12_L59=        t.need(type(args) is list and args and args[0] in ('about','lsjson','copyto','cat'),'RCLONE_VERB_FORBIDDEN')
FILE_12_L60=        t.need(type(limit) is int and 0<=limit<=core.MANIFEST_MAX_BYTES+1,'METADATA_BOUND')
FILE_12_L61=        self.check();seconds=min(3600 if args[0]=='copyto' else 90,self.deadline-time.monotonic())
FILE_12_L62=        t.need(seconds>0,'CLOUD_DEADLINE');self.calls+=1
FILE_12_L63=        if args[0]=='copyto':self.writes_attempted+=1
FILE_12_L64=        rc,out=t.bounded_process(flags(self.executable,self.config_path,self.work,args),self.env,limit,seconds)
FILE_12_L65=        self.check();return rc,out
FILE_12_L66=    def put(self,remote,name,path):
FILE_12_L67=        dest=self.address(remote,name)
FILE_12_L68=        if name in ('manifest.json','SEALED.json'):
FILE_12_L69=            return super().put(remote,name,path)
FILE_12_L70=        part=next((p for p in self.manifest['parts'] if p['name']==name),None)
FILE_12_L71=        t.need(part is not None,'PART_NOT_IN_MANIFEST')
FILE_12_L72=        n,h,identity=s.hash_file(path,part['size'])
FILE_12_L73=        t.need(n==part['size'] and h==part['sha256'],'UPLOAD_SOURCE_HASH')
FILE_12_L74=        rc,_=self.call(['lsjson',dest,'--stat'],65536)
FILE_12_L75=        t.need(rc in (3,4),'OBJECT_NOT_PROVEN_ABSENT')
FILE_12_L76=        with s.file_handle(path,part['size']) as (_,size,seen):
FILE_12_L77=            t.need(seen==identity,'UPLOAD_SOURCE_CHANGED')
FILE_12_L78=            rc,_=self.call(['copyto',str(path),dest,'--immutable','--no-update-modtime'],65536)
FILE_12_L79=            t.need(rc==0,'CLOUD_COPY_FAILED')
FILE_12_L80=    def read_stream(self,remote,name,size,digest,consume):
FILE_12_L81=        address=self.address(remote,name)
FILE_12_L82=        part=next((p for p in self.manifest['parts'] if p['name']==name),None)
FILE_12_L83=        t.need(part is not None and part['size']==size and part['sha256']==digest,'READBACK_EXPECTATION')
FILE_12_L84=        self.check();seconds=min(3600,self.deadline-time.monotonic());t.need(seconds>0,'CLOUD_DEADLINE')
FILE_12_L85=        self.calls+=1
FILE_12_L86=        out=process_stream(flags(self.executable,self.config_path,self.work,['cat',address,'--count',str(size+1)]),
FILE_12_L90=
FILE_12_L91=class ReadOnlyLarge(r.ReadOnlyCloud):
FILE_12_L92=    """Metadata uses inherited bounded reads; this class has no upload API."""
FILE_12_L93=    def read_stream(self,remote,generation,name,size,digest,consume):
FILE_12_L94=        t.need(type(size) is int and 0<size<=core.PART_BYTES and core.valid_hash(digest),'READBACK_EXPECTATION')
FILE_12_L95=        t.need(type(name) is str and name.startswith('part-'),'PART_REQUIRED')
FILE_12_L96=        address=self.address(remote,generation,name)
FILE_12_L97=        self.check();seconds=min(3600,self.deadline-time.monotonic());t.need(seconds>0,'RESTORE_DEADLINE')
FILE_12_L98=        self.calls+=1
FILE_12_L99=        out=process_stream(flags(self.executable,self.snapshot,self.work,['cat',address,'--count',str(size+1)]),
FILE_12_L100=                           self.env,size,digest,consume,seconds)
FILE_12_L116=
FILE_12_L117=
FILE_12_L118=def receipt(rep,m,whole,count):
FILE_12_L119=    t.need(count==m['payload_bytes'] and whole.hexdigest()==m['payload_sha256'],'PAYLOAD_READBACK_MISMATCH')
FILE_12_L120=    return {**rep,'generation':m['generation'],'manifest_sha256':core.manifest_hash(m),
FILE_12_L121=            'payload_sha256':whole.hexdigest(),'payload_bytes':count,'parts':m['parts'],
FILE_12_L122=            'method':'download-sha256','ok':True}
FILE_12_L123=
FILE_12_L124=
FILE_12_L125=def upload(source,work,entries,cloud,generation,logical_id,reserve,guard,clock=lambda:int(time.time())):
FILE_12_L126=    """Upload and seal; retain all source bytes here. Cleanup is a later gated operation."""
FILE_12_L127=    work=Path(work);source=Path(source);guard();core.validate_inventory(entries)
FILE_12_L128=    t.need(core.valid_name(generation) and core.valid_name(logical_id),'GENERATION_ID')
FILE_12_L129=    partdir=work/'parts';t.make_dir(partdir,exclusive=True)
FILE_12_L130=    record=s.split_file(source,partdir)
FILE_12_L131=    t.create(work/'parts-record.json',core.canonical_bytes(record))
FILE_12_L132=    quotas={e['account_id']:cloud.quota(e['crypt_remote']) for e in entries}
FILE_12_L133=    allocation=core.allocate(entries,quotas,record['payload_bytes'],reserve,clock())
FILE_12_L134=    m=core.make_manifest(generation,logical_id,record['payload_bytes'],record['payload_sha256'],record['parts'],allocation)
FILE_12_L135=    mb=core.canonical_bytes(m);mh=core.manifest_hash(m);cloud.bind(m)
FILE_12_L136=    t.create(work/'allocation.json',core.canonical_bytes(allocation));t.create(work/'manifest.json',mb)
FILE_12_L137=    for rep in m['replicas']:
FILE_12_L138=        guard();cloud.absent(rep['crypt_remote'])
FILE_12_L139=    receipts=[]
FILE_12_L140=    for rep in m['replicas']:
FILE_12_L141=        guard();remote=rep['crypt_remote'];q=cloud.quota(remote)
FILE_12_L142=        t.need(core.quota_reason(q,clock()) is None and q['free']>=allocation['required_free_bytes'],'SELECTED_ACCOUNT_CAPACITY_CHANGED')
FILE_12_L143=        s.verify_parts(partdir,record)
FILE_12_L144=        for part in m['parts']:cloud.put(remote,part['name'],partdir/part['name'])
FILE_12_L145=        cloud.put(remote,'manifest.json',work/'manifest.json')
FILE_12_L146=        t.need(cloud.get(remote,'manifest.json',len(mb)+1)==mb,'MANIFEST_READBACK_MISMATCH')
FILE_12_L147=        whole=hashlib.sha256();count=0
FILE_12_L148=        for part in m['parts']:
FILE_12_L149=            observed=cloud.read_stream(remote,part['name'],part['size'],part['sha256'],whole.update)
FILE_12_L150=            t.need(observed=={'size':part['size'],'sha256':part['sha256']},'PART_READBACK_MISMATCH');count+=observed['size']
FILE_12_L151=        receipts.append(receipt(rep,m,whole,count));t.create(work/('receipt-%d.json'%len(receipts)),core.canonical_bytes(receipts[-1]))
FILE_12_L152=    core.verify_receipts(m,receipts)
FILE_12_L153=    seal={'schema_version':2,'state':'SEALED','generation':generation,'logical_id':logical_id,
FILE_12_L154=          'manifest_sha256':mh,'replicas':m['replicas'],'receipts':receipts,
FILE_12_L155=          'acceptance':'IDENTICAL_SEAL_REQUIRED_ON_BOTH_NAMED_ACCOUNTS'}
FILE_12_L156=    sb=core.canonical_bytes(seal);t.need(len(sb)<=core.SEAL_MAX_BYTES,'SEAL_BOUND')
FILE_12_L157=    r.validate_seal(sb,entries,generation,logical_id);t.create(work/'SEALED.json',sb)
FILE_12_L158=    for rep in m['replicas']:
FILE_12_L159=        guard();cloud.put(rep['crypt_remote'],'SEALED.json',work/'SEALED.json')
FILE_12_L160=    for rep in m['replicas']:
FILE_12_L161=        t.need(cloud.get(rep['crypt_remote'],'SEALED.json',len(sb)+1)==sb,'SEALED_QUORUM_REQUIRED')
FILE_12_L162=    guard();s.verify_parts(partdir,record)
FILE_12_L163=    t.create(work/'QUORUM_VERIFIED.json',core.canonical_bytes({'manifest_sha256':mh,'seal_sha256':t.sha(sb)}))
FILE_12_L164=    return {'sealed':True,'manifest':m,'seal_bytes':sb,'parts_record':record,'source':str(source),'work':str(work)}
FILE_12_L165=
FILE_12_L166=
FILE_12_L167=def discover(cloud,entries,logical_id,expected_hash):
FILE_12_L168=    """Find placement from all cloud catalogs, using only an external manifest digest."""
FILE_12_L169=    core.validate_inventory(entries)
FILE_12_L170=    t.need(core.valid_name(logical_id) and core.valid_hash(expected_hash),'DISCOVERY_INPUT')
FILE_12_L171=    listed={};generations=set()
FILE_12_L172=    for e in entries:
FILE_12_L173=        gs=cloud.list_generations(e['crypt_remote'])
FILE_12_L174=        t.need(type(gs) is list and len(gs)<=r.MAX_GENERATIONS and all(core.valid_name(g) for g in gs),'GENERATION_LIST_INVALID')
FILE_12_L175=        t.need(len(gs)==len(set(gs)),'GENERATION_LIST_DUPLICATE');listed[e['crypt_remote']]=set(gs);generations.update(gs)
FILE_12_L176=    t.need(len(generations)<=r.MAX_GENERATIONS,'TOTAL_GENERATIONS_BOUND')
FILE_12_L177=    candidates=[]
FILE_12_L178=    for gen in sorted(generations):
FILE_12_L179=        seen={}
FILE_12_L180=        for e in entries:
FILE_12_L181=            remote=e['crypt_remote']
FILE_12_L182=            if gen not in listed[remote]:continue
FILE_12_L183=            b=cloud.get(remote,gen,'SEALED.json',core.SEAL_MAX_BYTES+1,missing_ok=True)
FILE_12_L184=            if b is None:continue
FILE_12_L185=            seal=r.validate_seal(b,entries,gen,logical_id)
FILE_12_L186=            t.need(remote in {x['crypt_remote'] for x in seal['replicas']},'UNNAMED_SEAL_LOCATION');seen[remote]=(b,seal)
FILE_12_L187=        if not seen:continue
FILE_12_L188=        sb,seal=next(iter(seen.values()))
FILE_12_L189=        if seal['manifest_sha256']!=expected_hash:continue
FILE_12_L190=        named={x['crypt_remote'] for x in seal['replicas']}
FILE_12_L191=        t.need(set(seen)==named and all(b==sb for b,_ in seen.values()),'IDENTICAL_TWO_SEALS_REQUIRED')
FILE_12_L192=        blobs=[]
FILE_12_L193=        for rep in seal['replicas']:
FILE_12_L194=            b=cloud.get(rep['crypt_remote'],gen,'manifest.json',core.MANIFEST_MAX_BYTES+1)
FILE_12_L195=            t.need(type(b) is bytes and t.sha(b)==expected_hash,'MANIFEST_DIGEST_MISMATCH')
FILE_12_L196=            m=r.strict_json(b,core.MANIFEST_MAX_BYTES);core.validate_manifest(m)
FILE_12_L197=            t.need(m['generation']==gen and m['logical_id']==logical_id and m['replicas']==seal['replicas'],'MANIFEST_PLACEMENT')
FILE_12_L198=            t.need(core.canonical_bytes(m)==b,'MANIFEST_CANONICAL_BYTES');core.verify_receipts(m,seal['receipts']);blobs.append(b)
FILE_12_L199=        t.need(len(blobs)==2 and blobs[0]==blobs[1],'TWO_MANIFEST_COPIES_REQUIRED')
FILE_12_L200=        candidates.append({'manifest':m,'seal_bytes':sb,'accounts_scanned':len(listed)})
FILE_12_L201=    t.need(len(candidates)==1,'EXACTLY_ONE_ACCEPTED_GENERATION_REQUIRED')
FILE_12_L202=    return candidates[0]
FILE_12_L203=
FILE_12_L204=
FILE_12_L205=def fresh_seals(cloud,discovery):
FILE_12_L206=    m=discovery['manifest'];core.validate_manifest(m);sb=discovery['seal_bytes']
FILE_12_L207=    for rep in m['replicas']:
FILE_12_L208=        t.need(cloud.get(rep['crypt_remote'],m['generation'],'SEALED.json',len(sb)+1)==sb,'SEAL_CHANGED_DURING_RESTORE')
FILE_12_L209=
FILE_12_L210=
FILE_12_L211=def download_part(cloud,rep,m,part,path,whole):
FILE_12_L212=    path=Path(path);parent=t.open_dir(path.parent);fd=None
FILE_12_L213=    try:
FILE_12_L214=        fd=os.open(path.name,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600,dir_fd=parent)
FILE_12_L215=        def consume(block):whole.update(block);s.write_all(fd,block)
FILE_12_L216=        result=cloud.read_stream(rep['crypt_remote'],m['generation'],part['name'],part['size'],part['sha256'],consume)
FILE_13_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/nodeplan263.py
FILE_13_BYTES=4603
FILE_13_SHA256=db5c16ee24d25aa1694530332d3190ab7cc5d4f8eb69067d025e27ad5c995060
FILE_13_CONTEXT_LINE_COUNT=23
FILE_13_L1="""Pure, allowlisted PVE metadata projection. Does not execute any command."""
FILE_13_L2=from decimal import Decimal,InvalidOperation
FILE_13_L3=import hashlib
FILE_13_L4=import re
FILE_13_L5=import v2core as core
FILE_13_L6=
FILE_13_L7=class PlanError(ValueError):pass
FILE_13_L8=
FILE_13_L15=    if type(value) is not str or not re.fullmatch(r'\d+(?:\.\d+)?[KMGTPE]?',value):return None
FILE_13_L16=    try:
FILE_13_L17=        suffix=value[-1] if value[-1] in 'KMGTPE' else ''
FILE_13_L18=        base=Decimal(value[:-1] if suffix else value)
FILE_13_L19=        b=base*(1024**('KMGTPE'.index(suffix)+1) if suffix else 1)
FILE_13_L20=        return int(b) if b==int(b) and 0<b<=2**63-1 else None
FILE_13_L21=    except (ValueError,InvalidOperation):return None
FILE_13_L22=
FILE_13_L47=        need(type(value) is str and len(value)<=8192,'DISK_VALUE_BOUND')
FILE_13_L48=        fields=value.split(',');vol=fields[0];opts={}
FILE_13_L49=        for item in fields[1:]:
FILE_13_L50=            k,sep,v=item.partition('=')
FILE_13_L51=            if sep:
FILE_13_L52=                need(k not in opts,'DISK_DUPLICATE_PROPERTY');opts[k]=v
FILE_13_L53=        if opts.get('media')=='cdrom':cdrom+=1;continue
FILE_14_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve265.py
FILE_14_BYTES=12888
FILE_14_SHA256=cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be
FILE_14_CONTEXT_LINE_COUNT=80
FILE_14_L1="""PVE producer 265R1. Import has no effects. No network, cloud or payload deletion.
FILE_14_L2=
FILE_14_L3=The installer calls only make_plan; produce is an explicit, guarded future-run API.
FILE_14_L4=A successful compression test is not a VM/CT restore test or proof of application consistency.
FILE_14_L5="""
FILE_14_L6=import hashlib
FILE_14_L7=import os
FILE_14_L8=from pathlib import Path
FILE_14_L9=import re
FILE_14_L10=import selectors
FILE_14_L11=import signal
FILE_14_L12=import stat
FILE_14_L13=import subprocess
FILE_14_L14=import time
FILE_14_L15=import v2core as core
FILE_14_L16=import transport261 as t
FILE_14_L17=import stream263 as stream
FILE_14_L18=import nodeplan263 as np
FILE_14_L19=
FILE_14_L20=GIB=1024**3
FILE_14_L21=LOCAL_RESERVE=4*GIB
FILE_14_L32=    if not ok:raise PVEError(reason)
FILE_14_L33=
FILE_14_L34=def path_ok(path):
FILE_14_L35=    return isinstance(path,(str,Path)) and Path(path).is_absolute() and '..' not in Path(path).parts and all(32<=ord(c)<127 for c in str(path))
FILE_14_L36=
FILE_14_L37=def defaults_summary(raw):
FILE_14_L38=    need(raw is None or type(raw) is bytes and len(raw)<=262144,'DEFAULTS_BOUND')
FILE_14_L85=        for disk in summary['disks']:
FILE_14_L86=            slot=disk['slot'];opts={}
FILE_14_L87=            for field in cfg[slot].split(',')[1:]:
FILE_14_L88=                k,sep,v=field.partition('=')
FILE_14_L89=                if sep:opts[k]=v
FILE_14_L90=            if 'backup' in opts and opts['backup'] not in ('0','1','yes','no','on','off','true','false'):
FILE_14_L91=                block.add('BACKUP_FLAG_UNKNOWN')
FILE_14_L109=             'archive_cap_bytes':cap,'configured_full_cycle_fits':bool(configured_bound and 4*configured_bound+LOCAL_RESERVE<=staging_free),
FILE_14_L110=             'compression_dependent':bool(configured_bound and cap<configured_bound),
FILE_14_L111=             'coverage_eligible':not block,'local_reserve_bytes':LOCAL_RESERVE,'snapshot_history_included':False,
FILE_14_L112=             'cdrom_media_included':False,'application_consistency_verified':False,'guest_restore_verified':False}
FILE_14_L113=        jobs.append(job)
FILE_14_L114=    return {'schema_version':1,'node':node,'observed_at':now,'local_guest_count':len(jobs),
FILE_14_L115=            'jobs':jobs,'storages':ss,'global_defaults':global_summary,'global_blockers':global_summary['blockers'],
FILE_14_L147=        p.wait()
FILE_14_L148=
FILE_14_L149=def capture_archive(argv,destination,cap,seconds,check):
FILE_14_L150=    """Bounded, exclusive file capture from a producer; on failure keep partial bytes at 0600."""
FILE_14_L151=    need(type(argv) is list and argv and all(type(x) is str for x in argv),'ARGV')
FILE_14_L152=    need(type(cap) is int and 0<cap<=stream.MAX_BYTES,'ARCHIVE_CAP')
FILE_14_L153=    need(type(seconds) in (int,float) and 0<seconds<=86400,'DEADLINE')
FILE_14_L169=                b=os.read(key.fileobj.fileno(),65536)
FILE_14_L170=                if not b:sel.unregister(key.fileobj);continue
FILE_14_L171=                if key.fileobj is p.stdout:
FILE_14_L172=                    need(total+len(b)<=cap,'ARCHIVE_CAP_REACHED_PARTIAL_RETAINED')
FILE_14_L173=                    stream.write_all(fd,b);digest.update(b);total+=len(b)
FILE_14_L174=        need(deadline>time.monotonic(),'PRODUCER_TIMEOUT')
FILE_14_L175=        try:rc=p.wait(timeout=deadline-time.monotonic())
FILE_14_L176=        except subprocess.TimeoutExpired:raise PVEError('PRODUCER_TIMEOUT') from None
FILE_14_L177=        need(rc==0,'PRODUCER_RC_FAILED_PARTIAL_RETAINED');need(total>0,'EMPTY_ARCHIVE');check()
FILE_14_L178=        st=os.fstat(fd);named=os.stat(dest.name,dir_fd=parent,follow_symlinks=False)
FILE_14_L179=        need(st.st_dev==initial.st_dev and st.st_ino==initial.st_ino and t.ident(st)==t.ident(named) and
FILE_14_L180=             st.st_nlink==1 and st.st_size==total,'PRODUCER_FILE_IDENTITY_CHANGED')
FILE_14_L200=    """Future explicit execution API. Caller must recheck full plan/coverage in guard.
FILE_14_L201=
FILE_14_L202=    Compression CRC and SHA are verified; guest bootability remains unproved.
FILE_14_L203=    This function has no cloud/seal/delete operations and returns a readonly artifact.
FILE_14_L204=    """
FILE_14_L205=    need(callable(guard),'GUARD_REQUIRED');guard();validate_job(job,int(time.time()));validate_tools(tools)
FILE_14_L206=    work=Path(work);parent=stream.private_dir(work)
FILE_14_L209=    tmp=work/'tmp';t.make_dir(tmp,exclusive=True)
FILE_14_L210=    dest=work/('guest-%d.%s.zst'%(job['vmid'],'tar' if job['type']=='lxc' else 'vma'))
FILE_14_L211=    def free_guard():
FILE_14_L212=        v=os.statvfs(work);need(v.f_frsize*v.f_bavail>=LOCAL_RESERVE,'STAGING_RESERVE_REACHED_PARTIAL_RETAINED')
FILE_14_L213=    free_guard()
FILE_14_L214=    result=capture_archive(dump_argv(job,tools['vzdump']['path'],tmp,int(time.time())),dest,job['archive_cap_bytes'],seconds,free_guard)
FILE_14_L215=    guard();validate_tools(tools)
FILE_14_L219=    need(n==result['size'] and h==result['sha256'] and list(identity)==result['identity'],'PRODUCER_READBACK_MISMATCH')
FILE_14_L220=    guard();validate_tools(tools)
FILE_14_L221=    return {**result,'path':str(dest),'vmid':job['vmid'],'type':job['type'],'node':job['node'],
FILE_14_L222=            'config_sha256':job['config_sha256'],'compression_test_ok':True,'restored':False,
FILE_14_L223=            'state':'PRODUCED_COMPRESSION_CHECKED_NOT_CLOUD_SEALED','local_payload_retained':True}
FILE_15_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py
FILE_15_BYTES=19595
FILE_15_SHA256=97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef
FILE_15_CONTEXT_LINE_COUNT=140
FILE_15_L3=Does not modify installed pve265, old workspaces, staging permissions or guest config.
FILE_15_L4=Only explicit produce() executes vzdump. Private bounded stderr/exit metadata retained.
FILE_15_L5="""
FILE_15_L6=import hashlib,json,os,re,secrets,selectors,signal,stat,subprocess,sys,time
FILE_15_L7=from pathlib import Path
FILE_15_L8=import v2core as core
FILE_15_L9=import transport261 as t
FILE_15_L10=import stream263 as stream
FILE_15_L11=import pve265 as old
FILE_15_L12=need=old.need
FILE_15_L13=MAX_STDERR=2*1024**2
FILE_15_L14=EXPECTED_CFG='09957aacd41ba9eeaf5fd4eda13936d580c9082a46895433379aa9dd0bad5969'
FILE_15_L39=def live_gate(job,pvesh_path,pvesh_sha):
FILE_15_L40=    need(job.get('vmid')==110 and job.get('type')=='lxc' and job.get('node')=='pve01' and job.get('config_sha256')==EXPECTED_CFG,'ONLY_ACCEPTED_CT110')
FILE_15_L41=    vals=[]
FILE_15_L42=    for part in ('config','status/current','snapshot'):
FILE_15_L43=        need(t.sha(t.read_secure(Path(pvesh_path),16*1024**2)[0])==pvesh_sha,'PVESH_CHANGED')
FILE_15_L44=        rc,b=t.bounded_process([str(pvesh_path),'get','/nodes/pve01/lxc/110/'+part,'--output-format','json'],dict(old.ENV),262144,30)
FILE_15_L45=        need(rc==0,'CT_GATE_READ_FAILED')
FILE_15_L46=        try:vals.append(json.loads(b))
FILE_15_L47=        except (ValueError,UnicodeError):raise old.PVEError('CT_GATE_JSON') from None
FILE_15_L48=    validate_ct(*vals,job['config_sha256'])
FILE_15_L49=    return True
FILE_15_L50=
FILE_15_L59=    def __init__(self,path,alias):
FILE_15_L60=        self.path=Path(path);self.alias=Path(alias);self.parent=None;self.fd=None
FILE_15_L61=        need(self.path.name=='perl' and self.alias.name=='perl5.40.1' and self.path.parent==self.alias.parent,'PERL_PATH_POLICY')
FILE_15_L62=        need(self.path.is_absolute() and '..' not in self.path.parts,'PERL_PATH_POLICY')
FILE_15_L63=        try:
FILE_15_L64=            self.parent=os.open('/',os.O_RDONLY|os.O_DIRECTORY)
FILE_15_L65=            for part in self.path.parts[1:-1]:
FILE_15_L66=                nxt=os.open(part,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=self.parent)
FILE_15_L67=                os.close(self.parent);self.parent=nxt
FILE_15_L68=                s=os.fstat(nxt)
FILE_15_L69=                need(s.st_uid==0 and not s.st_mode&0o022,'PERL_PARENT_UNTRUSTED')
FILE_15_L75=            need(os.pread(self.fd,4,0)==b'\x7fELF','PERL_ELF_REQUIRED')
FILE_15_L76=            self.identity=t.ident(s)+(s.st_nlink,)
FILE_15_L77=            self.sha256=self._digest();self.check()
FILE_15_L78=        except BaseException:
FILE_15_L79=            self.close();raise
FILE_15_L80=    def _digest(self):
FILE_15_L81=        s=os.fstat(self.fd);need(0<s.st_size<=32*1024**2,'PERL_SIZE_BOUND')
FILE_15_L94=            # Verify that the trusted parent path still resolves to the open dir.
FILE_15_L95=            fd=os.open('/',os.O_RDONLY|os.O_DIRECTORY)
FILE_15_L96=            try:
FILE_15_L97=                for part in self.path.parts[1:-1]:
FILE_15_L98=                    nxt=os.open(part,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=fd)
FILE_15_L99=                    os.close(fd);fd=nxt;s=os.fstat(fd)
FILE_15_L100=                    need(s.st_uid==0 and not s.st_mode&0o022,'PERL_PARENT_UNTRUSTED')
FILE_15_L101=                a=os.fstat(fd);b=os.fstat(self.parent)
FILE_15_L102=                need((a.st_dev,a.st_ino)==(b.st_dev,b.st_ino),'PERL_PARENT_CHANGED')
FILE_15_L103=            finally:os.close(fd)
FILE_15_L104=        except OSError:raise old.PVEError('PERL_PATH_CHANGED') from None
FILE_15_L105=    def run(self,args,seconds=30):
FILE_15_L106=        need(type(args) is list and all(type(x) is str and '\x00' not in x for x in args),'PERL_ARGV')
FILE_15_L107=        need(type(seconds) in (int,float) and 0<seconds<=30,'PERL_DEADLINE')
FILE_15_L121=                        need(len(out)+len(b)<=16384,'PERL_STDOUT_BOUND');out.extend(b)
FILE_15_L122=            left=deadline-time.monotonic();need(left>0,'PERL_TIMEOUT')
FILE_15_L123=            rc=p.wait(timeout=left);self.check();return rc,bytes(out)
FILE_15_L124=        except subprocess.TimeoutExpired:raise old.PVEError('PERL_TIMEOUT') from None
FILE_15_L125=        finally:
FILE_15_L126=            if p is not None:
FILE_15_L127=                if p.poll() is None:
FILE_15_L150=        for p,h in pins.items():need(t.sha(t.read_secure(Path(p),2*1024**2)[0])==h,'PVE_MAPPING_SOURCE_CHANGED')
FILE_15_L151=        pin.check()
FILE_15_L152=    try:d=json.loads(b)
FILE_15_L153=    except (ValueError,UnicodeError):raise old.PVEError('PVE_IDMAP_JSON') from None
FILE_15_L154=    return validate_mapping(d)
FILE_15_L155=
FILE_15_L156=def _parent(path):
FILE_15_L157=    path=Path(path)
FILE_15_L158=    need(path.is_absolute() and '..' not in path.parts,'TEMP_PARENT_PATH')
FILE_15_L159=    fd=os.open('/',os.O_RDONLY|os.O_DIRECTORY)
FILE_15_L160=    try:
FILE_15_L161=        for i,part in enumerate(path.parts[1:]):
FILE_15_L162=            nxt=os.open(part,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=fd);os.close(fd);fd=nxt
FILE_15_L163=            s=os.fstat(fd);last=i==len(path.parts)-2
FILE_15_L164=            need(s.st_uid==0,'TEMP_PARENT_OWNER')
FILE_15_L165=            need(not s.st_mode&0o022 or last and s.st_mode&stat.S_ISVTX,'TEMP_PARENT_WRITABLE')
FILE_15_L166=        result=fd;fd=None;return result
FILE_15_L170=
FILE_15_L171=class MappedScratch:
FILE_15_L172=    """Root-owned, mapped-GID traverse-only, no access for others. No recursive cleanup."""
FILE_15_L173=    def __init__(self,gid,base='/var/tmp'):
FILE_15_L174=        need(type(gid) is int and gid==100000,'TEMP_GID_POLICY')
FILE_15_L175=        self.parent=_parent(base);self.fd=None;self.gid=gid
FILE_15_L176=        self.name='homelab-vzdump-268-'+secrets.token_hex(16);self.path=Path(base)/self.name
FILE_15_L177=        try:
FILE_15_L178=            os.mkdir(self.name,0o700,dir_fd=self.parent)
FILE_15_L179=            self.fd=os.open(self.name,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=self.parent)
FILE_15_L181=            os.fchown(self.fd,0,gid);os.fchmod(self.fd,0o710)
FILE_15_L182=            s=os.fstat(self.fd);self.identity=(s.st_dev,s.st_ino)
FILE_15_L183=            os.fsync(self.parent);self.check()
FILE_15_L184=        except BaseException:
FILE_15_L185=            if self.fd is not None:os.close(self.fd);self.fd=None
FILE_15_L186=            os.close(self.parent);self.parent=None
FILE_15_L187=            raise
FILE_15_L199=        name='access-probe';fd=os.open(name,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o644,dir_fd=self.fd)
FILE_15_L200=        try:os.fchmod(fd,0o644);stream.write_all(fd,b'HOMELAB_ACCESS_PROBE\n');os.fsync(fd);identity=t.ident(os.fstat(fd))
FILE_15_L201=        finally:os.close(fd)
FILE_15_L202=        positive='''import os,sys
FILE_15_L203=p,private=sys.argv[1:]
FILE_15_L204=assert open(p+'/access-probe','rb').read()==b'HOMELAB_ACCESS_PROBE\\n'
FILE_15_L205=for action in (lambda:os.listdir(p),lambda:os.open(p+'/forbidden',os.O_WRONLY|os.O_CREAT,0o600),lambda:os.open(private,os.O_RDONLY|os.O_DIRECTORY)):
FILE_15_L207= except PermissionError:continue
FILE_15_L208= raise SystemExit(31)
FILE_15_L209='''
FILE_15_L210=        negative='''import sys
FILE_15_L211=try:open(sys.argv[1]+'/access-probe','rb').read()
FILE_15_L212=except PermissionError:raise SystemExit(0)
FILE_15_L213=raise SystemExit(32)
FILE_15_L256=                b=os.read(key.fileobj.fileno(),65536)
FILE_15_L257=                if not b:sel.unregister(key.fileobj);continue
FILE_15_L258=                if key.fileobj is p.stdout:
FILE_15_L259=                    need(total+len(b)<=cap,'ARCHIVE_CAP_REACHED_PARTIAL_RETAINED')
FILE_15_L260=                    stream.write_all(fd,b);digest.update(b);total+=len(b)
FILE_15_L261=                else:
FILE_15_L262=                    err_total+=len(b);eh.update(b);chunk=b[:max(0,MAX_STDERR-err_kept)]
FILE_15_L263=                    if chunk:stream.write_all(efd,chunk);err_kept+=len(chunk)
FILE_15_L264=        need(deadline>time.monotonic(),'PRODUCER_TIMEOUT')
FILE_15_L265=        try:rc=p.wait(timeout=deadline-time.monotonic())
FILE_15_L266=        except subprocess.TimeoutExpired:raise old.PVEError('PRODUCER_TIMEOUT') from None
FILE_15_L267=        need(rc==0,'PRODUCER_RC_FAILED_PARTIAL_RETAINED');need(total>0,'EMPTY_ARCHIVE');check()
FILE_15_L268=        st=os.fstat(fd);named=os.stat(dest.name,dir_fd=parent,follow_symlinks=False)
FILE_15_L269=        need(st.st_dev==initial.st_dev and st.st_ino==initial.st_ino and t.ident(st)==t.ident(named) and st.st_nlink==1 and st.st_size==total,'PRODUCER_FILE_IDENTITY_CHANGED')
FILE_15_L270=        os.fchmod(fd,0o400);os.fsync(fd);os.fsync(parent);good=True
FILE_15_L306=        scratch.probe(uid,work);emit('MAPPED_UID_ACCESS_AND_ISOLATION_PROBE','PASS')
FILE_15_L307=        def free_guard():
FILE_15_L308=            scratch.check()
FILE_15_L309=            for path,reserve,reason in ((work,old.LOCAL_RESERVE,'STAGING_RESERVE_REACHED_PARTIAL_RETAINED'),(scratch.path,256*1024**2,'PVE_TEMP_RESERVE_LOW')):
FILE_15_L310=                v=os.statvfs(path);need(v.f_frsize*v.f_bavail>=reserve,reason)
FILE_15_L311=        free_guard();guard();dest=work/'guest-110.tar.zst'
FILE_15_L312=        result=capture_archive(old.dump_argv(job,tools['vzdump']['path'],scratch.path,int(time.time())),dest,job['archive_cap_bytes'],seconds,free_guard)
FILE_15_L317=        need(n==result['size'] and h==result['sha256'] and list(identity)==result['identity'],'PRODUCER_READBACK_MISMATCH')
FILE_15_L318=        guard();old.validate_tools(tools);scratch.close(empty_only=True);complete=True;emit('PVE_TEMP_EMPTY_REMOVED','YES')
FILE_15_L319=        return {**result,'path':str(dest),'vmid':110,'type':'lxc','node':job['node'],'config_sha256':job['config_sha256'],
FILE_15_L320=                'compression_test_ok':True,'restored':False,'state':'PRODUCED_COMPRESSION_CHECKED_NOT_CLOUD_SEALED','local_payload_retained':True}
FILE_15_L321=    finally:
FILE_15_L322=        m=work/'PRODUCER_PROCESS.json'
FILE_15_L323=        if m.exists():
FILE_16_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve282.py
FILE_16_BYTES=6195
FILE_16_SHA256=73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012
FILE_16_CONTEXT_LINE_COUNT=58
FILE_16_L1="""282R1 bounded CT112 adapter; proven 270 capture/temp/Perl implementation unchanged.
FILE_16_L2=Expected source hash must be supplied from the immutable-hash-bound 265 plan.
FILE_16_L3=No changes to source guest configuration; no source110 backup or guest deletion.
FILE_16_L4="""
FILE_16_L5=import copy,json,os,time
FILE_16_L6=from pathlib import Path
FILE_16_L7=import v2core as core
FILE_16_L8=import transport261 as t
FILE_16_L9=import stream263 as stream
FILE_16_L10=import pve265 as old
FILE_16_L11=import pve270 as proven
FILE_16_L12=import guest266 as g
FILE_16_L13=need=old.need
FILE_16_L14=PerlPin=proven.PerlPin
FILE_16_L15=host_mapping=proven.host_mapping
FILE_16_L26=    need(core.valid_hash(expected_config) and job.get('config_sha256')==expected_config,'CT112_PLAN_CONFIG_ANCHOR')
FILE_16_L27=    return True
FILE_16_L28=
FILE_16_L29=def select112(current,baseline,now):
FILE_16_L30=    rows=g.plan_rows(current);previous=g.plan_rows(baseline)
FILE_16_L31=    by_id={j['vmid']:j for j in previous}
FILE_16_L32=    need(TARGET_VMID in by_id,'CT112_MISSING_FROM_ACCEPTED265')
FILE_16_L33=    g.same_state(baseline,current,TARGET_VMID)
FILE_16_L34=    need({j['vmid'] for j in rows}==set(by_id),'ACCEPTED265_MEMBERSHIP_CHANGED')
FILE_16_L35=    for row in rows:
FILE_16_L36=        need(row['config_sha256']==by_id[row['vmid']]['config_sha256'],'ACCEPTED265_GUEST_CONFIG_CHANGED')
FILE_16_L37=    selected=[j for j in rows if j['vmid']==TARGET_VMID]
FILE_16_L38=    need(len(selected)==1,'CT112_NOT_UNIQUE')
FILE_16_L39=    job=copy.deepcopy(selected[0]);old.validate_job(job,now)
FILE_16_L40=    need(current.get('global_blockers')==[],'GLOBAL_DEFAULT_BLOCK')
FILE_16_L41=    need(job.get('compression_dependent') is False and job.get('configured_full_cycle_fits') is True,'CT112_FULL_CYCLE_SPACE_UNPROVEN')
FILE_16_L42=    disks=job.get('disks');need(type(disks) is list and len(disks)==1,'CT112_SINGLE_ROOTFS_REQUIRED')
FILE_16_L53=def live_gate(job,pvesh_path,pvesh_sha,expected_config):
FILE_16_L54=    require_target(job,expected_config)
FILE_16_L55=    vals=[]
FILE_16_L56=    for part in ('config','status/current','snapshot'):
FILE_16_L57=        need(t.sha(t.read_secure(Path(pvesh_path),16*1024**2)[0])==pvesh_sha,'PVESH_CHANGED')
FILE_16_L58=        rc,b=t.bounded_process([str(pvesh_path),'get','/nodes/pve01/lxc/112/'+part,'--output-format','json'],dict(old.ENV),262144,30)
FILE_16_L59=        need(rc==0,'CT112_GATE_READ_FAILED')
FILE_16_L60=        try:vals.append(json.loads(b))
FILE_16_L61=        except (ValueError,UnicodeError):raise old.PVEError('CT112_GATE_JSON') from None
FILE_16_L62=    validate_ct(*vals,expected_config)
FILE_16_L63=    return True
FILE_16_L64=
FILE_16_L79=        scratch.probe(uid,work);emit('MAPPED_UID_ACCESS_AND_ISOLATION_PROBE','PASS')
FILE_16_L80=        def free_guard():
FILE_16_L81=            scratch.check()
FILE_16_L82=            for path,reserve,reason in ((work,old.LOCAL_RESERVE,'STAGING_RESERVE_REACHED_PARTIAL_RETAINED'),(scratch.path,256*1024**2,'PVE_TEMP_RESERVE_LOW')):
FILE_16_L83=                v=os.statvfs(path);need(v.f_frsize*v.f_bavail>=reserve,reason)
FILE_16_L84=        free_guard();guard();dest=work/'guest-112.tar.zst'
FILE_16_L85=        result=capture_archive(old.dump_argv(job,tools['vzdump']['path'],scratch.path,int(time.time())),dest,job['archive_cap_bytes'],seconds,free_guard)
FILE_16_L90=        need(n==result['size'] and h==result['sha256'] and list(identity)==result['identity'],'PRODUCER_READBACK_MISMATCH')
FILE_16_L91=        guard();old.validate_tools(tools);scratch.close(empty_only=True);complete=True;emit('PVE_TEMP_EMPTY_REMOVED','YES')
FILE_16_L92=        return {**result,'path':str(dest),'vmid':112,'type':'lxc','node':job['node'],'config_sha256':job['config_sha256'],
FILE_16_L93=                'compression_test_ok':True,'restored':False,'state':'PRODUCED_COMPRESSION_CHECKED_NOT_CLOUD_SEALED','local_payload_retained':True}
FILE_16_L94=    finally:
FILE_16_L95=        m=work/'PRODUCER_PROCESS.json'
FILE_16_L96=        if m.exists():
FILE_17_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/restore262.py
FILE_17_BYTES=14701
FILE_17_SHA256=56d1b961c8d5654d5e2ee2755268db46bd2202bca11e69788febf991cfaa79f1
FILE_17_CONTEXT_LINE_COUNT=180
FILE_17_L1="""262R1 bounded cloud-discovered recovery. No live action on import.
FILE_17_L2=
FILE_17_L3=Cloud access is strictly lsjson/cat. No source-local workspace/manifest/receipt
FILE_17_L4=is read. The external accepted manifest digest is a trust anchor, not placement.
FILE_17_L5="""
FILE_17_L6=import hashlib
FILE_17_L7=import io
FILE_17_L8=import json
FILE_17_L9=import os
FILE_17_L10=from pathlib import Path
FILE_17_L11=import re
FILE_17_L12=import stat
FILE_17_L13=import tarfile
FILE_17_L14=import time
FILE_17_L15=import v2core as core
FILE_17_L16=import transport261 as t
FILE_17_L17=
FILE_17_L18=SOURCE_NAMES=frozenset(('etc/pve/HOMELAB_ASSISTANT_ERROR_REGISTER.md','etc/pve/31_HOMELAB_REFERENCE.md',
FILE_17_L19=                       'usr/local/sbin/homelab-control-backup','etc/systemd/system/homelab-control-backup.service'))
FILE_17_L20=ALL_NAMES=SOURCE_NAMES|{'SOURCE_INDEX.json'}
FILE_17_L21=MAX_GENERATIONS=64
FILE_17_L22=SEAL_KEYS={'schema_version','state','generation','logical_id','manifest_sha256','replicas','receipts','acceptance'}
FILE_17_L23=
FILE_17_L24=def strict_json(data,limit):
FILE_17_L25=    t.need(type(data) is bytes and len(data)<=limit,'JSON_BOUND')
FILE_17_L29=            t.need(k not in result,'JSON_DUPLICATE_KEY');result[k]=v
FILE_17_L30=        return result
FILE_17_L31=    def bad_constant(value):raise t.Stop('JSON_NONFINITE_NUMBER')
DEPENDENCY_PATH_COUNT=28
DEPENDENCY_PATH_1=/opt/homelab-backup-v2/releases/core-260r1
DEPENDENCY_PATH_2=/opt/homelab-backup-v2/releases/core-260r1/v2core.py
DEPENDENCY_PATH_3=/opt/homelab-backup-v2/releases/ct-backup-282r1
DEPENDENCY_PATH_4=/opt/homelab-backup-v2/releases/ct-backup-282r1/guest266.py
DEPENDENCY_PATH_5=/opt/homelab-backup-v2/releases/ct-backup-282r1/pve282.py
DEPENDENCY_PATH_6=/opt/homelab-backup-v2/releases/ct-backup-282r1/test_guest266.py
DEPENDENCY_PATH_7=/opt/homelab-backup-v2/releases/ct-backup-282r1/test_perl270.py
DEPENDENCY_PATH_8=/opt/homelab-backup-v2/releases/ct-backup-282r1/test_producer282.py
DEPENDENCY_PATH_9=/opt/homelab-backup-v2/releases/ct-backup-282r1/test_pve282.py
DEPENDENCY_PATH_10=/opt/homelab-backup-v2/releases/large-cloud-264r1
DEPENDENCY_PATH_11=/opt/homelab-backup-v2/releases/large-cloud-264r1/large264.py
DEPENDENCY_PATH_12=/opt/homelab-backup-v2/releases/pve-producer-265r1
DEPENDENCY_PATH_13=/opt/homelab-backup-v2/releases/pve-producer-265r1/PLAN.json
DEPENDENCY_PATH_14=/opt/homelab-backup-v2/releases/pve-producer-265r1/pve265.py
DEPENDENCY_PATH_15=/opt/homelab-backup-v2/releases/pve-producer-265r1/test_pve265.py
DEPENDENCY_PATH_16=/opt/homelab-backup-v2/releases/pve-retry-268r1
DEPENDENCY_PATH_17=/opt/homelab-backup-v2/releases/pve-retry-270r1
DEPENDENCY_PATH_18=/opt/homelab-backup-v2/releases/pve-retry-270r1/pve270.py
DEPENDENCY_PATH_19=/opt/homelab-backup-v2/releases/pve-retry-270r1/test_pve270.py
DEPENDENCY_PATH_20=/opt/homelab-backup-v2/releases/pve-run-266r1
DEPENDENCY_PATH_21=/opt/homelab-backup-v2/releases/restore-262r1
DEPENDENCY_PATH_22=/opt/homelab-backup-v2/releases/restore-262r1/restore262.py
DEPENDENCY_PATH_23=/opt/homelab-backup-v2/releases/stream-263r1
DEPENDENCY_PATH_24=/opt/homelab-backup-v2/releases/stream-263r1/nodeplan263.py
DEPENDENCY_PATH_25=/opt/homelab-backup-v2/releases/stream-263r1/stream263.py
DEPENDENCY_PATH_26=/opt/homelab-backup-v2/releases/transport-261r1
DEPENDENCY_PATH_27=/opt/homelab-backup-v2/releases/transport-261r1/transport261.py
DEPENDENCY_PATH_28=/opt/homelab-backup-v2/releases/vm-backup-283r1
HAS_RCLONE_SOURCE=true
HAS_OBJECT_PATH_CONTRACT=true
DECISION=PASS_BACKUP213_EXACT_CLOUD_OBJECT_CONTRACT_CAPTURED
NEXT_GATE=BUILD_CORRECTED_CLOUD_GENERATION_RECOVERY
CLOUD_READS=0
CLOUD_WRITES=0
VPS_SSH_ATTEMPTS=0
MESSENGERS214_CLOSED=false
MAJOR_STAGES_REMAINING=8
NEWFI213_END=true

OUTPUT_END
CHAT_OUTPUT_END
