CHAT_OUTPUT_BEGIN
COMMAND_ID=NEWFI-260920-NEWFDOM-MESSENGERS214-PRODUCER207
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=newfi-newfdom-messengers214-backupv2-producer-contract-readonly-audit
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
COMMAND_SHA256=ead8fdf05c4cb0a9b8b49f67777a3e68a7a96170d3e4b5061fa03171a66917da
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=99d8dcf2767bb4aeb57e414153ec37f086162257482529c3dcce3939c780c5ec
SANITIZED_OUTPUT_SHA256=99d8dcf2767bb4aeb57e414153ec37f086162257482529c3dcce3939c780c5ec
OUTPUT_BEGIN
NEWFI207_BEGIN=true
MODE=read-only
IMMUTABLE_PLAN_CHECK=PASS
CHANGES_MADE=false
MUTATION_OUTCOME=NO_MUTATION
PIN_CHECK=PASS
ACCEPTED_RELEASE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b
RELEASE_FILE_COUNT=6
INTERESTING_FILE_COUNT=6
FILE_1_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
FILE_1_BYTES=10566
FILE_1_MODE=0o400
FILE_1_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793
FILE_1_KEYWORD_SCORE=13
FILE_1_AST_DEF_COUNT=0
FILE_1_AST_IMPORT_COUNT=0
FILE_1_AST_STRING_COUNT=7
FILE_1_STRING_1_LINE=4
FILE_1_STRING_1_VALUE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1
FILE_1_STRING_2_LINE=62
FILE_1_STRING_2_VALUE=backup_target
FILE_1_STRING_3_LINE=62
FILE_1_STRING_3_VALUE=ssh_remote
FILE_1_STRING_4_LINE=135
FILE_1_STRING_4_VALUE=payload_sha256
FILE_1_STRING_5_LINE=135
FILE_1_STRING_5_VALUE=manifest_sha256
FILE_1_STRING_6_LINE=135
FILE_1_STRING_6_VALUE=replicas
FILE_1_STRING_7_LINE=132
FILE_1_STRING_7_VALUE=homelab-scheduler-proof-
FILE_2_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
FILE_2_BYTES=13825
FILE_2_MODE=0o400
FILE_2_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d
FILE_2_KEYWORD_SCORE=9
FILE_2_AST_DEF_COUNT=2
FILE_2_DEF_1_LINE=35
FILE_2_DEF_1_NAME=_remote_sha
FILE_2_DEF_2_LINE=117
FILE_2_DEF_2_NAME=_execute_remote
FILE_2_AST_IMPORT_COUNT=0
FILE_2_AST_STRING_COUNT=17
FILE_2_STRING_1_LINE=79
FILE_2_STRING_1_VALUE=/var/tmp/homelab-vzdump-v2-plan-only
FILE_2_STRING_2_LINE=118
FILE_2_STRING_2_VALUE=REMOTE_NODE
FILE_2_STRING_3_LINE=119
FILE_2_STRING_3_VALUE=REMOTE_ARGV
FILE_2_STRING_4_LINE=120
FILE_2_STRING_4_VALUE=REMOTE_ARGV_NODE
FILE_2_STRING_5_LINE=121
FILE_2_STRING_5_VALUE=REMOTE_CAP_VALUE
FILE_2_STRING_6_LINE=124
FILE_2_STRING_6_VALUE=REMOTE_WORKDIR
FILE_2_STRING_7_LINE=158
FILE_2_STRING_7_VALUE=remote-bounded-ssh-cwd-root
FILE_2_STRING_8_LINE=198
FILE_2_STRING_8_VALUE=/var/tmp/homelab-vzdump-v2-
FILE_2_STRING_9_LINE=149
FILE_2_STRING_9_VALUE=REMOTE_TIMEOUT
FILE_2_STRING_10_LINE=151
FILE_2_STRING_10_VALUE=REMOTE_RC
FILE_2_STRING_11_LINE=152
FILE_2_STRING_11_VALUE=REMOTE_EMPTY
FILE_2_STRING_12_LINE=155
FILE_2_STRING_12_VALUE=REMOTE_FILE_IDENTITY
FILE_2_STRING_13_LINE=162
FILE_2_STRING_13_VALUE=remote-bounded-ssh-cwd-root
FILE_2_STRING_14_LINE=204
FILE_2_STRING_14_VALUE=payload.bin
FILE_2_STRING_15_LINE=210
FILE_2_STRING_15_VALUE=VZDUMP_PAYLOAD_BOUND
FILE_2_STRING_16_LINE=138
FILE_2_STRING_16_VALUE=REMOTE_TIMEOUT
FILE_2_STRING_17_LINE=143
FILE_2_STRING_17_VALUE=REMOTE_CAP
FILE_3_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py
FILE_3_BYTES=4627
FILE_3_MODE=0o400
FILE_3_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b
FILE_3_KEYWORD_SCORE=9
FILE_3_AST_DEF_COUNT=1
FILE_3_DEF_1_LINE=11
FILE_3_DEF_1_NAME=_remote_sha
FILE_3_AST_IMPORT_COUNT=0
FILE_3_AST_STRING_COUNT=3
FILE_3_STRING_1_LINE=48
FILE_3_STRING_1_VALUE=/var/tmp/homelab-vzdump-v2-
FILE_3_STRING_2_LINE=66
FILE_3_STRING_2_VALUE=payload.bin
FILE_3_STRING_3_LINE=70
FILE_3_STRING_3_VALUE=QEMU_PAYLOAD_MISSING
FILE_4_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
FILE_4_BYTES=4097
FILE_4_MODE=0o400
FILE_4_SHA256=a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96
FILE_4_KEYWORD_SCORE=9
FILE_4_AST_DEF_COUNT=0
FILE_4_AST_IMPORT_COUNT=0
FILE_4_AST_STRING_COUNT=9
FILE_4_STRING_1_LINE=44
FILE_4_STRING_1_VALUE=last_success_payload_sha256
FILE_4_STRING_2_LINE=45
FILE_4_STRING_2_VALUE=last_success_manifest_sha256
FILE_4_STRING_3_LINE=45
FILE_4_STRING_3_VALUE=last_success_replicas
FILE_4_STRING_4_LINE=37
FILE_4_STRING_4_VALUE=payload_sha256
FILE_4_STRING_5_LINE=37
FILE_4_STRING_5_VALUE=last_success_payload_sha256
FILE_4_STRING_6_LINE=38
FILE_4_STRING_6_VALUE=manifest_sha256
FILE_4_STRING_7_LINE=38
FILE_4_STRING_7_VALUE=last_success_manifest_sha256
FILE_4_STRING_8_LINE=38
FILE_4_STRING_8_VALUE=replicas
FILE_4_STRING_9_LINE=38
FILE_4_STRING_9_VALUE=last_success_replicas
FILE_5_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
FILE_5_BYTES=3449
FILE_5_MODE=0o400
FILE_5_SHA256=b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3
FILE_5_KEYWORD_SCORE=7
FILE_5_AST_DEF_COUNT=0
FILE_5_AST_IMPORT_COUNT=0
FILE_5_AST_STRING_COUNT=2
FILE_5_STRING_1_LINE=4
FILE_5_STRING_1_VALUE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411
FILE_5_STRING_2_LINE=45
FILE_5_STRING_2_VALUE=payload.bin
FILE_6_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
FILE_6_BYTES=2320
FILE_6_MODE=0o400
FILE_6_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011
FILE_6_KEYWORD_SCORE=3
FILE_6_AST_DEF_COUNT=0
FILE_6_AST_IMPORT_COUNT=0
FILE_6_AST_STRING_COUNT=1
FILE_6_STRING_1_LINE=4
FILE_6_STRING_1_VALUE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1
CTX_1_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_1_START_LINE=15
CTX_1_END_LINE=21
CTX_1_L15=}
CTX_1_L16=
CTX_1_L17=def _sha(p):
CTX_1_L18=    h=hashlib.sha256()
CTX_1_L19=    with open(p,'rb',buffering=0) as f:
CTX_1_L20=        while True:
CTX_1_L21=            b=f.read(1<<20)
CTX_2_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_2_START_LINE=34
CTX_2_END_LINE=40
CTX_2_L34=
CTX_2_L35=class _GlobalsProxy:
CTX_2_L36=    __slots__=('_g',)
CTX_2_L37=    def __init__(self,g): object.__setattr__(self,'_g',g)
CTX_2_L38=    def __getattr__(self,n):
CTX_2_L39=        try: return self._g[n]
CTX_2_L40=        except KeyError as e: raise AttributeError(n) from e
CTX_3_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_3_START_LINE=59
CTX_3_END_LINE=72
CTX_3_L59=    if len(found)!=1:
CTX_3_L60=        raise RuntimeError('LEGACY_PROVENANCE_CARDINALITY')
CTX_3_L61=    g=next(iter(found.values()))
CTX_3_L62=    required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote',
CTX_3_L63=              '_default_unprivileged_lxc','mapped_scratch_probe','_stream_argv_to_local','run',
CTX_3_L64=              'choose_due_target','write_state','epoch')
CTX_3_L65=    if any(not callable(g.get(n)) for n in required):
CTX_3_L66=        raise RuntimeError('LEGACY_PROVENANCE_API')
CTX_3_L67=    original=g['capture_pve_guest']
CTX_3_L68=    proxy=_GlobalsProxy(g)
CTX_3_L69=    if not isinstance(g.get('SCP'),str) or not g['SCP'].startswith('/'):
CTX_3_L70=        raise RuntimeError('LEGACY_SCP_API')
CTX_3_L71=    qemu_patched=qemu_adapter.bind(proxy,original)
CTX_3_L72=    if not callable(qemu_patched):
CTX_4_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_4_START_LINE=75
CTX_4_END_LINE=82
CTX_4_L75=    if not callable(patched):
CTX_4_L76=        raise RuntimeError('LXC_ADAPTER_BIND_RESULT')
CTX_4_L77=    g['capture_pve_guest']=patched
CTX_4_L78=    scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state'])
CTX_4_L79=    if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']:
CTX_4_L80=        raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT')
CTX_4_L81=    return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired}
CTX_4_L82=
CTX_5_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_5_START_LINE=96
CTX_5_END_LINE=117
CTX_5_L96=    wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE)
CTX_5_L97=    return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired
CTX_5_L98=
CTX_5_L99=def _target(wrapper,lid):
CTX_5_L100=    rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid]
CTX_5_L101=    if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY')
CTX_5_L102=    return hits[0]
CTX_5_L103=
CTX_5_L104=def selftest():
CTX_5_L105=    wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()
CTX_5_L106=    if wired['legacy_globals'].get('capture_pve_guest') is not wired['patched_capture']:
CTX_5_L107=        raise RuntimeError('PATCH_BINDING')
CTX_5_L108=    if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']:
CTX_5_L109=        raise RuntimeError('SCHEDULER_CHOOSE_BINDING')
CTX_5_L110=    if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']:
CTX_5_L111=        raise RuntimeError('SCHEDULER_WRITE_BINDING')
CTX_5_L112=    if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]:
CTX_5_L113=        raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT')
CTX_5_L114=    if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets):
CTX_5_L115=        raise RuntimeError('WRAPPER_PUBLIC_API')
CTX_5_L116=    print('SELFTEST_OVERLAY504=PASS',flush=True)
CTX_5_L117=    return 0
CTX_6_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_6_START_LINE=125
CTX_6_END_LINE=187
CTX_6_L125=    if argv==['scheduler-proof']:
CTX_6_L126=        import tempfile
CTX_6_L127=        legacy=wired['legacy']; g=wired['legacy_globals']
CTX_6_L128=        old_root=g.get('STATE_ROOT'); old_epoch=g.get('epoch')
CTX_6_L129=        if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE')
CTX_6_L130=        now=[1000]
CTX_6_L131=        try:
CTX_6_L132=            with tempfile.TemporaryDirectory(prefix='homelab-scheduler-proof-',dir='/run') as td:
CTX_6_L133=                g['STATE_ROOT']=pathlib.Path(td); (g['STATE_ROOT']/'state').mkdir(mode=0o700)
CTX_6_L134=                g['epoch']=lambda: now[0]
CTX_6_L135=                common={'payload_sha256':'a'*64,'manifest_sha256':'b'*64,'replicas':['proof-r1','proof-r2']}
CTX_6_L136=                legacy.write_state('proof-a','SUCCESS',generation='proof-a-good',**common)
CTX_6_L137=                legacy.write_state('proof-b','SUCCESS',generation='proof-b-good',**common)
CTX_6_L138=                now[0]=100000
CTX_6_L139=                legacy.write_state('proof-a','FAIL',generation='proof-a-bad',reason='PROOF_FAILURE',sealed=False)
CTX_6_L140=                state=legacy.load_state_all(); a=state['proof-a']
CTX_6_L141=                targets=[{'logical_id':'proof-a','enabled':True,'due_seconds':100},{'logical_id':'proof-b','enabled':True,'due_seconds':100}]
CTX_6_L142=                first=legacy.choose_due_target(targets,state,now[0])
CTX_6_L143=                if not isinstance(first,dict) or first.get('logical_id')!='proof-b': raise RuntimeError('SCHEDULER_PROOF_PEER_NOT_SELECTED')
CTX_6_L144=                retry=int(a.get('retry_after_epoch',0)); preserved=int(a.get('last_success_epoch',0))
CTX_6_L145=                if preserved!=1000 or a.get('last_success_generation')!='proof-a-good' or int(a.get('consecutive_failures',0))!=1 or retry!=101800:
CTX_6_L146=                    raise RuntimeError('SCHEDULER_PROOF_FAILURE_STATE')
CTX_6_L147=                now[0]=retry+1
CTX_6_L148=                second=legacy.choose_due_target(targets,legacy.load_state_all(),now[0])
CTX_6_L149=                if not isinstance(second,dict) or second.get('logical_id')!='proof-a': raise RuntimeError('SCHEDULER_PROOF_RETRY_NOT_REELIGIBLE')
CTX_6_L150=                legacy.write_state('proof-a','SUCCESS',generation='proof-a-recovered',**common)
CTX_6_L151=                recovered=legacy.load_state_all()['proof-a']
CTX_6_L152=                if int(recovered.get('consecutive_failures',-1))!=0 or int(recovered.get('retry_after_epoch',-1))!=0:
CTX_6_L153=                    raise RuntimeError('SCHEDULER_PROOF_SUCCESS_RESET')
CTX_6_L154=                proof={'failed_target':'proof-a','peer_selected_during_backoff':first['logical_id'],'retry_after_epoch':retry,'last_success_preserved':preserved==1000,'retry_target_after_backoff':second['logical_id'],'success_resets_failures':True,'production_state_root_used':False}
CTX_6_L155=                print('SCHEDULER_FAILURE_ISOLATION_PROOF='+json.dumps(proof,separators=(',',':'),sort_keys=True),flush=True)
CTX_6_L156=                return 0
CTX_6_L157=        finally:
CTX_6_L158=            g['STATE_ROOT']=old_root; g['epoch']=old_epoch
CTX_6_L159=    if argv==['scheduler-select-live']:
CTX_6_L160=        state=legacy.load_state_all(); targets=wrapper.load_targets()
CTX_6_L161=        chosen=legacy.choose_due_target(targets,state)
CTX_6_L162=        if chosen is None:
CTX_6_L163=            print('SCHEDULER_LIVE_SELECTION=DEFER_NO_DUE_TARGET',flush=True)
CTX_6_L164=        else:
CTX_6_L165=            print('SCHEDULER_LIVE_SELECTION='+json.dumps({'logical_id':chosen.get('logical_id'),'due_seconds':chosen.get('due_seconds'),'enabled':chosen.get('enabled') is True},separators=(',',':'),sort_keys=True),flush=True)
CTX_6_L166=        return 0
CTX_6_L167=    if len(argv)==2 and argv[0]=='plan-lxc':
CTX_6_L168=        t=_target(wrapper,argv[1])
CTX_6_L169=        if t.get('guest_type')!='lxc' or t.get('logical_id')=='guest-pve01-lxc-112':
CTX_6_L170=            raise RuntimeError('PLAN_TARGET_NOT_LEGACY_LXC')
CTX_6_L171=        out=lxc_adapter.plan_only(legacy,t)
CTX_6_L172=        print('PLAN_LXC_RESULT='+json.dumps({'logical_id':t['logical_id'],'vmid':int(t['vmid']),'node':out['job']['node'],'job':out['job']},separators=(',',':'),sort_keys=True),flush=True)
CTX_6_L173=        return 0
CTX_6_L174=    if len(argv)==2 and argv[0]=='verify-target':
CTX_6_L175=        t=_target(wrapper,argv[1])
CTX_6_L176=        if t.get('logical_id')=='guest-pve01-lxc-112':
CTX_6_L177=            raise RuntimeError('VERIFY_SYNTHETIC_CT112_FORBIDDEN')
CTX_6_L178=        try:
CTX_6_L179=            out=wrapper.backup_target(t,True)
CTX_6_L180=        except legacy.BackupError as e:
CTX_6_L181=            print('VERIFY_TARGET_RESULT=FAIL',flush=True)
CTX_6_L182=            print('VERIFY_TARGET_REASON='+str(e.code),flush=True)
CTX_6_L183=            return 2
CTX_6_L184=        print('VERIFY_TARGET_RESULT='+json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)
CTX_6_L185=        return 0
CTX_6_L186=    return wrapper.main([sys.argv[0],*argv])
CTX_6_L187=
CTX_7_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_7_START_LINE=20
CTX_7_END_LINE=26
CTX_7_L20=    except Exception as e: raise AdapterError(code) from e
CTX_7_L21=
CTX_7_L22=def _sha_file(p):
CTX_7_L23=    h=hashlib.sha256()
CTX_7_L24=    with open(p,'rb',buffering=0) as f:
CTX_7_L25=        for b in iter(lambda:f.read(1<<20),b''): h.update(b)
CTX_7_L26=    return h.hexdigest()
CTX_8_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_8_START_LINE=32
CTX_8_END_LINE=62
CTX_8_L32=        if n<=0: raise AdapterError('WRITE_FAILED')
CTX_8_L33=        view=view[n:]
CTX_8_L34=
CTX_8_L35=def _remote_sha(legacy,node,path):
CTX_8_L36=    p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)
CTX_8_L37=    parts=p.stdout.decode('ascii','strict').strip().split()
CTX_8_L38=    _need(len(parts)>=2 and parts[1]==path,'TOOL_SHA_OUTPUT')
CTX_8_L39=    return parts[0]
CTX_8_L40=
CTX_8_L41=def _live_inputs(legacy,node,vmid,scratch):
CTX_8_L42=    _need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY')
CTX_8_L43=    _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY')
CTX_8_L44=    rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON')
CTX_8_L45=    stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON')
CTX_8_L46=    _need(type(rows) is list and type(stores) is list,'PVE_LIST_SCHEMA')
CTX_8_L47=    configs=[]
CTX_8_L48=    for r in rows:
CTX_8_L49=        if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue
CTX_8_L50=        try: rid=int(r.get('vmid'))
CTX_8_L51=        except Exception: raise AdapterError('RESOURCE_VMID')
CTX_8_L52=        cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r["type"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON')
CTX_8_L53=        _need(type(cfg) is dict,'CONFIG_SCHEMA')
CTX_8_L54=        configs.append([rid,cfg])
CTX_8_L55=    tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON')
CTX_8_L56=    _need(type(tasks) is list and len(tasks)<1000,'TASKS_SCHEMA')
CTX_8_L57=    q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False)
CTX_8_L58=    defaults=None
CTX_8_L59=    if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout
CTX_8_L60=    elif q.returncode!=1: raise AdapterError('DEFAULTS_PROBE')
CTX_8_L61=    st=os.statvfs('/mnt/staging'); free=int(st.f_bavail*st.f_frsize)
CTX_8_L62=    return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs,
CTX_9_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_9_START_LINE=85
CTX_9_END_LINE=91
CTX_9_L85=    a=_helper(_live_inputs(legacy,node,vmid,scratch)); b=_helper(_live_inputs(legacy,node,vmid,scratch))
CTX_9_L86=    _need(_stable_job(a['job'])==_stable_job(b['job']),'FRESH_PLAN_UNSTABLE')
CTX_9_L87=    _need(a['argv']==b['argv'],'FRESH_ARGV_UNSTABLE')
CTX_9_L88=    _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_POST')
CTX_9_L89=    return b
CTX_9_L90=
CTX_9_L91=def _execute_local(legacy,node,argv,dest,cap,timeout):
CTX_10_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_10_START_LINE=94
CTX_10_END_LINE=109
CTX_10_L94=    data=json.dumps(inp,separators=(',',':'),sort_keys=True).encode()
CTX_10_L95=    p=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)
CTX_10_L96=    if p.stderr or not p.stdout or len(p.stdout)>262144:
CTX_10_L97=        raise ExecFailure('LOCAL_HELPER_PROTOCOL',{'executor':'local-proven-pve270','producer_rc':None,'stderr_stream_sha256':hashlib.sha256(p.stderr).hexdigest(),'stderr_bytes_observed':len(p.stderr)})
CTX_10_L98=    try: out=json.loads(p.stdout)
CTX_10_L99=    except Exception:
CTX_10_L100=        raise ExecFailure('LOCAL_HELPER_JSON',{'executor':'local-proven-pve270','producer_rc':None,'stderr_stream_sha256':hashlib.sha256(p.stderr).hexdigest(),'stderr_bytes_observed':len(p.stderr)})
CTX_10_L101=    summary={'executor':'local-proven-pve270','helper_rc':p.returncode,'exception_class':out.get('exception_class'),'exception_message_sha256':out.get('exception_message_sha256')}
CTX_10_L102=    if isinstance(out.get('process'),dict): summary.update(out['process'])
CTX_10_L103=    if p.returncode!=0 or out.get('status')!='OK': raise ExecFailure('LOCAL_PRODUCER_FAILED',summary)
CTX_10_L104=    result=out.get('result'); _need(type(result) is dict,'LOCAL_RESULT_SCHEMA')
CTX_10_L105=    _need(pathlib.Path(dest).is_file() and pathlib.Path(dest).stat().st_size==int(result.get('size',-1)),'LOCAL_RESULT_FILE')
CTX_10_L106=    return summary|{'size':result['size'],'sha256':result['sha256'],'producer_rc':result.get('producer_rc')}
CTX_10_L107=
CTX_10_L108=def _kill(p):
CTX_10_L109=    try: os.killpg(p.pid,signal.SIGTERM)
CTX_11_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_11_START_LINE=114
CTX_11_END_LINE=166
CTX_11_L114=        except ProcessLookupError: pass
CTX_11_L115=        p.wait()
CTX_11_L116=
CTX_11_L117=def _execute_remote(legacy,node,argv,dest,cap,timeout):
CTX_11_L118=    _need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE')
CTX_11_L119=    _need(type(argv) is list and argv and argv[0]=='/usr/bin/vzdump' and all(type(x) is str and '\x00' not in x for x in argv),'REMOTE_ARGV')
CTX_11_L120=    _need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE')
CTX_11_L121=    _need(type(cap) is int and 0<cap<=16*1024**3,'REMOTE_CAP_VALUE')
CTX_11_L122=    _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_PRE')
CTX_11_L123=    dest=pathlib.Path(dest); parent=dest.parent
CTX_11_L124=    st=os.lstat(parent); _need(stat.S_ISDIR(st.st_mode) and not stat.S_ISLNK(st.st_mode) and st.st_uid==0 and stat.S_IMODE(st.st_mode)==0o700,'REMOTE_WORKDIR')
CTX_11_L125=    errp=parent/'producer.stderr.log'; metap=parent/'PRODUCER_PROCESS.json'
CTX_11_L126=    fd=os.open(dest,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600); efd=os.open(errp,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600)
CTX_11_L127=    initial=os.fstat(fd)
CTX_11_L128=    digest=hashlib.sha256(); eh=hashlib.sha256(); total=err_total=err_kept=0; p=None; sel=None; good=False
CTX_11_L129=    remote='cd / && exec '+shlex.join(argv)
CTX_11_L130=    ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]
CTX_11_L131=    deadline=time.monotonic()+timeout
CTX_11_L132=    try:
CTX_11_L133=        p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)
CTX_11_L134=        sel=selectors.DefaultSelector()
CTX_11_L135=        for pipe in (p.stdout,p.stderr): os.set_blocking(pipe.fileno(),False); sel.register(pipe,selectors.EVENT_READ)
CTX_11_L136=        while sel.get_map():
CTX_11_L137=            now=time.monotonic()
CTX_11_L138=            if now>=deadline: raise ExecFailure('REMOTE_TIMEOUT',{})
CTX_11_L139=            for key,_ in sel.select(min(.2,max(0,deadline-now))):
CTX_11_L140=                b=os.read(key.fileobj.fileno(),65536)
CTX_11_L141=                if not b: sel.unregister(key.fileobj); continue
CTX_11_L142=                if key.fileobj is p.stdout:
CTX_11_L143=                    if total+len(b)>cap: raise ExecFailure('REMOTE_CAP',{})
CTX_11_L144=                    _write_all(fd,b); digest.update(b); total+=len(b)
CTX_11_L145=                else:
CTX_11_L146=                    err_total+=len(b); eh.update(b); keep=b[:max(0,MAX_STDERR-err_kept)]
CTX_11_L147=                    if keep: _write_all(efd,keep); err_kept+=len(keep)
CTX_11_L148=        left=deadline-time.monotonic()
CTX_11_L149=        if left<=0: raise ExecFailure('REMOTE_TIMEOUT',{})
CTX_11_L150=        rc=p.wait(timeout=left)
CTX_11_L151=        if rc!=0: raise ExecFailure('REMOTE_RC',{})
CTX_11_L152=        if total<=0: raise ExecFailure('REMOTE_EMPTY',{})
CTX_11_L153=        stf=os.fstat(fd); named=os.stat(dest,follow_symlinks=False)
CTX_11_L154=        if (stf.st_dev,stf.st_ino)!=(initial.st_dev,initial.st_ino) or (named.st_dev,named.st_ino)!=(initial.st_dev,initial.st_ino) or stf.st_nlink!=1 or stf.st_size!=total:
CTX_11_L155=            raise ExecFailure('REMOTE_FILE_IDENTITY',{})
CTX_11_L156=        _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST')
CTX_11_L157=        os.fchmod(fd,0o400); os.fsync(fd); os.fsync(efd); good=True
CTX_11_L158=        return {'executor':'remote-bounded-ssh-cwd-root','producer_rc':rc,'size':total,'sha256':digest.hexdigest(),
CTX_11_L159=                'stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}
CTX_11_L160=    except ExecFailure as e:
CTX_11_L161=        if p is not None and p.poll() is None: _kill(p)
CTX_11_L162=        summary={'executor':'remote-bounded-ssh-cwd-root','producer_rc':None if p is None else p.returncode,'archive_bytes':total,
CTX_11_L163=                 'stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}
CTX_11_L164=        summary.update(e.summary); raise ExecFailure(e.code,summary)
CTX_11_L165=    finally:
CTX_11_L166=        if p is not None:
CTX_12_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_12_START_LINE=171
CTX_12_END_LINE=178
CTX_12_L171=        try: os.fsync(fd); os.fsync(efd)
CTX_12_L172=        except OSError: pass
CTX_12_L173=        os.close(fd); os.close(efd)
CTX_12_L174=        summary={'process_started':p is not None,'producer_rc':None if p is None else p.returncode,'capture_success':good,'archive_bytes':total,
CTX_12_L175=                 'stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest(),'raw_stderr_exported':False,'cwd':'/'}
CTX_12_L176=        try:
CTX_12_L177=            mb=(json.dumps(summary,separators=(',',':'),sort_keys=True)+'\n').encode()
CTX_12_L178=            mfd=os.open(metap,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600)
CTX_13_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_13_START_LINE=182
CTX_13_END_LINE=188
CTX_13_L182=
CTX_13_L183=def _emit_diag(node,summary):
CTX_13_L184=    safe={'node':node}
CTX_13_L185=    for k in ('executor','failure_code','helper_rc','producer_rc','archive_bytes','stderr_bytes_observed','stderr_bytes_retained','stderr_truncated','stderr_stream_sha256','exception_class','exception_message_sha256'):
CTX_13_L186=        if k in summary: safe[k]=summary[k]
CTX_13_L187=    print('LXC_EXECUTION_DIAG='+json.dumps(safe,separators=(',',':'),sort_keys=True),flush=True)
CTX_13_L188=
CTX_14_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_14_START_LINE=196
CTX_14_END_LINE=218
CTX_14_L196=        _need(typ==t.get('guest_type')=='lxc','PVE_GUEST_TYPE_DRIFT')
CTX_14_L197=        legacy._default_unprivileged_lxc(node,vmid)
CTX_14_L198=        scratch=f'/var/tmp/homelab-vzdump-v2-{gen}'
CTX_14_L199=        legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)
CTX_14_L200=        q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)
CTX_14_L201=        _need(q.stdout.decode().strip()=='710:0:100000','PVE_MAPPED_SCRATCH_ACCESS_CONTRACT')
CTX_14_L202=        try:
CTX_14_L203=            legacy.mapped_scratch_probe(node,scratch)
CTX_14_L204=            p=plan_only(legacy,t,scratch); local=pathlib.Path(work)/'payload.bin'; cap=int(p['job']['archive_cap_bytes'])
CTX_14_L205=            try:
CTX_14_L206=                result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200)
CTX_14_L207=            except ExecFailure as e:
CTX_14_L208=                _emit_diag(node,e.summary|{'failure_code':e.code})
CTX_14_L209=                raise legacy.BackupError('LXC_PRODUCER_FAILED') from None
CTX_14_L210=            _need(local.is_file() and 0<local.stat().st_size<=cap,'VZDUMP_PAYLOAD_BOUND')
CTX_14_L211=            _emit_diag(node,result)
CTX_14_L212=        except Exception:
CTX_14_L213=            legacy.ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False); raise
CTX_14_L214=        cleanup={'kind':'pve_source_dir','node':node,'path':scratch}
CTX_14_L215=        meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'lxc','node':node,'status':row.get('status'),
CTX_14_L216=              'producer_contract':'fresh-pve265-plan-bounded-producer-overlay502'}
CTX_14_L217=        return local,meta,cleanup
CTX_14_L218=    capture_pve_guest.__name__='capture_pve_guest'; return capture_pve_guest
CTX_15_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py
CTX_15_START_LINE=8
CTX_15_END_LINE=37
CTX_15_L8=def _need(ok,code):
CTX_15_L9=    if not ok: raise QemuAdapterError(code)
CTX_15_L10=
CTX_15_L11=def _remote_sha(legacy,node,path):
CTX_15_L12=    p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)
CTX_15_L13=    parts=p.stdout.decode('ascii','strict').strip().split()
CTX_15_L14=    _need(len(parts)>=2 and parts[1]==path,'QEMU_TOOL_SHA_OUTPUT')
CTX_15_L15=    return parts[0]
CTX_15_L16=
CTX_15_L17=def _select_qemu_outputs(vmid,files):
CTX_15_L18=    _need(type(vmid) is int and vmid>0,'QEMU_VMID')
CTX_15_L19=    _need(type(files) is list and files and all(type(x) is str and x.startswith('/') and '\x00' not in x for x in files),'QEMU_OUTPUT_LIST')
CTX_15_L20=    _need(len(files)==len(set(files)),'QEMU_OUTPUT_DUPLICATE')
CTX_15_L21=    pat=re.compile(r'^vzdump-qemu-'+re.escape(str(vmid))+r'-(\d{4}_\d{2}_\d{2}-\d{2}_\d{2}_\d{2})\.vma\.zst$')
CTX_15_L22=    archives=[]
CTX_15_L23=    for f in files:
CTX_15_L24=        name=pathlib.PurePosixPath(f).name
CTX_15_L25=        m=pat.fullmatch(name)
CTX_15_L26=        if m: archives.append((f,m.group(1)))
CTX_15_L27=    _need(len(archives)==1,'QEMU_ARCHIVE_NOT_UNIQUE')
CTX_15_L28=    archive,stamp=archives[0]; parent=pathlib.PurePosixPath(archive).parent
CTX_15_L29=    expected_log=parent/f'vzdump-qemu-{vmid}-{stamp}.log'
CTX_15_L30=    allowed={archive}; log=None
CTX_15_L31=    if str(expected_log) in files:
CTX_15_L32=        log=str(expected_log); allowed.add(log)
CTX_15_L33=    _need(set(files)==allowed,'QEMU_OUTPUT_UNEXPECTED_FILE')
CTX_15_L34=    return archive,log
CTX_15_L35=
CTX_15_L36=def _emit_diag(**kw):
CTX_15_L37=    print('QEMU_EXECUTION_DIAG='+json.dumps(kw,separators=(',',':'),sort_keys=True),flush=True)
CTX_16_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py
CTX_16_START_LINE=44
CTX_16_END_LINE=78
CTX_16_L44=        _need(len(rows)==1,'PVE_GUEST_NOT_UNIQUE')
CTX_16_L45=        row=rows[0]; node=row.get('node'); typ=row.get('type')
CTX_16_L46=        _need(typ==t.get('guest_type')=='qemu','PVE_GUEST_TYPE_DRIFT')
CTX_16_L47=        _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE')
CTX_16_L48=        srcdir=f'/var/tmp/homelab-vzdump-v2-{gen}'
CTX_16_L49=        legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)
CTX_16_L50=        try:
CTX_16_L51=            vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False)
CTX_16_L52=            if vp.returncode!=0:
CTX_16_L53=                _emit_diag(vmid=vmid,node=node,producer_rc=vp.returncode,stderr_bytes=len(vp.stderr),stderr_sha256=hashlib.sha256(vp.stderr).hexdigest(),archive_selected=False)
CTX_16_L54=                raise legacy.BackupError('QEMU_VZDUMP_FAILED')
CTX_16_L55=            _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST')
CTX_16_L56=            p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\n'],timeout=30)
CTX_16_L57=            files=[x for x in p.stdout.decode('utf-8','strict').splitlines() if x]
CTX_16_L58=            try: src,log=_select_qemu_outputs(vmid,files)
CTX_16_L59=            except QemuAdapterError as e:
CTX_16_L60=                _emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e))
CTX_16_L61=                raise legacy.BackupError(str(e)) from None
CTX_16_L62=            q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30)
CTX_16_L63=            raw=q.stdout.decode('ascii','strict').strip()
CTX_16_L64=            _need(raw.isdigit() and int(raw)>0,'QEMU_ARCHIVE_STAT')
CTX_16_L65=            size=int(raw)
CTX_16_L66=            local=pathlib.Path(work)/'payload.bin'
CTX_16_L67=            if node=='pve01': local=pathlib.Path(src)
CTX_16_L68=            else:
CTX_16_L69=                legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)
CTX_16_L70=            _need(pathlib.Path(local).is_file() and pathlib.Path(local).stat().st_size==size,'QEMU_PAYLOAD_MISSING')
CTX_16_L71=            _emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),sidecar_count=1 if log else 0,archive_bytes=size,archive_selected=True)
CTX_16_L72=        except Exception:
CTX_16_L73=            legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise
CTX_16_L74=        cleanup={'kind':'pve_source_dir','node':node,'path':srcdir}
CTX_16_L75=        meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'),
CTX_16_L76=              'producer_contract':'strict-qemu-vma-zst-plus-matching-log-overlay503'}
CTX_16_L77=        return pathlib.Path(local),meta,cleanup
CTX_16_L78=    capture_pve_guest.__name__='capture_pve_guest'
CTX_17_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_17_START_LINE=20
CTX_17_END_LINE=28
CTX_17_L20=    n=max(1,_as_nonneg_int(consecutive_failures,1))
CTX_17_L21=    return min(MAX_BACKOFF,MIN_BACKOFF*(2**min(n-1,4)))
CTX_17_L22=
CTX_17_L23=def _read_prior(legacy,logical_id):
CTX_17_L24=    root=pathlib.Path(legacy.STATE_ROOT)/'state'
CTX_17_L25=    p=root/(str(logical_id)+'.json')
CTX_17_L26=    try:
CTX_17_L27=        if not p.is_file(): return {}
CTX_17_L28=        d=json.loads(p.read_text(encoding='utf-8'))
CTX_18_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_18_START_LINE=34
CTX_18_END_LINE=48
CTX_18_L34=    if not isinstance(prior,dict): return {}
CTX_18_L35=    if prior.get('result')=='SUCCESS':
CTX_18_L36=        out={'last_success_epoch':_as_nonneg_int(prior.get('last_success_epoch'),0)}
CTX_18_L37=        mapping=(('generation','last_success_generation'),('payload_sha256','last_success_payload_sha256'),
CTX_18_L38=                 ('manifest_sha256','last_success_manifest_sha256'),('replicas','last_success_replicas'),
CTX_18_L39=                 ('green_verified','last_success_green_verified'))
CTX_18_L40=        for src,dst in mapping:
CTX_18_L41=            if src in prior: out[dst]=prior[src]
CTX_18_L42=        return out
CTX_18_L43=    out={}
CTX_18_L44=    for k in ('last_success_epoch','last_success_generation','last_success_payload_sha256',
CTX_18_L45=              'last_success_manifest_sha256','last_success_replicas','last_success_green_verified'):
CTX_18_L46=        if k in prior: out[k]=prior[k]
CTX_18_L47=    return out
CTX_18_L48=
CTX_19_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_19_START_LINE=50
CTX_19_END_LINE=65
CTX_19_L50=    _need(callable(original_choose),'ORIGINAL_CHOOSE_REQUIRED')
CTX_19_L51=    _need(callable(original_write),'ORIGINAL_WRITE_REQUIRED')
CTX_19_L52=    _need(callable(getattr(legacy,'epoch',None)),'LEGACY_EPOCH_REQUIRED')
CTX_19_L53=    _need(hasattr(legacy,'STATE_ROOT'),'LEGACY_STATE_ROOT_REQUIRED')
CTX_19_L54=
CTX_19_L55=    def choose_due_target(targets,state,now=None):
CTX_19_L56=        now=_as_nonneg_int(legacy.epoch() if now is None else now,0)
CTX_19_L57=        _need(isinstance(targets,list) and isinstance(state,dict),'SCHEDULER_INPUT_SCHEMA')
CTX_19_L58=        due=[]
CTX_19_L59=        for order,t in enumerate(targets):
CTX_19_L60=            if not isinstance(t,dict) or t.get('enabled') is not True: continue
CTX_19_L61=            lid=t.get('logical_id'); seconds=_as_nonneg_int(t.get('due_seconds'),0)
CTX_19_L62=            _need(isinstance(lid,str) and lid and seconds>0,'SCHEDULER_TARGET_SCHEMA')
CTX_19_L63=            s=state.get(lid,{})
CTX_19_L64=            if not isinstance(s,dict): s={}
CTX_19_L65=            retry_after=_as_nonneg_int(s.get('retry_after_epoch'),0)
CTX_20_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_20_START_LINE=72
CTX_20_END_LINE=93
CTX_20_L72=        if not due: return None
CTX_20_L73=        return max(due,key=lambda x:(x[0],x[1]))[2]
CTX_20_L74=
CTX_20_L75=    def write_state(logical_id,result,**kw):
CTX_20_L76=        now=_as_nonneg_int(legacy.epoch(),0)
CTX_20_L77=        prior=_read_prior(legacy,logical_id)
CTX_20_L78=        if result=='SUCCESS':
CTX_20_L79=            clean=dict(kw)
CTX_20_L80=            clean.update({'last_attempt_epoch':now,'consecutive_failures':0,'retry_after_epoch':0,'failure_backoff_seconds':0})
CTX_20_L81=            return original_write(logical_id,result,**clean)
CTX_20_L82=        failures=_as_nonneg_int(prior.get('consecutive_failures'),0)+1
CTX_20_L83=        backoff=backoff_seconds(failures)
CTX_20_L84=        clean=dict(kw)
CTX_20_L85=        clean.update(_success_snapshot(prior))
CTX_20_L86=        clean.update({'last_attempt_epoch':now,'consecutive_failures':failures,
CTX_20_L87=                      'retry_after_epoch':now+backoff,'failure_backoff_seconds':backoff})
CTX_20_L88=        return original_write(logical_id,result,**clean)
CTX_20_L89=
CTX_20_L90=    legacy.choose_due_target=choose_due_target
CTX_20_L91=    legacy.write_state=write_state
CTX_20_L92=    return {'choose_due_target':choose_due_target,'write_state':write_state,
CTX_20_L93=            'original_choose':original_choose,'original_write':original_write}
CTX_21_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_21_START_LINE=7
CTX_21_END_LINE=13
CTX_21_L7=MAX_INPUT=262144
CTX_21_L8=
CTX_21_L9=def sha_file(p:pathlib.Path)->str:
CTX_21_L10=    h=hashlib.sha256()
CTX_21_L11=    with open(p,'rb',buffering=0) as f:
CTX_21_L12=        for b in iter(lambda:f.read(1<<20),b''): h.update(b)
CTX_21_L13=    return h.hexdigest()
CTX_22_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_22_START_LINE=20
CTX_22_END_LINE=33
CTX_22_L20=    if not p.is_file() or p.is_symlink(): return None
CTX_22_L21=    try: d=json.loads(p.read_bytes())
CTX_22_L22=    except Exception: return {'summary_read':'FAILED'}
CTX_22_L23=    keys=('process_started','producer_rc','capture_success','archive_bytes','stderr_bytes_observed','stderr_bytes_retained','stderr_truncated','stderr_stream_sha256','raw_stderr_exported','child_umask')
CTX_22_L24=    return {k:d.get(k) for k in keys if k in d}
CTX_22_L25=
CTX_22_L26=def selftest()->int:
CTX_22_L27=    if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY')
CTX_22_L28=    sys.path.insert(0,str(BASE))
CTX_22_L29=    import adapter
CTX_22_L30=    adapter.verify_sources(); adapter.load_graph()
CTX_22_L31=    print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True)
CTX_22_L32=    return 0
CTX_22_L33=
CTX_23_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_23_START_LINE=42
CTX_23_END_LINE=66
CTX_23_L42=    argv=x['argv']; dest=pathlib.Path(x['dest']); cap=x['cap']; seconds=x['seconds']
CTX_23_L43=    if not (type(argv) is list and argv and all(type(v) is str and '\x00' not in v for v in argv)): fail('ARGV')
CTX_23_L44=    if argv[0]!='/usr/bin/vzdump': fail('VZDUMP_PATH')
CTX_23_L45=    if not (dest.is_absolute() and dest.name=='payload.bin' and '..' not in dest.parts): fail('DEST')
CTX_23_L46=    if not (type(cap) is int and 0<cap<=16*1024**3): fail('CAP')
CTX_23_L47=    if not (type(seconds) is int and 0<seconds<=86400): fail('SECONDS')
CTX_23_L48=    if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY')
CTX_23_L49=    sys.path.insert(0,str(BASE))
CTX_23_L50=    import adapter
CTX_23_L51=    adapter.verify_sources()
CTX_23_L52=    _g,p265,p270,_p282=adapter.load_graph()
CTX_23_L53=    os.chdir('/')
CTX_23_L54=    def guard():
CTX_23_L55=        if sha_file(VZDUMP)!=VZDUMP_SHA: raise p265.PVEError('VZDUMP_CHANGED')
CTX_23_L56=    try:
CTX_23_L57=        result=p270.capture_archive(argv,dest,cap,seconds,guard)
CTX_23_L58=        out={'status':'OK','result':result,'process':safe_process_summary(dest.parent)}
CTX_23_L59=        print(json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)
CTX_23_L60=        return 0
CTX_23_L61=    except Exception as e:
CTX_23_L62=        out={'status':'FAIL','exception_class':type(e).__module__+'.'+type(e).__name__,
CTX_23_L63=             'exception_message_sha256':hashlib.sha256(str(e).encode()).hexdigest(),
CTX_23_L64=             'process':safe_process_summary(dest.parent)}
CTX_23_L65=        print(json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)
CTX_23_L66=        return 2
CTX_24_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_24_START_LINE=69
CTX_24_END_LINE=74
CTX_24_L69=    try: raise SystemExit(main())
CTX_24_L70=    except Exception as e:
CTX_24_L71=        print(json.dumps({'status':'FAIL','exception_class':type(e).__module__+'.'+type(e).__name__,
CTX_24_L72=                          'exception_message_sha256':hashlib.sha256(str(e).encode()).hexdigest(),
CTX_24_L73=                          'process':None},separators=(',',':'),sort_keys=True),flush=True)
CTX_24_L74=        raise SystemExit(2)
CTX_25_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
CTX_25_START_LINE=6
CTX_25_END_LINE=12
CTX_25_L6=PVE265_SHA='cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be'
CTX_25_L7=
CTX_25_L8=def sha(p:pathlib.Path)->str:
CTX_25_L9=    return hashlib.sha256(p.read_bytes()).hexdigest()
CTX_25_L10=
CTX_25_L11=def fail(code:str):
CTX_25_L12=    raise RuntimeError(code)
CTX_26_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
CTX_26_START_LINE=17
CTX_26_END_LINE=23
CTX_26_L17=    if not p.is_file() or p.is_symlink() or sha(p)!=PVE265_SHA: fail('PVE265_IDENTITY')
CTX_26_L18=    sys.path.insert(0,str(C411))
CTX_26_L19=    import adapter
CTX_26_L20=    adapter.verify_sources()
CTX_26_L21=    guest266,pve265,_pve270,_pve282=adapter.load_graph()
CTX_26_L22=    data=sys.stdin.buffer.read(4_000_001)
CTX_26_L23=    if not data or len(data)>4_000_000: fail('INPUT_BOUND')
CTX_27_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
CTX_27_START_LINE=36
CTX_27_END_LINE=42
CTX_27_L36=    if job.get('configured_full_cycle_fits') is not True or job.get('compression_dependent') is not False: fail('JOB_CAPACITY_POLICY')
CTX_27_L37=    guest266.no_active_tasks(raw.get('tasks'),vmid)
CTX_27_L38=    argv=pve265.dump_argv(job,'/usr/bin/vzdump',scratch,now)
CTX_27_L39=    keep=('vmid','type','node','status','template','config_sha256','disks','configured_disk_bytes','configured_archive_bound_bytes','archive_cap_bytes','global_defaults_sha256','blockers','coverage_eligible')
CTX_27_L40=    out={'schema':1,'argv':argv,'job':{k:job.get(k) for k in keep}}
CTX_27_L41=    sys.stdout.write(json.dumps(out,separators=(',',':'),sort_keys=True)+'\n')
CTX_27_L42=    return 0
USA_STATE_FULL_SAFE_BEGIN=true
USA_STATE_FIELD=$.consecutive_failures=0
USA_STATE_FIELD=$.failure_backoff_seconds=0
USA_STATE_FIELD=$.generation=v2-md-relay-20260919T070058Z-0e409ea129e2
USA_STATE_FIELD=$.green_verified=False
USA_STATE_FIELD=$.last_attempt_epoch=1789801278
USA_STATE_FIELD=$.last_success_epoch=1789801278
USA_STATE_FIELD=$.logical_id=md-relay
USA_STATE_FIELD=$.manifest_sha256=6887c5423640738aeb2bc1d104d515df1d1a21e2cd2d3291481475aa81cb6838
USA_STATE_FIELD=$.payload_sha256=187401a5fbf6c29b4dfd77e5d272db77951aa45003d0d80e0be834235571f32f
USA_STATE_FIELD=$.replicas[0].crypt=pve03-mail-04-crypt
USA_STATE_FIELD=$.replicas[0].physical=pve03-mail-04
USA_STATE_FIELD=$.replicas[1].crypt=pve03-mail-01-crypt
USA_STATE_FIELD=$.replicas[1].physical=pve03-mail-01
USA_STATE_FIELD=$.result=SUCCESS
USA_STATE_FIELD=$.retry_after_epoch=0
USA_STATE_FIELD=$.schema=1
USA_STATE_FIELD=$.updated_at_utc=2026-09-19T07:01:18Z
USA_STATE_FULL_SAFE_END=true
MOLDOVA_STATE_FULL_SAFE_BEGIN=true
MOLDOVA_STATE_FIELD=$.consecutive_failures=6
MOLDOVA_STATE_FIELD=$.failure_backoff_seconds=21600
MOLDOVA_STATE_FIELD=$.generation=v2-us-netbird-20260920T000652Z-7ecdcfcafc12
MOLDOVA_STATE_FIELD=$.last_attempt_epoch=1789862827
MOLDOVA_STATE_FIELD=$.last_success_epoch=1789704670
MOLDOVA_STATE_FIELD=$.last_success_generation=v2-us-netbird-20260918T041032Z-d7648be4c16b
MOLDOVA_STATE_FIELD=$.last_success_green_verified=False
MOLDOVA_STATE_FIELD=$.last_success_manifest_sha256=f82c761cafe8aa43d90d0b4b6124933799b5087d34daf880791d850d0d15cee5
MOLDOVA_STATE_FIELD=$.last_success_payload_sha256=e41e3e012442ef41da1c667d7f5fbe4fd52786b0bb5ffca195660750c773efbf
MOLDOVA_STATE_FIELD=$.last_success_replicas[0].crypt=pve01-mail-05-crypt
MOLDOVA_STATE_FIELD=$.last_success_replicas[0].physical=pve01-mail-05
MOLDOVA_STATE_FIELD=$.last_success_replicas[1].crypt=pve03-mail-04-crypt
MOLDOVA_STATE_FIELD=$.last_success_replicas[1].physical=pve03-mail-04
MOLDOVA_STATE_FIELD=$.logical_id=us-netbird
MOLDOVA_STATE_FIELD=$.reason=PIPE_FAILED
MOLDOVA_STATE_FIELD=$.result=FAIL
MOLDOVA_STATE_FIELD=$.retry_after_epoch=1789884427
MOLDOVA_STATE_FIELD=$.schema=1
MOLDOVA_STATE_FIELD=$.sealed=False
MOLDOVA_STATE_FIELD=$.updated_at_utc=2026-09-20T00:07:07Z
MOLDOVA_STATE_FULL_SAFE_END=true
HAS_RCLONE_SOURCE=false
HAS_GENERATION_MANIFEST_PAYLOAD_SOURCE=true
HAS_REMOTE_REPLICA_SOURCE=true
DECISION=HOLD_BACKUP207_PRODUCER_CONTRACT_INCOMPLETE
NEXT_GATE=READ_ONLY_TARGETED_MODULE_FOLLOWUP
CLOUD_READS=0
CLOUD_WRITES=0
VPS_SSH_ATTEMPTS=0
MESSENGERS214_CLOSED=false
MAJOR_STAGES_REMAINING=8
NEWFI207_END=true

OUTPUT_END
CHAT_OUTPUT_END
