CHAT_OUTPUT_BEGIN
COMMAND_ID=SUPPORT-260916-INFRA-DR-BACKUPV2-LEGACY-PVE-RETENTION-SOURCE-CAPTURE-489R1
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=infra-dr-backupv2-legacy-pve-retention-source-capture
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
COMMAND_SHA256=45aee1dd4582048afc3a1893c770533d881e663514524acddbccf3a9685edc9b
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=87ab0715c0a1ecdb6af4b9bca6d13dea8fee4e52aa04edf113ad69329149d286
SANITIZED_OUTPUT_SHA256=7c8ac17b371d7c485cbd9c1a7c4097ffa6cf649306bdb7ee68326ee8d9484e9c
OUTPUT_BEGIN
COMMAND_ID=SUPPORT-260916-INFRA-DR-BACKUPV2-LEGACY-PVE-RETENTION-SOURCE-CAPTURE-489R1
SCOPE=READ_ONLY_SOURCE_AUTHORITY_CAPTURE_NO_BACKUP_NO_CLOUD_NO_MUTATION
IDENTITIES={"adapter":"18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3","engine":"dbfd237ddae5d2199bd8567ec6880d11276631dcc45acb49967de97329524037","gfs":null,"legacy":"b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7","policy":"e06b7e6285eda2885ef913aa954a70abc7c1d892199a8b7cea2ada98b8edba34","pve265":"cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be","pve270":"97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef","retention":"8adb6c10f5911f39c53775b89eac3cd1823f1ed34b4caccade5279c213e998a3","seal":"f508adc9b09bad9692c580e642018f5d3dbf223fc572ee62478466fd517234fa","targets":"a723befc7fd42d70af9088406598f18156dc3b4c76d8b34c4bb725dfaa48dd38"}
BASELINE_MATCH={"engine":true,"retention":true,"seal":true,"targets":true}
LEGACY_CAPTURE_PVE_GUEST={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py","file_sha256":"b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7","lines":["def capture_pve_guest(t,gen,work):","    vmid=int(t['vmid']); rows=[r for r in cluster_inventory() if int(r.get('vmid',-1))==vmid]","    if len(rows)!=1: raise BackupError('PVE_GUEST_NOT_UNIQUE')","    row=rows[0]; node=row.get('node'); typ=row.get('type')","    if typ!=t['guest_type']: raise BackupError('PVE_GUEST_TYPE_DRIFT')","    if typ=='lxc':","        _require_exact_source(P270,P270_SHA,'P270_IDENTITY');_require_exact_source(P282,P282_SHA,'P282_IDENTITY')","        _default_unprivileged_lxc(node,vmid)","        scratch=f'/var/tmp/homelab-vzdump-v2-{gen}'","        ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)","        q=ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)","        if q.stdout.decode().strip()!='710:0:100000': raise BackupError('PVE_MAPPED_SCRATCH_ACCESS_CONTRACT')","        try:","            mapped_scratch_probe(node,scratch)","            argv,job=proven_lxc_dump_argv(t,row,node,scratch)","            local=work/'payload.bin'","            _stream_argv_to_local(node,argv,local,timeout=7200)","            if local.stat().st_size>int(job['archive_cap_bytes']): raise BackupError('VZDUMP_ARCHIVE_CAP_EXCEEDED')","        except Exception:","            ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False);raise","        cleanup={'kind':'pve_source_dir','node':node,'path':scratch}","        return local,{'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':typ,'node':node,'status':row.get('status'),'producer_contract':'proven-270-282-stream'},cleanup","    # QEMU path remains unchanged: bounded dedicated dumpdir with later cloud readback/reconstruction.","    srcdir=f'/var/tmp/homelab-vzdump-v2-{gen}'","    ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)","    try:","        ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200)","        p=ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\\n'],timeout=30)","        files=[x for x in p.stdout.decode().splitlines() if x.strip()]","        if len(files)!=1: raise BackupError('VZDUMP_OUTPUT_NOT_UNIQUE')","        src=files[0];local=work/'payload.bin'","        if node=='pve01': local=pathlib.Path(src)","        else: run([SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)","        if not pathlib.Path(local).is_file() or pathlib.Path(local).stat().st_size<=0: raise BackupError('VZDUMP_PAYLOAD_MISSING')","    except Exception:","        ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False);raise","    return pathlib.Path(local),{'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':typ,'node':node,'status':row.get('status')},{'kind':'pve_source_dir','node':node,'path':srcdir}"],"name":"capture_pve_guest","source_sha256":"c4c22625a9c6a954d0ed93dfc63f0501af0644ca9f5e6781d3b2e50a7e2563ea"}
LEGACY_CAPTURE_TARGET={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py","file_sha256":"b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7","lines":["def capture_target(t,gen,work):","    typ=t['type']","    if typ=='pve_guest': return capture_pve_guest(t,gen,work)","    if typ=='pve_node_bundle': return capture_node_bundle(t,gen,work)","    if typ=='vps_md': return capture_vps_md(t,gen,work)","    if typ=='vps_spb': return capture_vps_spb(t,gen,work)","    if typ=='vps_us': return capture_vps_us(t,gen,work)","    if typ=='router': return capture_router(t,gen,work)","    if typ=='xenforo': return capture_xenforo(t,gen,work)","    raise BackupError('CAPTURE_TYPE_UNKNOWN')"],"name":"capture_target","source_sha256":"f52cec3a28467da247da0efaffb9523a775b1bb0cab2ce7fef1b1a5923a765bb"}
PVE265_DUMP_ARGV={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve265.py","file_sha256":"cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be","lines":["def dump_argv(job,executable,tmpdir,now):","    validate_job(job,now)","    need(path_ok(executable) and path_ok(tmpdir),'EXECUTION_PATH')","    return [str(executable),str(job['vmid']),'--node',job['node'],'--mode','snapshot','--stdout','1',","            '--compress','zstd','--zstd','1','--remove','0','--prune-backups','keep-all=1',","            '--stdexcludes','0','--lockwait','0','--bwlimit','32768','--ionice','7','--tmpdir',str(tmpdir)]"],"name":"dump_argv","source_sha256":"5244bbe02f2fc966e08b6c71ffc8430cedfb66635864e8994f8bcc3a1483cd93"}
PVE270_HOST_MAPPING={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py","file_sha256":"97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef","lines":["def host_mapping():","    # Scope of the exception is this observed, protected system ELF pair only.","    # PVE modules and private data retain the original single-link reader.","    pins={p:t.sha(t.read_secure(Path(p),2*1024**2)[0]) for p in","          ('/usr/share/perl5/PVE/LXC.pm','/usr/share/perl5/PVE/VZDump/LXC.pm')}","    code=('my($m,$u,$g)=PVE::LXC::parse_id_maps({unprivileged=>1,lxc=>[]});'","          'print JSON::PP->new->canonical->encode({root_uid=>0+$u,root_gid=>0+$g,'","          'id_map=>[map {[$_->[0],0+$_->[1],0+$_->[2],0+$_->[3]]} @$m]});')","    with PerlPin('/usr/bin/perl','/usr/bin/perl5.40.1') as pin:","        rc,b=pin.run(['-MPVE::LXC','-MJSON::PP','-e',code])","        need(rc==0,'PVE_IDMAP_READ_FAILED')","        for p,h in pins.items():need(t.sha(t.read_secure(Path(p),2*1024**2)[0])==h,'PVE_MAPPING_SOURCE_CHANGED')","        pin.check()","    try:d=json.loads(b)","    except (ValueError,UnicodeError):raise old.PVEError('PVE_IDMAP_JSON') from None","    return validate_mapping(d)"],"name":"host_mapping","source_sha256":"3594394c852f13ba57e3c1ae623a071352d95d2dac35bfba6bb6af73d5783f0a"}
PVE270_VALIDATE_MAPPING={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py","file_sha256":"97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef","lines":["def validate_mapping(d):","    need(type(d) is dict and set(d)=={'root_uid','root_gid','id_map'},'IDMAP_SCHEMA')","    need(type(d['root_uid']) is int and type(d['root_gid']) is int,'IDMAP_VALUE')","    need(d['root_uid']==d['root_gid']==100000,'ONLY_DEFAULT_UNPRIVILEGED_IDMAP')","    expect=[['u',0,100000,65536],['g',0,100000,65536]]","    need(type(d['id_map']) is list and len(d['id_map'])==2,'IDMAP_ROWS')","    for row,exp in zip(d['id_map'],expect):","        need(type(row) is list and len(row)==4 and type(row[0]) is str and all(type(n) is int for n in row[1:]) and row==exp,'IDMAP_NONDEFAULT')","    return d['root_uid'],d['root_gid']"],"name":"validate_mapping","source_sha256":"461ec78d3d02e1d590ed62baee4a278976d9737a88f08e4a4030d702a0be1ef3"}
PVE270_CAPTURE_ARCHIVE={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py","file_sha256":"97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef","lines":["def capture_archive(argv,destination,cap,seconds,check):","    \"\"\"Same streaming bounds as 265; stderr kept privately, child-only umask=022.\"\"\"","    need(type(argv) is list and argv and all(type(x) is str for x in argv),'ARGV')","    need(type(cap) is int and 0<cap<=stream.MAX_BYTES,'ARCHIVE_CAP')","    need(type(seconds) in (int,float) and 0<seconds<=86400,'DEADLINE')","    need(callable(check),'GUARD_REQUIRED');check()","    dest=Path(destination);parent=stream.private_dir(dest.parent)","    fd=efd=None;p=sel=None;good=False;owned=False;total=err_total=err_kept=0;digest=hashlib.sha256();eh=hashlib.sha256()","    deadline=time.monotonic()+seconds","    try:","        fd=os.open(dest.name,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600,dir_fd=parent);owned=True;os.fchmod(fd,0o600)","        initial=os.fstat(fd)","        efd=os.open('producer.stderr.log',os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600,dir_fd=parent);os.fchmod(efd,0o600)","        p=subprocess.Popen(argv,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,","                           env=dict(old.ENV),start_new_session=True,close_fds=True,umask=0o022)","        sel=selectors.DefaultSelector()","        for pipe in (p.stdout,p.stderr):os.set_blocking(pipe.fileno(),False);sel.register(pipe,selectors.EVENT_READ)","        next_check=0","        while sel.get_map():","            now=time.monotonic();need(now<deadline,'PRODUCER_TIMEOUT')","            if now>=next_check:check();next_check=now+0.5","            for key,_ in sel.select(min(0.1,max(0,deadline-now))):","                b=os.read(key.fileobj.fileno(),65536)","                if not b:sel.unregister(key.fileobj);continue","                if key.fileobj is p.stdout:","                    need(total+len(b)<=cap,'ARCHIVE_CAP_REACHED_PARTIAL_RETAINED')","                    stream.write_all(fd,b);digest.update(b);total+=len(b)","                else:","                    err_total+=len(b);eh.update(b);chunk=b[:max(0,MAX_STDERR-err_kept)]","                    if chunk:stream.write_all(efd,chunk);err_kept+=len(chunk)","        need(deadline>time.monotonic(),'PRODUCER_TIMEOUT')","        try:rc=p.wait(timeout=deadline-time.monotonic())","        except subprocess.TimeoutExpired:raise old.PVEError('PRODUCER_TIMEOUT') from None","        need(rc==0,'PRODUCER_RC_FAILED_PARTIAL_RETAINED');need(total>0,'EMPTY_ARCHIVE');check()","        st=os.fstat(fd);named=os.stat(dest.name,dir_fd=parent,follow_symlinks=False)","        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')","        os.fchmod(fd,0o400);os.fsync(fd);os.fsync(parent);good=True","        return {'size':total,'sha256':digest.hexdigest(),'producer_rc':rc,'identity':list(t.ident(os.fstat(fd)))}","    finally:","        if p is not None:","            if p.poll() is None:old.terminate(p)","            p.wait();p.stdout.close();p.stderr.close()","        if sel is not None:sel.close()","        try:","            if fd is not None:os.fsync(fd)","            if efd is not None:os.fsync(efd)","            if owned:","                summary={'process_started':p is not None,'producer_rc':p.returncode if p is not None else None,","                         'capture_success':good,'archive_bytes':total,'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,'child_umask':'0022'}","                t.create(dest.parent/'PRODUCER_PROCESS.json',core.canonical_bytes(summary))","        finally:","            if fd is not None:os.close(fd)","            if efd is not None:os.close(efd)","            os.close(parent)"],"name":"capture_archive","source_sha256":"795afc9f2c9f3ff0691680362771f703506295588e6f6b73dfb7e68addded6e7"}
PVE270_PRODUCE={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py","file_sha256":"97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef","lines":["def produce(job,work,tools,guard,*,mapping,seconds=14400,emit=lambda k,v:None):","    need(callable(guard),'GUARD_REQUIRED');guard();old.validate_job(job,int(time.time()));old.validate_tools(tools)","    need(job.get('vmid')==110 and job.get('type')=='lxc' and job.get('config_sha256')==EXPECTED_CFG,'ONLY_ACCEPTED_CT110')","    uid,gid=validate_mapping(mapping)","    work=Path(work);parent=stream.private_dir(work)","    try:need(os.listdir(parent)==[],'PRODUCER_WORKSPACE_NOT_EMPTY')","    finally:os.close(parent)","    # Keep the old orchestration contract: this private placeholder stays empty.","    t.make_dir(work/'tmp',exclusive=True)","    scratch=None;complete=False","    try:","        scratch=MappedScratch(gid)","        emit('PVE_TEMP_DIRECTORY',scratch.path);emit('PVE_TEMP_MODE','0710');emit('PVE_TEMP_GID',gid)","        t.create(work/'PVE_TEMP.json',core.canonical_bytes({'path':str(scratch.path),'mode':'0710','uid':0,'gid':gid,'identity':list(scratch.identity)}))","        scratch.probe(uid,work);emit('MAPPED_UID_ACCESS_AND_ISOLATION_PROBE','PASS')","        def free_guard():","            scratch.check()","            for path,reserve,reason in ((work,old.LOCAL_RESERVE,'STAGING_RESERVE_REACHED_PARTIAL_RETAINED'),(scratch.path,256*1024**2,'PVE_TEMP_RESERVE_LOW')):","                v=os.statvfs(path);need(v.f_frsize*v.f_bavail>=reserve,reason)","        free_guard();guard();dest=work/'guest-110.tar.zst'","        result=capture_archive(old.dump_argv(job,tools['vzdump']['path'],scratch.path,int(time.time())),dest,job['archive_cap_bytes'],seconds,free_guard)","        guard();old.validate_tools(tools)","        rc,_=t.bounded_process([tools['zstd']['path'],'--test','--quiet','--',str(dest)],dict(old.ENV),65536,min(seconds,3600))","        need(rc==0,'ARCHIVE_COMPRESSION_TEST_FAILED_RETAINED')","        n,h,identity=stream.hash_file(dest,job['archive_cap_bytes'])","        need(n==result['size'] and h==result['sha256'] and list(identity)==result['identity'],'PRODUCER_READBACK_MISMATCH')","        guard();old.validate_tools(tools);scratch.close(empty_only=True);complete=True;emit('PVE_TEMP_EMPTY_REMOVED','YES')","        return {**result,'path':str(dest),'vmid':110,'type':'lxc','node':job['node'],'config_sha256':job['config_sha256'],","                'compression_test_ok':True,'restored':False,'state':'PRODUCED_COMPRESSION_CHECKED_NOT_CLOUD_SEALED','local_payload_retained':True}","    finally:","        m=work/'PRODUCER_PROCESS.json'","        if m.exists():","            info=json.loads(t.read_secure(m,65536,private=True)[0])","            emit('VZDUMP_PROCESS_STARTED','YES' if info.get('process_started') else 'NO')","            emit('VZDUMP_PROCESS_RC',info.get('producer_rc'));emit('PRIVATE_STDERR_BYTES',info.get('stderr_bytes_retained'))","        if scratch is not None and not complete:","            emit('PVE_TEMP_RETAINED','YES');scratch.close(empty_only=False)"],"name":"produce","source_sha256":"5278bae09546a659401348335cf2d0834f49d372727a4751245ead6a3aa27a79"}
PVE270_LIVE_GATE={"file":"/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py","file_sha256":"97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef","lines":["def live_gate(job,pvesh_path,pvesh_sha):","    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')","    vals=[]","    for part in ('config','status/current','snapshot'):","        need(t.sha(t.read_secure(Path(pvesh_path),16*1024**2)[0])==pvesh_sha,'PVESH_CHANGED')","        rc,b=t.bounded_process([str(pvesh_path),'get','/nodes/pve01/lxc/110/'+part,'--output-format','json'],dict(old.ENV),262144,30)","        need(rc==0,'CT_GATE_READ_FAILED')","        try:vals.append(json.loads(b))","        except (ValueError,UnicodeError):raise old.PVEError('CT_GATE_JSON') from None","    validate_ct(*vals,job['config_sha256'])","    return True"],"name":"live_gate","source_sha256":"5ec8790c2633c8e576ddecfc04d7878ce7a5ee8ee2de5097dd664245f6621ac0"}
ADAPTER_CONTEXT={"bytes":2989,"file_sha256":"18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3","lines":["11:'pve265.py':'cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be',","12:'guest266.py':'86433bc424d5fa5017c20f7a237c82874b02357a3283660d8a6b0039ef2bc868',","13:'pve270.py':'97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef',","14:'pve282.py':'73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012'}","15:def sha(p):","23:  if not p.is_file() or p.is_symlink() or sha(p)!=want:raise RuntimeError('SOURCE_IDENTITY_'+name)","24:def load_graph():","25: import guest266,pve265,pve270,pve282","26: if hasattr(guest266,'dump_argv'):raise RuntimeError('GUEST266_UNEXPECTED_DUMP_ARGV')","27: if not hasattr(pve265,'dump_argv'):raise RuntimeError('PVE265_DUMP_ARGV_MISSING')","28: if getattr(pve270,'old',None) is not pve265:raise RuntimeError('PVE270_OLD_NOT_PVE265')","29: if getattr(pve282,'old',None) is not pve265:raise RuntimeError('PVE282_OLD_NOT_PVE265')","30: if getattr(pve282,'proven',None) is not pve270:raise RuntimeError('PVE282_PROVEN_NOT_PVE270')","31: for n in ('MappedScratch','capture_archive','validate_mapping'):","32:  if not hasattr(pve270,n):raise RuntimeError('PVE270_'+n.upper()+'_MISSING')","33:  if getattr(pve282,n,None) is not getattr(pve270,n):raise RuntimeError('PVE282_ALIAS_'+n.upper()+'_MISMATCH')","34: return guest266,pve265,pve270,pve282","35:def describe():","36: _,p265,p270,p282=load_graph()","37: 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}","38: 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'}}","39:def main():","40: verify_sources(); mode=sys.argv[1] if len(sys.argv)>1 else 'selftest'; d=describe()"],"match_count":10,"state":"OK"}
RETENTION_CLI_FLAGS=["--arg","--argjson","--config","--dirs-only","--immutable","--max-depth","--size-only"]
GFS_CLI_FLAGS=[]
RETENTION_SOURCE_CONTEXT={"bytes":32975,"file_sha256":"8adb6c10f5911f39c53775b89eac3cd1823f1ed34b4caccade5279c213e998a3","lines":["21:REGISTRY_HELPER=\"${HOMELAB_BACKUP_TARGET_REGISTRY_HELPER:-/usr/local/libexec/homelab-backup-target-registry}\"","22:REGISTRY_HELPER_SHA_EXPECTED=c681c44be7557d192d7b453b67e31164237874596168f1d4c78e1e926e2e9cb4","23:GFS_HELPER=\"${HOMELAB_BACKUP_GFS_POLICY_HELPER:-/usr/local/libexec/homelab-backup-gfs-policy}\"","24:GFS_HELPER_SHA_EXPECTED=6b7ec1ab3ee1c540a9113b5620c3b4b5a50de6536f3a069d31b2e1243f23bafa","25:GFS_POLICY=\"${HOMELAB_BACKUP_GFS_POLICY:-/etc/homelab-backup/gfs-retention.json}\"","26:CONTROL_EVIDENCE_ROOT=/var/lib/homelab-backup/control-restore-validation/control-bootstrap","27:[[ -x \"$REGISTRY_HELPER\" && ! -L \"$REGISTRY_HELPER\" ]] || { printf 'GC_STATUS=ERROR|ROOT_CAUSE=TARGET_REGISTRY_HELPER_MISSING\\n' >&2; exit 69; }","28:[[ \"$(sha256sum \"$REGISTRY_HELPER\"|awk '{print $1}')\" == \"$REGISTRY_HELPER_SHA_EXPECTED\" ]] || { printf 'GC_STATUS=ERROR|ROOT_CAUSE=TARGET_REGISTRY_HELPER_SHA_DRIFT\\n' >&2; exit 65; }","29:\"$REGISTRY_HELPER\" validate >/dev/null || { printf 'GC_STATUS=ERROR|ROOT_CAUSE=TARGET_REGISTRY_INVALID\\n' >&2; exit 66; }","30:[[ -x \"$GFS_HELPER\" && ! -L \"$GFS_HELPER\" ]] || { printf 'GC_STATUS=ERROR|ROOT_CAUSE=GFS_POLICY_HELPER_MISSING\\n' >&2; exit 69; }","31:[[ \"$(sha256sum \"$GFS_HELPER\"|awk '{print $1}')\" == \"$GFS_HELPER_SHA_EXPECTED\" ]] || { printf 'GC_STATUS=ERROR|ROOT_CAUSE=GFS_POLICY_HELPER_SHA_DRIFT\\n' >&2; exit 65; }","32:HOMELAB_BACKUP_GFS_POLICY=\"$GFS_POLICY\" \"$GFS_HELPER\" validate >/dev/null || { printf 'GC_STATUS=ERROR|ROOT_CAUSE=GFS_POLICY_INVALID\\n' >&2; exit 66; }","33:GFS_WEEKLY=\"$(HOMELAB_BACKUP_GFS_POLICY=\"$GFS_POLICY\" \"$GFS_HELPER\" weekly-buckets)\"","34:GFS_MONTHLY=\"$(HOMELAB_BACKUP_GFS_POLICY=\"$GFS_POLICY\" \"$GFS_HELPER\" monthly-buckets)\"","35:GFS_CRITICAL_COUNT=\"$(HOMELAB_BACKUP_GFS_POLICY=\"$GFS_POLICY\" \"$GFS_HELPER\" critical-logicals | wc -l)\"","36:VM_KEEP=\"$(\"$REGISTRY_HELPER\" policy-keep VM)\"","37:APP_KEEP=\"$(\"$REGISTRY_HELPER\" policy-keep APP)\"","38:CONTROL_KEEP=\"$(\"$REGISTRY_HELPER\" policy-keep CONTROL)\"","39:MIN_DELETE_AGE_SECONDS=86400","40:SSH_BASE=(-n -o BatchMode=yes -o ConnectTimeout=12 -o StrictHostKeyChecking=yes -o UserKnownHostsFile=[SENSITIVE_PATH] local msg=\"$1\" rc=\"${2:-65}\"; trap - ERR; printf 'GC_STATUS=ERROR|ROOT_CAUSE=%s\\n' \"$msg\" >&2; exit \"$rc\"; }","43:cleanup(){ if [[ -n \"${TMPROOT:-}\" && -d \"$TMPROOT\" ]]; then rm -rf -- \"$TMPROOT\"; fi; }","44:stable_delete_set(){ sed -E 's/\\|age_seconds=[0-9]+$//'; }","45:trap cleanup EXIT","46:","72:strict_state(){","73:  local json=\"$1\" logical=\"$2\" generation=\"$3\"","74:  jq -e --arg l \"$logical\" --arg g \"$generation\" '.schema==\"homelab-cloud-quorum-payload-v1\" and .logical_id==$l and .generation==$g and .status==\"SEALED\" and .cloud_quorum==2 and .cloud_a_verified==true and .cloud_b_verified==true and .part_hashes_verified==true and .seal_written==true and .cloud_a_seal_verified==true and .cloud_b_seal_verified==true and .local_delete_allowed==true and .local_payload_present==false and .local_cleanup==\"OK\"' <<<\"$json\" >/dev/null","75:}","76:latest_restore_proven(){","121:    case \"$status\" in","122:      DONE) ;;","123:      PLANNED|B_DELETED) count=$((count+1)) ;;","124:      *) die \"TX_STATUS_INVALID_$f\" ;;","125:    esac","128:}","129:","130:pinned_delete_contract_enabled(){","131:  [[ -n \"${HOMELAB_RETENTION_PINNED_DELETE_FILE:-}\" || -n \"${HOMELAB_RETENTION_PINNED_DELETE_SHA256:-}\" ]]","132:}","133:pinned_delete_assert_file(){","134:  local f=\"${HOMELAB_RETENTION_PINNED_DELETE_FILE:-}\" expected=\"${HOMELAB_RETENTION_PINNED_DELETE_SHA256:-}\" actual line logical generation owner state_file state_sha count=0","135:  [[ -n \"$f\" && -n \"$expected\" ]] || die PINNED_DELETE_CONTRACT_INCOMPLETE 64","136:  [[ \"$expected\" =~ ^[0-9a-f]{64}$ ]] || die PINNED_DELETE_SHA_INVALID 64","137:  [[ -f \"$f\" && ! -L \"$f\" ]] || die PINNED_DELETE_FILE_UNSAFE 64","138:  actual=\"$(sha256sum \"$f\" | awk '{print $1}')\"","139:  [[ \"$actual\" == \"$expected\" ]] || die PINNED_DELETE_FILE_SHA_MISMATCH 66","140:  while IFS= read -r line; do","141:    [[ -n \"$line\" ]] || die PINNED_DELETE_EMPTY_LINE 66","142:    logical=\"$(awk -F'|' '{for(i=1;i<=NF;i++)if($i~/^logical=/){sub(/^logical=/,\"\",$i);print $i}}' <<<\"$line\")\"","143:    generation=\"$(awk -F'|' '{for(i=1;i<=NF;i++)if($i~/^generation=/){sub(/^generation=/,\"\",$i);print $i}}' <<<\"$line\")\"","145:    state_file=\"$(awk -F'|' '{for(i=1;i<=NF;i++)if($i~/^state_file=/){sub(/^state_file=/,\"\",$i);print $i}}' <<<\"$line\")\"","146:    state_sha=\"$(awk -F'|' '{for(i=1;i<=NF;i++)if($i~/^state_sha256=/){sub(/^state_sha256=/,\"\",$i);print $i}}' <<<\"$line\")\"","147:    [[ \"$line\" == \"DELETE|logical=$logical|generation=$generation|owner=$owner|state_file=$state_file|state_sha256=$state_sha\" ]] || die PINNED_DELETE_LINE_FORMAT_INVALID 66","148:    [[ \"$(node_for_logical \"$logical\")\" == \"$owner\" ]] || die \"PINNED_DELETE_OWNER_INVALID_${logical}\" 66","149:    safe_generation \"$logical\" \"$generation\" || die \"PINNED_DELETE_GENERATION_INVALID_${logical}\" 66","150:    [[ \"$state_file\" == \"$STATE_ROOT/$logical/$generation.json\" ]] || die \"PINNED_DELETE_STATE_PATH_INVALID_${logical}\" 66","151:    [[ \"$state_sha\" =~ ^[0-9a-f]{64}$ ]] || die \"PINNED_DELETE_STATE_SHA_INVALID_${logical}\" 66"],"match_count":28,"state":"OK"}
GFS_SOURCE_CONTEXT={"state":"ABSENT"}
POLICY_EVIDENCE={"bytes":1436,"hits":[],"sha256":"e06b7e6285eda2885ef913aa954a70abc7c1d892199a8b7cea2ada98b8edba34","top_keys":["account_failure_domains","accounts","canary","change_id","cloud_retention","failure_policy","local_retention","policy_id","provider","provider_failure_domains","quorum","restore_policy","schema_version"],"top_type":"dict"}
OPS_REPO_EVIDENCE={"branch":{"lines":["main"],"rc":0,"stderr_sha256":null,"stdout_sha256":"6403203dd5a0867eb14d104ee8a73730bd72dd9ad92e78d996a6dba0a5dcfc01"},"current_lifecycle":{"lines":["HEAD:kb/AI_CONTEXT.md:24:110 dns1, 111 dns2, 112 unbound1, 113 unbound2, VM130 edge-vm, VM150 Snikket, VM160 forum-prod, VM170 core-apps/Gitea, VM171 monitoring, VM190 Gitea Actions runner. VM180 and CT200 are retirement candidates only; no blind delete. VM9130 edge-cold-standby stays until timed VM130 DR restore proof.","HEAD:kb/AI_CONTEXT.md:28:Inbound pvepro.ru mail is retired with Null MX. Outbound PHP/XenForo transport is Yandex Cloud Postbox via VM160 msmtp. Credential ref is `postbox_smtp_secret`; its storage metadata is private-facade data and the value never belongs in Git/chat. Five XenForo DBs require individual P0 application acceptance: `xf_codevipe`, `xf_dsmods`, `xf_gamevipe`, `xf_hkmods`, `xf_zakrutim`.","HEAD:kb/AI_CONTEXT_PUBLIC.md:11:The homelab is a three-node Proxmox cluster with dedicated DNS/Unbound guests, EDGE VM, Snikket, forum production, core-apps/Gitea, monitoring and Gitea Actions runner. Retirement candidates and DR standby are not deletion-authorized merely because they are not primary production.","HEAD:kb/AI_CONTEXT_PUBLIC.md:15:CR0083 is merged/closed. Current P0 sequence starts with Git topology preservation, then canonical post-migration state, recovery/backup refresh, VM160/forum acceptance, permanent new-USA SSH hardening, old-USA observation/retirement, and final seal.","HEAD:kb/AI_CONTEXT_PUBLIC.md:19:- Inbound mail is intentionally retired with Null MX; outbound forum mail uses Yandex Cloud Postbox.","HEAD:kb/changes/CR-2026-0086-HANDOFF.md:142:CR0085 should be reviewed/retired separately after CR0086 is established.","HEAD:kb/changes/CR-2026-0087-HANDOFF.md:11:- retired VM170 application/control-plane state is removed.","HEAD:kb/changes/CR-2026-0087-HANDOFF.md:12:- VM171 retired monitoring closure is complete.","HEAD:kb/changes/CR-2026-0087-IMPLEMENTATION.md:10:- CMD-1137..1140: VM171 retired Kuma/Prometheus monitoring closure completed and read back.","HEAD:kb/changes/CR-2026-0087-IMPLEMENTATION.md:11:- CMD-1141: VM170 retired application payload removed; VM170 itself remains KEEP/CRITICAL as Gitea/core-app host.","HEAD:kb/changes/CR-2026-0087-IMPLEMENTATION.md:14:- CMD-1144: retired current registry/backup metadata, stale latest-state/runbooks and orphan Beszel/SOPS current state removed; service registry, dependency map, runbooks and local desired-state regenerated.","HEAD:kb/changes/CR-2026-0087-IMPLEMENTATION.md:24:- `/root/homelab-cleanup-backups/CR-2026-0087/cmd-1139-retired-health`","HEAD:kb/changes/CR-2026-0087-IMPLEMENTATION.md:26:- `/var/backups/homelab-cleanup/CR-2026-0087/cmd-1141-vm170-retired-payload`","HEAD:kb/changes/CR-2026-0087-IMPLEMENTATION.md:29:- `/var/backups/homelab-cleanup/CR-2026-0087/cmd-1144-retired-current-state`","HEAD:kb/changes/CR-2026-0087-IMPLEMENTATION.md:37:`tools/collect_context.py` no longer tracks the retired `homelab-crypto-portfolio-chart-health.timer`; generated context is refreshed from cleaned current state.","HEAD:kb/current/01_CURRENT_STATE.md:12:- old Mailcow/old NetBird server architecture is retired from production; rollback window remains.","HEAD:kb/current/04_P0_NEXT.md:5:3. Canonical post-migration CR including NetBird new USA, Postbox/Null MX, Moldova V3/Gotify, old-USA retirement window and dependencies.","HEAD:kb/private/archive/2026-08-19/MANIFEST.tsv:18:docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md\t1740","HEAD:kb/private/archive/2026-08-19/MANIFEST.tsv:24:docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md\t2504","HEAD:kb/private/archive/2026-08-19/MANIFEST.tsv:29:docs/26_ALEXHOST_RETIREMENT_STATE_2026-08-19.md\t963","HEAD:kb/private/archive/2026-08-19/README_FIRST.md:21:6. `docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md`","HEAD:kb/private/archive/2026-08-19/SHA256SUMS:18:ad3ea70345063e8a13608a83acb4d6a1118533eb6acab22929e0bf1ac20c06af  docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md","HEAD:kb/private/archive/2026-08-19/SHA256SUMS:24:c8c11e3c6b8b5d9e2509f975657194944edbc89e483da04f2413224b79084309  docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md","HEAD:kb/private/archive/2026-08-19/SHA256SUMS:29:426a22a970150ff86adbd441a616481fbcedfc1cdb48c5a4976862d747cbcd43  docs/26_ALEXHOST_RETIREMENT_STATE_2026-08-19.md","HEAD:kb/private/archive/2026-08-19/docs/01_CURRENT_AUTHORITATIVE_STATE.md:122:VM180 and CT200 are retirement candidates only, not blind-delete authorization.","HEAD:kb/private/archive/2026-08-19/docs/01_CURRENT_AUTHORITATIVE_STATE.md:153:Inbound email deliberately retired.","HEAD:kb/private/archive/2026-08-19/docs/01_CURRENT_AUTHORITATIVE_STATE.md:256:`/root/retired-mailcow-backups/mailcow-final-offline-20260818T185112Z`","HEAD:kb/private/archive/2026-08-19/docs/01_CURRENT_AUTHORITATIVE_STATE.md:264:Old observer retirement backup:","HEAD:kb/private/archive/2026-08-19/docs/01_CURRENT_AUTHORITATIVE_STATE.md:265:`/root/retired-homelab-dr-observer-20260818T221046Z`","HEAD:kb/private/archive/2026-08-19/docs/02_CLUSTER_TOPOLOGY_AND_INVENTORY.md:74:Known consumers prove these are not currently safe to retire blindly.","HEAD:kb/private/archive/2026-08-19/docs/05_BACKUP_DR_AND_CLOUDS.md:49:Lifecycle = not configured","HEAD:kb/private/archive/2026-08-19/docs/11_OPEN_ISSUES_AND_FUTURE_WORK.md:20:- current mirror policy: verify or formally retire mirror","HEAD:kb/private/archive/2026-08-19/docs/11_OPEN_ISSUES_AND_FUTURE_WORK.md:33:- second independent copy of retired Mailcow archive","HEAD:kb/private/archive/2026-08-19/docs/11_OPEN_ISSUES_AND_FUTURE_WORK.md:92:Retire only with fresh consumer proof:","HEAD:kb/private/archive/2026-08-19/docs/11_OPEN_ISSUES_AND_FUTURE_WORK.md:101:### Retirement projects","HEAD:kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md:1:# CRITICAL KEEP / RETIRE DECISIONS","HEAD:kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md:3:This is a convenience matrix distilled from the historical handbook plus current state. A RETIRE label is not authorization to delete without fresh proof.","HEAD:kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md:16:| VM180 cluster-admin | historical future RETIRE candidate | only after dependency/backup/monitoring cleanup |","HEAD:kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md:18:| CT200 skladchik-mod | historical future RETIRE candidate | preserve required data/monitoring first |","HEAD:kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md:24:| pve01 18788 | KEEP NOW | reader-v3, usage proof before retirement |","HEAD:kb/private/archive/2026-08-19/docs/17_CLOUDRU_CURRENT.md:18:lifecycle: absent","HEAD:kb/private/archive/2026-08-19/docs/18_P0_CLOSEOUT_MASTER_PLAN_2026-08-19.md:35:- old NetBird server retirement","HEAD:kb/private/archive/2026-08-19/docs/18_P0_CLOSEOUT_MASTER_PLAN_2026-08-19.md:36:- Mailcow retirement","HEAD:kb/private/archive/2026-08-19/docs/18_P0_CLOSEOUT_MASTER_PLAN_2026-08-19.md:42:- AlexHost retirement/rollback window","HEAD:kb/private/archive/2026-08-19/docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md:1:# MAILCOW RETIREMENT / POSTBOX / FORUMS \u2014 CURRENT RECORD","HEAD:kb/private/archive/2026-08-19/docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md:8:18 containers before retirement.","HEAD:kb/private/archive/2026-08-19/docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md:30:## Retirement","HEAD:kb/private/archive/2026-08-19/docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md:53:`/root/retired-mailcow-backups/mailcow-final-offline-20260818T185112Z`","HEAD:kb/private/archive/2026-08-19/docs/22_MOLDOVA_HEALTHCHECK_GOTIFY_2026-08-18.md:14:Old checker referenced retired Mailcow/old NetBird IP and caused false failures.","HEAD:kb/private/archive/2026-08-19/docs/22_MOLDOVA_HEALTHCHECK_GOTIFY_2026-08-18.md:48:Old USA observer had been converted to Gotify-only before retirement.","HEAD:kb/private/archive/2026-08-19/docs/22_MOLDOVA_HEALTHCHECK_GOTIFY_2026-08-18.md:103:`/root/retired-homelab-dr-observer-20260818T221046Z`","HEAD:kb/private/archive/2026-08-19/docs/24_GLOBAL_BACKLOG_MASTER_2026-08-19.md:20:- current mirror policy: verify or formally retire mirror","HEAD:kb/private/archive/2026-08-19/docs/24_GLOBAL_BACKLOG_MASTER_2026-08-19.md:33:- second independent copy of retired Mailcow archive","HEAD:kb/private/archive/2026-08-19/docs/24_GLOBAL_BACKLOG_MASTER_2026-08-19.md:92:Retire only with fresh consumer proof:","HEAD:kb/private/archive/2026-08-19/docs/24_GLOBAL_BACKLOG_MASTER_2026-08-19.md:101:### Retirement projects","HEAD:kb/private/archive/2026-08-19/docs/26_ALEXHOST_RETIREMENT_STATE_2026-08-19.md:1:# ALEXHOST RETIREMENT / BILLING STATE \u2014 2026-08-19","HEAD:kb/private/archive/2026-08-19/docs/27_SECURITY_ACCESS_CURRENT_DELTA_2026-08-19.md:12:Lifecycle:","HEAD:kb/private/archive/2026-08-19/docs/27_SECURITY_ACCESS_CURRENT_DELTA_2026-08-19.md:14:- after accepted old-USA shutdown/retirement:","HEAD:kb/private/archive/2026-08-19/machine/current_state.json:108:    \"lifecycle\": \"NOT_CONFIGURED\",","HEAD:kb/private/archive/2026-08-19/machine/current_state.yaml:89:  new_usa_path: \"/root/retired-mailcow-backups/mailcow-final-offline-20260818T185112Z\"","HEAD:kb/private/source/source_manifest.json:83:    \"path\": \"docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md\",","HEAD:kb/private/source/source_manifest.json:98:    \"path\": \"docs/26_ALEXHOST_RETIREMENT_STATE_2026-08-19.md\",","HEAD:kb/private/source/source_manifest.json:113:    \"path\": \"docs/21_MAILCOW_RETIREMENT_POSTBOX_FORUMS_2026-08-18.md\",","HEAD:kb/runbooks/02_PROXMOX.md:12:Before deletion/retirement, prove consumers and backup/restore path. VM9130 remains protected until timed VM130 DR restore proof.","HEAD:kb/runbooks/05_FORUMS_MAIL.md:9:Null MX means inbound mail is intentionally retired; do not \u201crepair\u201d old Mailcow MX/DNS as if outage without checking current policy.","HEAD:kb/secrets/registry.json:92:    \"lifecycle\": \"Remove after old-USA retirement accepted and corresponding authorized_keys line no longer needed.\""],"rc":0,"stderr_sha256":null,"stdout_sha256":"fefced8de60a5efa9488a0bcc961ca0d75d90bc2f411e26a7fe40d4e0b106c78"},"current_vm200":{"lines":["HEAD:kb/inventory/guests.json:136:    \"name\": \"skladchik-mod\",","HEAD:kb/inventory/guests.json:143:    \"role\": \"skladchik-mod: moderator v2 + PostgreSQL\",","HEAD:kb/private/archive/2026-08-19/docs/02_CLUSTER_TOPOLOGY_AND_INVENTORY.md:42:| 200 | skladchik-mod | lxc | pve03 | running | [PRIVATE_IP] | 6144 MiB | 39.1 GiB | skladchik-mod: moderator v2 + PostgreSQL |","HEAD:kb/private/archive/2026-08-19/docs/03_SERVICE_CATALOG.md:230:## VM/LXC 200 \u2014 skladchik-mod","HEAD:kb/private/archive/2026-08-19/docs/03_SERVICE_CATALOG.md:232:Role: skladchik-mod: moderator v2 + PostgreSQL.","HEAD:kb/private/archive/2026-08-19/docs/03_SERVICE_CATALOG.md:235:- `skladchik-moderator-v2-collector.service`","HEAD:kb/private/archive/2026-08-19/docs/03_SERVICE_CATALOG.md:236:- `skladchik-moderator-v2-collector.timer`","HEAD:kb/private/archive/2026-08-19/docs/03_SERVICE_CATALOG.md:237:- `skladchik-moderator-v2-rules.service`","HEAD:kb/private/archive/2026-08-19/docs/03_SERVICE_CATALOG.md:238:- `skladchik-moderator-v2-rules.timer`","HEAD:kb/private/archive/2026-08-19/docs/03_SERVICE_CATALOG.md:239:- `skladchik-moderator-v2-web.service`","HEAD:kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md:18:| CT200 skladchik-mod | historical future RETIRE candidate | preserve required data/monitoring first |","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:1929:      \"name\": \"skladchik-mod\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:1941:        \"skladchik-moderator-v2-web.service\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:1993:          \"unit\": \"skladchik-moderator-v2-collector.timer\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:1997:          \"unit\": \"skladchik-moderator-v2-rules.timer\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:2012:        \"skladchik-moderator-v2-collector.service\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:2013:        \"skladchik-moderator-v2-collector.timer\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:2014:        \"skladchik-moderator-v2-rules.service\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:2015:        \"skladchik-moderator-v2-rules.timer\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:2016:        \"skladchik-moderator-v2-web.service\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:2031:      \"role\": \"skladchik-mod: moderator v2 + PostgreSQL\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.json:2038:        \"name\": \"skladchik-mod\",","HEAD:kb/private/archive/2026-08-19/machine/cluster_inventory.tsv:13:200\tskladchik-mod\tlxc\tpve03\trunning\t[PRIVATE_IP]\t6144\t39.1\tskladchik-mod: moderator v2 + PostgreSQL","HEAD:observed/cluster-guests.json:238:    \"id\": \"lxc/200\",","HEAD:observed/cluster-guests.json:244:    \"name\": \"skladchik-mod\","],"rc":0,"stderr_sha256":null,"stdout_sha256":"df20c2a29261d45b0b381d76e521bf77e9564403622c73fc1790fba39ba4d42d"},"head":{"lines":["d5e2ef5639398a762283e47143c17b494f8ed579"],"rc":0,"stderr_sha256":null,"stdout_sha256":"baa4912ce1befe1c70ce681a7e9110152b3c894c8b36ed9880013efd7b70cb29"},"history":{"lines":[],"rc":0,"stderr_sha256":null,"stdout_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},"refs":{"refs/heads/cr-2026-0035-skladchik-moderator-ct200":{"diff_names":{"lines":["D\t.gitea/workflows/validate-kb.yml","M\tACTIVE_CHANGES.md","M\tAGENTS.md","M\tCURRENT_CONTEXT.md","D\tKB_START_HERE.md","M\tREADME.md","D\tchanges/CR-2026-0018/acceptance.json","D\tchanges/CR-2026-0018/caller-inventory-requirements.md","D\tchanges/CR-2026-0018/design.md","A\tchanges/CR-2026-0018/evidence.md","D\tchanges/CR-2026-0018/execution-contract.md","A\tchanges/CR-2026-0018/plan.json","D\tchanges/CR-2026-0018/plan.md","D\tchanges/CR-2026-0018/regression-cases-draft.json","D\tchanges/CR-2026-0018/request.json","D\tchanges/CR-2026-0018/review-decision.md","M\tchanges/CR-2026-0018/risk.md","M\tchanges/CR-2026-0018/rollback.md","A\tchanges/CR-2026-0018/task-package.sha256","D\tchanges/CR-2026-0018/task-reference.md","M\tchanges/CR-2026-0018/tests.md","D\tchanges/CR-2026-0018/threat-model.md","A\tchanges/CR-2026-0019/evidence.md","A\tchanges/CR-2026-0019/plan.json","A\tchanges/CR-2026-0019/risk.md","A\tchanges/CR-2026-0019/rollback.md","A\tchanges/CR-2026-0019/source-freeze.sha256","A\tchanges/CR-2026-0019/task-package.sha256","A\tchanges/CR-2026-0019/tests.md","A\tchanges/CR-2026-0026/design-package.sha256","A\tchanges/CR-2026-0026/discovery.md","A\tchanges/CR-2026-0026/implementation.md","A\tchanges/CR-2026-0026/plan.json","A\tchanges/CR-2026-0026/risk.md","A\tchanges/CR-2026-0026/rollback.md","A\tchanges/CR-2026-0026/source-provenance.tsv","A\tchanges/CR-2026-0026/task-package.sha256","A\tchanges/CR-2026-0026/tests.md","A\tchanges/CR-2026-0027/design-package.sha256","A\tchanges/CR-2026-0027/discovery.md","A\tchanges/CR-2026-0027/implementation.md","A\tchanges/CR-2026-0027/plan.json","A\tchanges/CR-2026-0027/risk.md","A\tchanges/CR-2026-0027/rollback.md","A\tchanges/CR-2026-0027/source-provenance.tsv","A\tchanges/CR-2026-0027/task-package.sha256","A\tchanges/CR-2026-0027/tests.md","A\tchanges/CR-2026-0028/design-package.sha256","A\tchanges/CR-2026-0028/discovery.md","A\tchanges/CR-2026-0028/implementation.md","A\tchanges/CR-2026-0028/plan.json","A\tchanges/CR-2026-0028/risk.md","A\tchanges/CR-2026-0028/rollback.md","A\tchanges/CR-2026-0028/source-provenance.tsv","A\tchanges/CR-2026-0028/task-package.sha256","A\tchanges/CR-2026-0028/tests.md","A\tchanges/CR-2026-0029/design-package.sha256","A\tchanges/CR-2026-0029/discovery.md","A\tchanges/CR-2026-0029/implementation.md","A\tchanges/CR-2026-0029/plan.json","A\tchanges/CR-2026-0029/risk.md","A\tchanges/CR-2026-0029/rollback.md","A\tchanges/CR-2026-0029/source-provenance.tsv","A\tchanges/CR-2026-0029/task-package.sha256","A\tchanges/CR-2026-0029/tests.md","A\tchanges/CR-2026-0030/design-package.sha256","A\tchanges/CR-2026-0030/discovery.md","A\tchanges/CR-2026-0030/implementation.md","A\tchanges/CR-2026-0030/plan.json","A\tchanges/CR-2026-0030/risk.md","A\tchanges/CR-2026-0030/rollback.md","A\tchanges/CR-2026-0030/source-provenance.tsv","A\tchanges/CR-2026-0030/task-package.sha256","A\tchanges/CR-2026-0030/tests.md","A\tchanges/CR-2026-0031/design-package.sha256","A\tchanges/CR-2026-0031/discovery.md","A\tchanges/CR-2026-0031/implementation.md","A\tchanges/CR-2026-0031/risk.md","A\tchanges/CR-2026-0031/source-provenance.tsv","A\tchanges/CR-2026-0031/task-package.sha256","A\tchanges/CR-2026-0031/tests.md","A\tchanges/CR-2026-0032/README.md","A\tchanges/CR-2026-0032/design-package.sha256","A\tchanges/CR-2026-0032/task-package.sha256","A\tchanges/CR-2026-0033/README.md","A\tchanges/CR-2026-0033/design-package.sha256","A\tchanges/CR-2026-0033/task-package.sha256","A\tchanges/CR-2026-0034/README.md","A\tchanges/CR-2026-0034/design-package.sha256","A\tchanges/CR-2026-0034/task-package.sha256","A\tchanges/CR-2026-0035/discovery.md","A\tchanges/CR-2026-0035/implementation.md","A\tchanges/CR-2026-0035/package.sha256","A\tchanges/CR-2026-0035/risk.md","A\tchanges/CR-2026-0035/source-provenance.tsv","A\tchanges/CR-2026-0035/tests.md","D\tchanges/CR-2026-0078/task-package.sha256","D\tchanges/CR-2026-0079/README.md","D\tchanges/CR-2026-0079/mail-pvepro-dr-observer-source.tar.gz","D\tchanges/CR-2026-0079/task-package.sha256","D\tchanges/CR-2026-0080/task-package.sha256","D\tchanges/CR-2026-0081/home-forward-retire-package.sha256","D\tchanges/CR-2026-0081/turn-dns-retire-package.sha256","D\tchanges/CR-2026-0083/README.md","D\tchanges/CR-2026-0083/gitea-edge-publisher-v3-deploy-v1.tar.gz","D\tchanges/CR-2026-0083/gitea-edge-publisher-v3-source-v1.tar.gz","D\tchanges/CR-2026-0083/source-package.sha256","D\tdeploy/gitea-edge-publisher-v3/MANIFEST.sha256","D\tdeploy/gitea-edge-publisher-v3/deploy.sh","D\tdeploy/gitea-edge-publisher-v3/nginx/git-read-access-log-format.conf","D\tdeploy/gitea-edge-publisher-v3/nginx/git-read-server-observer.conf","D\tdeploy/gitea-edge-publisher-v3/patch_vhost.py","D\tdeploy/gitea-edge-publisher-v3/payload/homelab-gitea-publisher-v3","D\tdeploy/gitea-edge-publisher-v3/payload/homelab-oai-searchbot-observer","D\tdeploy/gitea-edge-publisher-v3/payload/homelab-oai-searchbot-ranges","D\tdeploy/gitea-edge-publisher-v3/rollback.sh","D\tdeploy/gitea-edge-publisher-v3/selftest.sh","D\tdeploy/gitea-edge-publisher-v3/systemd/homelab-gitea-publisher-v3.service","D\tdeploy/gitea-edge-publisher-v3/systemd/homelab-gitea-publisher-v3.timer","D\tdeploy/gitea-edge-publisher-v3/systemd/homelab-oai-searchbot-observer.service"],"rc":0,"stderr_sha256":null,"stdout_sha256":"9f24c0031ba6ccee22a76aee6935c5ff9da440b743eb9428ba38332195f1e1e5"},"exists":true,"vm200":{"lines":["refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/discovery.md:3:- Existing `skladchik-moderator-assistant` is an unused MVP on pve01: one Python file, one rules JSON, SQLite analyses count 0.","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/implementation.md:3:Task: `skladchik-moderator-ct200-infrastructure-v1`.","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/implementation.md:5:The controlled apply creates CT200 on pve03 using the pinned Debian 13 template, 4 vCPU, 6144 MiB RAM, 1024 MiB swap, 40 GiB local-lvm rootfs, unprivileged mode and nesting. It proves boot and DNS, performs an initial vm200 cloud-quorum backup with restore-validation using the candidate worker before changing live backup runtime, then enrolls vm200 in the canonical VM queue/probe/worker/audit/retention runtime on pve01/pve02/pve03 as required.","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:6:cf81f24981ad71f84840f0dc3f7c17d25716ae10d09432de023f2332e41b299c  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-audit","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:7:d5e70fca273e67ec272ea44f73558e28fb707902a09e96497a5fb7cecf4e3336  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-retention-gc","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:8:bd6257397c6ea910df2ea0dd57252b33bccd0bbd965175840486dfe5e079bf96  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-freshness-probe","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:9:91bdd116be865560a38105dffbd1a66d687232035e2359e4a5be4d225e9c61d1  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-node-worker","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:10:6994b8750bb3ced52497699738199a77ba9ac28c51ad23ad6eb3f3576aebbef2  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-queue","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:11:43ff350cd9d98bb521bebde51389ff3b90d3dc4a742b0084586ffd0a1b74f47e  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/pve03-ct200.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:12:019a64e294d164e94cb429c63590e2f7e5e607516bdd4e0dd9cf81d7b729b1e9  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/remote-runtime.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:13:7a230f0f29bcbe29c870472ccb8751b04d9f5e6fdd72af226c83ed3ca417f0e0  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/apply.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:14:4b8798cb5035bb026c1e04a655866b5cfd6772ae76ce747b4b1778ed28964886  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/dry-run.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:15:f12792c78635913ef671cf1d0593aed76599617669e75a90cd3462c611df4c74  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/preflight.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:16:3e12eacd397f5a8c10969d20990353993894aa0c6ed94c696724e9a1d3956055  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/prepare.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:17:1b24b43a7167edd0df215951c1c59885a18fffbfe4318939fd5a3a7eafeb181e  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/rollback.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:18:c34680c51e83699b9e93e8e2720cce06d90dc2b94e4adbb92548d82368b448eb  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/seal.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:19:2730fb3920c07b79a59ce32b0bb8b5d0f5b6569b3430565be4c2da84188ba73c  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/verify.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:20:c9ef2aae496c76e4dc955f2eae91eb472c4abdbd83ca6b9019a02fb17cf14d1c  tasks/skladchik-moderator-ct200-infrastructure-v1/task.json","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:21:980b88d51feb9115695985870af4b48af884876de8d23ee6678c633ae00beb95  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/package.sha256:22:974c6181e543c74ea2bb1a1a392960b98aba8bb1fb8ff111f15fc8d6bbc6d06e  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/test_contract.py","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/risk.md:11:- first vm200 SEALED backup and restore evidence before live enrollment;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/risk.md:13:- rollback preserves any already sealed vm200 cloud generation/evidence rather than deleting recovery data;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/tests.md:14:- Regression: retention candidate requires SSH stdin isolation and live plan must emit vm200 after hotfix.","refs/heads/cr-2026-0035-skladchik-moderator-ct200:changes/CR-2026-0035/tests.md:15:- Live hotfix proof requires read-only candidate/post-install retention plans to include remote-owned VMIDs and `KEEP|logical=vm200|...|reason=POLICY_NEWEST_2`.","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-freshness-probe:12:    memos|skladchik-moderator-assistant|filebrowser|skladchik-reports-monitor|immich|hbarhub|scrutiny) printf 'app-%s\\n' \"$1\" ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-queue:9:ALL_APPS=(memos skladchik-moderator-assistant filebrowser skladchik-reports-monitor immich hbarhub scrutiny)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-queue:10:MIGRATE_APPS=(skladchik-moderator-assistant filebrowser skladchik-reports-monitor immich hbarhub scrutiny)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-queue:84:  case \"$a\" in memos|skladchik-moderator-assistant|filebrowser|skladchik-reports-monitor|immich|hbarhub|scrutiny) ;; *) die \"APP_NOT_ALLOWED_$a\" 64 ;; esac","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:72:    skladchik-moderator-assistant) echo app-skladchik-moderator-assistant ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:85:    skladchik-moderator-assistant) echo pve01 ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:173:  started=\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"; new_capture_paths skladchik-moderator-assistant \"$gen\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:174:  mkdir -p \"$CAPTURE/skladchik-moderator-assistant/var-lib\" \"$CAPTURE/skladchik-moderator-assistant/opt\" \"$CAPTURE/skladchik-moderator-assistant/systemd\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:175:  [[ -s /var/lib/skladchik-moderator-assistant/state.sqlite3 ]] || die MODERATOR_DB_MISSING 66","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:176:  sqlite3 /var/lib/skladchik-moderator-assistant/state.sqlite3 \".backup '$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3'\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:177:  chown --reference=/var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:178:  chmod --reference=/var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:179:  touch -r /var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:180:  [[ \"$(sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\" 'PRAGMA integrity_check;'|tail -n1)\" == ok ]] || die MODERATOR_DB_BACKUP_INVALID 70","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:181:  cp -a /opt/skladchik-moderator-assistant/. \"$CAPTURE/skladchik-moderator-assistant/opt/\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:182:  [[ -f /etc/systemd/system/skladchik-moderator-assistant.service ]] && cp -a /etc/systemd/system/skladchik-moderator-assistant.service \"$CAPTURE/skladchik-moderator-assistant/systemd/\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:183:  dbsha=\"$(sha256sum \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"|awk '{print $1}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:184:  manifest_tree \"$CAPTURE/skladchik-moderator-assistant\" \"$CAPTURE/skladchik-moderator-assistant/files.sha256\"; treesha=\"$(sha256sum \"$CAPTURE/skladchik-moderator-assistant/files.sha256\"|awk '{print $1}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:186:  comps=\"$(jq -n --arg a \"$dbsha\" --arg b \"$treesha\" '{database:{path:\"skladchik-moderator-assistant/var-lib/state.sqlite3\",sha256:$a},files_manifest:{path:\"skladchik-moderator-assistant/files.sha256\",sha256:$b}}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:187:  write_binding \"$CAPTURE/app-generation.json\" app-skladchik-moderator-assistant \"$gen\" skladchik-moderator-assistant \"$started\" \"$completed\" \"\" \"\" \"$comps\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:358:    skladchik-moderator-assistant) capture_moderator \"$gen\" ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:433:    skladchik-moderator-assistant)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:434:      db=\"$ex/skladchik-moderator-assistant/var-lib/state.sqlite3\"; [[ \"$(sqlite3 \"$db\" 'PRAGMA integrity_check;'|tail -n1)\" == ok ]] || die MODERATOR_RESTORE_INTEGRITY_FAILED 70","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:436:      (cd \"$ex/skladchik-moderator-assistant\"; sha256sum -c files.sha256 >/dev/null)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:437:      find \"$ex/skladchik-moderator-assistant/opt\" -type f -name '*.py' -print0 | xargs -0 -r python3 -m py_compile","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-cloud-quorum-v1/assets/runtime/homelab-app-cloud-quorum-worker:624:    skladchik-moderator-assistant) test -s /var/lib/skladchik-moderator-assistant/state.sqlite3 ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-freshness-probe:12:    memos|skladchik-moderator-assistant|filebrowser|skladchik-reports-monitor|immich|hbarhub|scrutiny) printf 'app-%s\\n' \"$1\" ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-queue:9:ALL_APPS=(memos skladchik-moderator-assistant filebrowser skladchik-reports-monitor immich hbarhub scrutiny)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-queue:10:MIGRATE_APPS=(skladchik-moderator-assistant filebrowser skladchik-reports-monitor immich hbarhub scrutiny)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-queue:84:  case \"$a\" in memos|skladchik-moderator-assistant|filebrowser|skladchik-reports-monitor|immich|hbarhub|scrutiny) ;; *) die \"APP_NOT_ALLOWED_$a\" 64 ;; esac","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:72:    skladchik-moderator-assistant) echo app-skladchik-moderator-assistant ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:85:    skladchik-moderator-assistant) echo pve01 ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:173:  started=\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"; new_capture_paths skladchik-moderator-assistant \"$gen\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:174:  mkdir -p \"$CAPTURE/skladchik-moderator-assistant/var-lib\" \"$CAPTURE/skladchik-moderator-assistant/opt\" \"$CAPTURE/skladchik-moderator-assistant/systemd\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:175:  [[ -s /var/lib/skladchik-moderator-assistant/state.sqlite3 ]] || die MODERATOR_DB_MISSING 66","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:176:  sqlite3 /var/lib/skladchik-moderator-assistant/state.sqlite3 \".backup '$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3'\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:177:  chown --reference=/var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:178:  chmod --reference=/var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:179:  touch -r /var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:180:  [[ \"$(sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\" 'PRAGMA integrity_check;'|tail -n1)\" == ok ]] || die MODERATOR_DB_BACKUP_INVALID 70","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:181:  cp -a /opt/skladchik-moderator-assistant/. \"$CAPTURE/skladchik-moderator-assistant/opt/\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:182:  [[ -f /etc/systemd/system/skladchik-moderator-assistant.service ]] && cp -a /etc/systemd/system/skladchik-moderator-assistant.service \"$CAPTURE/skladchik-moderator-assistant/systemd/\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:183:  dbsha=\"$(sha256sum \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"|awk '{print $1}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:184:  manifest_tree \"$CAPTURE/skladchik-moderator-assistant\" \"$CAPTURE/skladchik-moderator-assistant/files.sha256\"; treesha=\"$(sha256sum \"$CAPTURE/skladchik-moderator-assistant/files.sha256\"|awk '{print $1}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:186:  comps=\"$(jq -n --arg a \"$dbsha\" --arg b \"$treesha\" '{database:{path:\"skladchik-moderator-assistant/var-lib/state.sqlite3\",sha256:$a},files_manifest:{path:\"skladchik-moderator-assistant/files.sha256\",sha256:$b}}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:187:  write_binding \"$CAPTURE/app-generation.json\" app-skladchik-moderator-assistant \"$gen\" skladchik-moderator-assistant \"$started\" \"$completed\" \"\" \"\" \"$comps\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:358:    skladchik-moderator-assistant) capture_moderator \"$gen\" ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:433:    skladchik-moderator-assistant)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:434:      db=\"$ex/skladchik-moderator-assistant/var-lib/state.sqlite3\"; [[ \"$(sqlite3 \"$db\" 'PRAGMA integrity_check;'|tail -n1)\" == ok ]] || die MODERATOR_RESTORE_INTEGRITY_FAILED 70","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:436:      (cd \"$ex/skladchik-moderator-assistant\"; sha256sum -c files.sha256 >/dev/null)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:437:      find \"$ex/skladchik-moderator-assistant/opt\" -type f -name '*.py' -print0 | xargs -0 -r python3 -m py_compile","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-bootstrap-configs-source-v1/assets/runtime/homelab-app-cloud-quorum-worker:624:    skladchik-moderator-assistant) test -s /var/lib/skladchik-moderator-assistant/state.sqlite3 ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-freshness-probe:12:    memos|skladchik-moderator-assistant|filebrowser|skladchik-reports-monitor|immich|hbarhub|scrutiny) printf 'app-%s\\n' \"$1\" ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-queue:9:ALL_APPS=(memos skladchik-moderator-assistant filebrowser skladchik-reports-monitor immich hbarhub scrutiny)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-queue:10:MIGRATE_APPS=(skladchik-moderator-assistant filebrowser skladchik-reports-monitor immich hbarhub scrutiny)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-queue:84:  case \"$a\" in memos|skladchik-moderator-assistant|filebrowser|skladchik-reports-monitor|immich|hbarhub|scrutiny) ;; *) die \"APP_NOT_ALLOWED_$a\" 64 ;; esac","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:72:    skladchik-moderator-assistant) echo app-skladchik-moderator-assistant ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:85:    skladchik-moderator-assistant) echo pve01 ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:173:  started=\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"; new_capture_paths skladchik-moderator-assistant \"$gen\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:174:  mkdir -p \"$CAPTURE/skladchik-moderator-assistant/var-lib\" \"$CAPTURE/skladchik-moderator-assistant/opt\" \"$CAPTURE/skladchik-moderator-assistant/systemd\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:175:  [[ -s /var/lib/skladchik-moderator-assistant/state.sqlite3 ]] || die MODERATOR_DB_MISSING 66","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:176:  sqlite3 /var/lib/skladchik-moderator-assistant/state.sqlite3 \".backup '$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3'\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:177:  chown --reference=/var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:178:  chmod --reference=/var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:179:  touch -r /var/lib/skladchik-moderator-assistant/state.sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:180:  [[ \"$(sqlite3 \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\" 'PRAGMA integrity_check;'|tail -n1)\" == ok ]] || die MODERATOR_DB_BACKUP_INVALID 70","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:181:  cp -a /opt/skladchik-moderator-assistant/. \"$CAPTURE/skladchik-moderator-assistant/opt/\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:182:  [[ -f /etc/systemd/system/skladchik-moderator-assistant.service ]] && cp -a /etc/systemd/system/skladchik-moderator-assistant.service \"$CAPTURE/skladchik-moderator-assistant/systemd/\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:183:  dbsha=\"$(sha256sum \"$CAPTURE/skladchik-moderator-assistant/var-lib/state.sqlite3\"|awk '{print $1}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:184:  manifest_tree \"$CAPTURE/skladchik-moderator-assistant\" \"$CAPTURE/skladchik-moderator-assistant/files.sha256\"; treesha=\"$(sha256sum \"$CAPTURE/skladchik-moderator-assistant/files.sha256\"|awk '{print $1}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:186:  comps=\"$(jq -n --arg a \"$dbsha\" --arg b \"$treesha\" '{database:{path:\"skladchik-moderator-assistant/var-lib/state.sqlite3\",sha256:$a},files_manifest:{path:\"skladchik-moderator-assistant/files.sha256\",sha256:$b}}')\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:187:  write_binding \"$CAPTURE/app-generation.json\" app-skladchik-moderator-assistant \"$gen\" skladchik-moderator-assistant \"$started\" \"$completed\" \"\" \"\" \"$comps\"","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:358:    skladchik-moderator-assistant) capture_moderator \"$gen\" ;;","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:433:    skladchik-moderator-assistant)","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:434:      db=\"$ex/skladchik-moderator-assistant/var-lib/state.sqlite3\"; [[ \"$(sqlite3 \"$db\" 'PRAGMA integrity_check;'|tail -n1)\" == ok ]] || die MODERATOR_RESTORE_INTEGRITY_FAILED 70","refs/heads/cr-2026-0035-skladchik-moderator-ct200:tasks/backup-control-final-generation-v1/assets/runtime/homelab-app-cloud-quorum-worker:436:      (cd \"$ex/skladchik-moderator-assistant\"; sha256sum -c files.sha256 >/dev/null)"],"rc":0,"stderr_sha256":null,"stdout_sha256":"68d1d931e6d4c48dd15ac5faeb8feddb0548018245d16997d7c486f29c56d355"}},"refs/heads/cr-2026-0058-legacy-backup-target-retirement":{"diff_names":{"lines":["D\t.gitea/workflows/validate-kb.yml","M\tACTIVE_CHANGES.md","M\tAGENTS.md","M\tCURRENT_CONTEXT.md","D\tKB_START_HERE.md","M\tREADME.md","D\tchanges/CR-2026-0018/acceptance.json","D\tchanges/CR-2026-0018/caller-inventory-requirements.md","D\tchanges/CR-2026-0018/design.md","A\tchanges/CR-2026-0018/evidence.md","D\tchanges/CR-2026-0018/execution-contract.md","A\tchanges/CR-2026-0018/plan.json","D\tchanges/CR-2026-0018/plan.md","D\tchanges/CR-2026-0018/regression-cases-draft.json","D\tchanges/CR-2026-0018/request.json","D\tchanges/CR-2026-0018/review-decision.md","M\tchanges/CR-2026-0018/risk.md","M\tchanges/CR-2026-0018/rollback.md","A\tchanges/CR-2026-0018/task-package.sha256","D\tchanges/CR-2026-0018/task-reference.md","M\tchanges/CR-2026-0018/tests.md","D\tchanges/CR-2026-0018/threat-model.md","A\tchanges/CR-2026-0019/evidence.md","A\tchanges/CR-2026-0019/plan.json","A\tchanges/CR-2026-0019/risk.md","A\tchanges/CR-2026-0019/rollback.md","A\tchanges/CR-2026-0019/source-freeze.sha256","A\tchanges/CR-2026-0019/task-package.sha256","A\tchanges/CR-2026-0019/tests.md","A\tchanges/CR-2026-0026/design-package.sha256","A\tchanges/CR-2026-0026/discovery.md","A\tchanges/CR-2026-0026/implementation.md","A\tchanges/CR-2026-0026/plan.json","A\tchanges/CR-2026-0026/risk.md","A\tchanges/CR-2026-0026/rollback.md","A\tchanges/CR-2026-0026/source-provenance.tsv","A\tchanges/CR-2026-0026/task-package.sha256","A\tchanges/CR-2026-0026/tests.md","A\tchanges/CR-2026-0027/design-package.sha256","A\tchanges/CR-2026-0027/discovery.md","A\tchanges/CR-2026-0027/implementation.md","A\tchanges/CR-2026-0027/plan.json","A\tchanges/CR-2026-0027/risk.md","A\tchanges/CR-2026-0027/rollback.md","A\tchanges/CR-2026-0027/source-provenance.tsv","A\tchanges/CR-2026-0027/task-package.sha256","A\tchanges/CR-2026-0027/tests.md","A\tchanges/CR-2026-0028/design-package.sha256","A\tchanges/CR-2026-0028/discovery.md","A\tchanges/CR-2026-0028/implementation.md","A\tchanges/CR-2026-0028/plan.json","A\tchanges/CR-2026-0028/risk.md","A\tchanges/CR-2026-0028/rollback.md","A\tchanges/CR-2026-0028/source-provenance.tsv","A\tchanges/CR-2026-0028/task-package.sha256","A\tchanges/CR-2026-0028/tests.md","A\tchanges/CR-2026-0029/design-package.sha256","A\tchanges/CR-2026-0029/discovery.md","A\tchanges/CR-2026-0029/implementation.md","A\tchanges/CR-2026-0029/plan.json","A\tchanges/CR-2026-0029/risk.md","A\tchanges/CR-2026-0029/rollback.md","A\tchanges/CR-2026-0029/source-provenance.tsv","A\tchanges/CR-2026-0029/task-package.sha256","A\tchanges/CR-2026-0029/tests.md","A\tchanges/CR-2026-0030/design-package.sha256","A\tchanges/CR-2026-0030/discovery.md","A\tchanges/CR-2026-0030/implementation.md","A\tchanges/CR-2026-0030/plan.json","A\tchanges/CR-2026-0030/risk.md","A\tchanges/CR-2026-0030/rollback.md","A\tchanges/CR-2026-0030/source-provenance.tsv","A\tchanges/CR-2026-0030/task-package.sha256","A\tchanges/CR-2026-0030/tests.md","A\tchanges/CR-2026-0031/design-package.sha256","A\tchanges/CR-2026-0031/discovery.md","A\tchanges/CR-2026-0031/implementation.md","A\tchanges/CR-2026-0031/risk.md","A\tchanges/CR-2026-0031/source-provenance.tsv","A\tchanges/CR-2026-0031/task-package.sha256","A\tchanges/CR-2026-0031/tests.md","A\tchanges/CR-2026-0032/README.md","A\tchanges/CR-2026-0032/design-package.sha256","A\tchanges/CR-2026-0032/task-package.sha256","A\tchanges/CR-2026-0033/README.md","A\tchanges/CR-2026-0033/design-package.sha256","A\tchanges/CR-2026-0033/task-package.sha256","A\tchanges/CR-2026-0034/README.md","A\tchanges/CR-2026-0034/design-package.sha256","A\tchanges/CR-2026-0034/task-package.sha256","A\tchanges/CR-2026-0035/discovery.md","A\tchanges/CR-2026-0035/implementation.md","A\tchanges/CR-2026-0035/package.sha256","A\tchanges/CR-2026-0035/risk.md","A\tchanges/CR-2026-0035/source-provenance.tsv","A\tchanges/CR-2026-0035/tests.md","A\tchanges/CR-2026-0036/discovery.md","A\tchanges/CR-2026-0036/implementation.md","A\tchanges/CR-2026-0036/package.sha256","A\tchanges/CR-2026-0036/risk.md","A\tchanges/CR-2026-0036/source-provenance.tsv","A\tchanges/CR-2026-0036/tests.md","A\tchanges/CR-2026-0046/discovery.md","A\tchanges/CR-2026-0046/implementation.md","A\tchanges/CR-2026-0046/risk.md","A\tchanges/CR-2026-0046/source-provenance.tsv","A\tchanges/CR-2026-0046/task-package.sha256","A\tchanges/CR-2026-0046/tests.md","A\tchanges/CR-2026-0047/task-package.sha256","A\tchanges/CR-2026-0048/discovery.md","A\tchanges/CR-2026-0048/implementation.md","A\tchanges/CR-2026-0048/risk.md","A\tchanges/CR-2026-0048/source-provenance.tsv","A\tchanges/CR-2026-0048/task-package.sha256","A\tchanges/CR-2026-0048/tests.md","A\tchanges/CR-2026-0049/discovery.md","A\tchanges/CR-2026-0049/implementation.md","A\tchanges/CR-2026-0049/risk.md","A\tchanges/CR-2026-0049/source-provenance.tsv","A\tchanges/CR-2026-0049/task-package.sha256"],"rc":0,"stderr_sha256":null,"stdout_sha256":"40ecc0852c5589b22a435e26bbcf5702ae59069739901be6f22734bf008538f1"},"exists":true,"vm200":{"lines":["refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/discovery.md:3:- Existing `skladchik-moderator-assistant` is an unused MVP on pve01: one Python file, one rules JSON, SQLite analyses count 0.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/implementation.md:3:Task: `skladchik-moderator-ct200-infrastructure-v1`.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/implementation.md:5:The controlled apply creates CT200 on pve03 using the pinned Debian 13 template, 4 vCPU, 6144 MiB RAM, 1024 MiB swap, 40 GiB local-lvm rootfs, unprivileged mode and nesting. It proves boot and DNS, performs an initial vm200 cloud-quorum backup with restore-validation using the candidate worker before changing live backup runtime, then enrolls vm200 in the canonical VM queue/probe/worker/audit/retention runtime on pve01/pve02/pve03 as required.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:6:cf81f24981ad71f84840f0dc3f7c17d25716ae10d09432de023f2332e41b299c  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-audit","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:7:d5e70fca273e67ec272ea44f73558e28fb707902a09e96497a5fb7cecf4e3336  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-retention-gc","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:8:bd6257397c6ea910df2ea0dd57252b33bccd0bbd965175840486dfe5e079bf96  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-freshness-probe","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:9:91bdd116be865560a38105dffbd1a66d687232035e2359e4a5be4d225e9c61d1  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-node-worker","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:10:6994b8750bb3ced52497699738199a77ba9ac28c51ad23ad6eb3f3576aebbef2  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-queue","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:11:43ff350cd9d98bb521bebde51389ff3b90d3dc4a742b0084586ffd0a1b74f47e  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/pve03-ct200.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:12:019a64e294d164e94cb429c63590e2f7e5e607516bdd4e0dd9cf81d7b729b1e9  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/remote-runtime.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:13:7a230f0f29bcbe29c870472ccb8751b04d9f5e6fdd72af226c83ed3ca417f0e0  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/apply.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:14:4b8798cb5035bb026c1e04a655866b5cfd6772ae76ce747b4b1778ed28964886  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/dry-run.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:15:f12792c78635913ef671cf1d0593aed76599617669e75a90cd3462c611df4c74  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/preflight.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:16:3e12eacd397f5a8c10969d20990353993894aa0c6ed94c696724e9a1d3956055  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/prepare.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:17:1b24b43a7167edd0df215951c1c59885a18fffbfe4318939fd5a3a7eafeb181e  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/rollback.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:18:c34680c51e83699b9e93e8e2720cce06d90dc2b94e4adbb92548d82368b448eb  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/seal.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:19:2730fb3920c07b79a59ce32b0bb8b5d0f5b6569b3430565be4c2da84188ba73c  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/verify.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:20:c9ef2aae496c76e4dc955f2eae91eb472c4abdbd83ca6b9019a02fb17cf14d1c  tasks/skladchik-moderator-ct200-infrastructure-v1/task.json","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:21:980b88d51feb9115695985870af4b48af884876de8d23ee6678c633ae00beb95  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:22:974c6181e543c74ea2bb1a1a392960b98aba8bb1fb8ff111f15fc8d6bbc6d06e  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/test_contract.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/risk.md:11:- first vm200 SEALED backup and restore evidence before live enrollment;","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/risk.md:13:- rollback preserves any already sealed vm200 cloud generation/evidence rather than deleting recovery data;","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/tests.md:14:- Regression: retention candidate requires SSH stdin isolation and live plan must emit vm200 after hotfix.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0035/tests.md:15:- Live hotfix proof requires read-only candidate/post-install retention plans to include remote-owned VMIDs and `KEEP|logical=vm200|...|reason=POLICY_NEWEST_2`.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:12:- Recovery after the initial external-network timeout uses a dedicated `skladchik-moderator-v2-edge-egress-v1` task: CT200 alone uses edge-vm `[PRIVATE_IP]` as its default gateway; edge-vm NATs only `[PRIVATE_IP]/32` into its already-existing NetBird `wt0` default exit (table 7120). No NetBird management policy is changed.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:26:Authenticated section evidence on 2026-08-12 showed 107 `discussionListItem` nodes, 106 `PreviewTooltip` markers and 517 root-relative `threads/...` hrefs. `skladchik-moderator-v2-xf1-parser-hotfix-v1` overlays only `forum.py` and `ads.py`, preserving XF2 support while adding XF1 listing/topic/message/search parsing and root-relative URL resolution. Cookie onboarding is fail-closed on the parser hotfix seal and exact installed module SHA values.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:42:The first controlled cookie apply proved the edge-vm source jar before mutation, installed it, then failed only at the v2 `auth-check`; the apply error path removed the CT200 cookie, disabled collector/competitor timers, and removed transient pve03 staging. The divergence was between two authentication classifiers: edge-vm proves the moderator session by authenticated XenForo 1 `discussionListItem` rows, while v2 still downgraded the same cookie-backed section using a text-only login heuristic. `skladchik-moderator-v2-auth-classification-hotfix-v1` preserves the sealed XF1 parser and changes only section authentication classification: a cookie-backed section that parses canonical topic rows is positive auth evidence. This is bounded by the already-observed public response yielding zero rows ","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:54:The authenticated bootstrap reached 104 listed topics and 40 detailed topics but produced zero analyses because every analyzed detail failed at `stage_history.stage = %s` with PostgreSQL `text = bytea`. The application connection inherited `SQL_ASCII`, so Psycopg returned text values as Python bytes and adapted the fetched stage back as `bytea` on the next parameterized query. The fix is at the connection boundary, not an SQL cast: `skladchik-moderator-v2-db-text-encoding-hotfix-v1` pins Psycopg `client_encoding=UTF8`, proves the baseline bytes failure against existing data, then performs a pre-mutation UTF8 probe across every existing app-facing text column and the exact formerly failing stage-history query; apply/verify repeat that proof through the installed module. No schema or data rewr","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:58:The post-cookie health failure after successful authenticated collection (104 listed topics, 17 analyses in the triggering run; 65 analyses persisted overall) was isolated to rule state. The formatting-rule fetch inherited the moderator cookie and was redirected to XenForo `/login/two-step`, creating a non-approved rule-source revision. Rule pages are public policy sources, so `skladchik-moderator-v2-rules-public-sync-hotfix-v1` fetches them through an independent cookie-free Requests session and requires the redirected final URL to preserve the expected rule thread id. Before mutation, the live dry-run requires each current public content hash to already exist as an explicitly approved historical source; a genuinely new rule revision therefore still stops for manual review and is never auto","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:62:The final cookie bootstrap exposed a collector-only SQL defect after all 104 section topics had already been detailed: `global_search_hits` used `ON CONFLICT DO UPDATE` without the unique-key inference target, so PostgreSQL rejected every whole-site duplicate-search upsert for the remaining four topics. Because detail state is committed before duplicate search and analysis, those topics then became ineligible for another detail fetch for two days. `skladchik-moderator-v2-collector-resume-hotfix-v1` fixes the upsert against the existing `UNIQUE(source_topic_id,query_kind,query_text,hit_url)` key and adds a cached-detail analysis backlog that retries topics whose latest committed detail has no analysis at or after that detail timestamp. Its dry-run executes the corrected upsert twice inside a ","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:70:After cookie onboarding is SEALED and current v2 health/timers are re-proven, `skladchik-moderator-v2-old-mvp-retirement-v1` retires only the legacy pve01 operational service. The task pins the exact legacy unit/app/rules bytes and version, captures root-only rollback copies, disables/stops the service, removes `/etc/systemd/system/skladchik-moderator-assistant.service` and `/opt/skladchik-moderator-assistant`, and preserves `/var/lib/skladchik-moderator-assistant` unchanged as inert historical state. Any apply/verify failure before seal restores the exact legacy unit/application and service state. Retirement does not touch CT200, complaints, forum state, or v2 data.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:74:The final retirement task does not delete `/opt/skladchik-moderator-assistant`. The existing app-cloud backup scheduler still schedules `skladchik-moderator-assistant`, and its worker captures `/var/lib/skladchik-moderator-assistant/state.sqlite3` plus `/opt/skladchik-moderator-assistant`. Deleting the legacy app directory would therefore break the next scheduled app backup. Retirement is corrected to disable/stop the old service and remove only its systemd unit/endpoint while preserving the exact legacy app and StateDirectory as inert, byte-pinned historical payload. The task read-only proves the existing queue/audit/worker backup contract before and after retirement; backup runtime itself is not modified.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:76:The old MVP unit uses `DynamicUser=yes` with `StateDirectory=skladchik-moderator-assistant`. Retirement accepts the normal directory layout or the exact systemd-managed `/var/lib/skladchik-moderator-assistant` symlink resolving to `/var/lib/private/skladchik-moderator-assistant`; the SQLite file itself must remain a regular non-symlink file.","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:6:4e119cef286d48ac4675235a82309e0c1087316bcada25bc6f8f43aea665e1dd  tasks/skladchik-moderator-v2-application-v1/assets/app-payload.tar.gz","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:7:cf37824d4bb8d0d412d505cfeca33c81ddc37ac31ceedb6b131181653895fad1  tasks/skladchik-moderator-v2-application-v1/assets/app/config.json","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:8:761de78bd15049d408ed2f109a0fcd87e453d702defdf0e8d1547e1b35a55974  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/__init__.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:9:3e90e6c148a2b7ba52072be35280130f00fb966cfb94b76908fbd2eecd965b35  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/ads.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:10:5664ff8e9d45381a0c08a71a794060e60db8f523bd32911b390d28014066fc6c  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/analyzer.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:11:56f52f89fff1468d5e13da29c3c10cf60bc0aea06d71be871dcfc805aec23b60  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/cli.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:12:122e44d95edfc1c205cdee589ab83a9ccbce724a7951b569995e29171d4cb393  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/collector.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:13:0fd4e356a70e56f7293492b5f3d7677cc1a31156ba1964b3997c8852483edf63  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/competitors.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:14:bb207fe35de98aae0013a15eb27294e24902beeda01daf4f9b404bd8600165bc  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/config.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:15:ba63cc5d4f4e68a0cdd82c985d4fd5989fe9cf4c3beefb94ef1643d4a83bb80e  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/db.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:16:9e3bfd6a9481768800897f4a6be27e68f27e10bec96d3dda567407443b03bc99  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/forum.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:17:5b61133d9b2a72a8e5b86c01627899f60c988dee52fc7fdcc7adb7f82ebe1d47  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/normalize.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:18:88b5d4874b865ebe82ece25448a55bd083f4fb95a2c203621d715b6f0f58df57  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/rules.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:19:4c400f907b0c8fd57a4959a2d3fbc83206fd577e4429b7947e372f15c1637c25  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/schema.sql","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:20:6710a6dae5c3889412c823af20a989d2f1f072dd03451c9b1e00b6078aab570d  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/webapp.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:21:3d7e4c0054a958c6f440ffc2ee112360e1d7a433d3371590deb7575f89323f3b  tasks/skladchik-moderator-v2-application-v1/assets/app/wsgi.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:22:f2f353dd56327395e03d26942deadf4987ac9b3a8a244dc87b3bddbbf9a301d9  tasks/skladchik-moderator-v2-application-v1/assets/pve03-app.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:23:04a441d36e41d30e1190dab7e71d3c05fb5733248ee7308f9b1b675abbf414b9  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-collector.service","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:24:fee9af8ac8ab3f875a2860178b1029a1bc2fa251bf6e42a021585e02eee90c17  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-collector.timer","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:25:d9e99cb8f07c328842f1eebc6d262dca623173cb9cfdd7e2afb4b279449a9519  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-competitor.service","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:26:37cd7bfe11a6c1cd70d5da7c62af19d7147e5f70a9641a0641cac8acbc709bb2  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-competitor.timer","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:27:9789f77fc9d6e246cacbc915b178ed2fedcf1367f7af8fe20a98881abe6597c5  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-rules.service","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:28:a56c7d0c1bef8917f2407cabc9e27d0461b19f5af2698e556365d00673a93180  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-rules.timer","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:29:e9cb92c0702ae26a0c6a063ffaaab0f1bafc08a82c05263509e112ff7847edae  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-web.service","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:30:6e7e7f45c756bec56a64321ebb6ca89d8f4edb8e070a57481e730e2c876deeeb  tasks/skladchik-moderator-v2-application-v1/phases/apply.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:31:d17e4d6f9e9eece7672bccd18dec0fb533810fafb469e0e2ca99753fa5fe4136  tasks/skladchik-moderator-v2-application-v1/phases/dry-run.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:32:8a39aef9926a6cf55c659937817bc5dc12657d5ef1f7edd549dc99530b88ade9  tasks/skladchik-moderator-v2-application-v1/phases/preflight.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:33:5157ec8da4bcfc0b88ccac54bed52a3ffeb676d5513cdb3f6b4ed5955658f76a  tasks/skladchik-moderator-v2-application-v1/phases/prepare.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:34:403263caebb4925ada3957e0dbc852cf1813ba4ceda3fb308c33b2b22107c955  tasks/skladchik-moderator-v2-application-v1/phases/rollback.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:35:11f128d5da0a7c1276b77e10400e825a267633828cd173c0d8e5582902d28443  tasks/skladchik-moderator-v2-application-v1/phases/seal.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:36:3fba9b905dccf09dff024684894443d3b670b973f67c9db7653efde0b1c42fe8  tasks/skladchik-moderator-v2-application-v1/phases/verify.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:37:b9b2aa5fa48836fecbec286136377b8d6af00383df9e1a97b5ba0833c4099d27  tasks/skladchik-moderator-v2-application-v1/task.json","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:38:4b4c8d38c0e6613ec6cf2c6aaf873c506fffe5fd400566255e2a77618da7bb90  tasks/skladchik-moderator-v2-application-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:39:0c23274ab9b0ea843595689536284c86bdc7746220ebb4f140ccd1fff2c752bd  tasks/skladchik-moderator-v2-application-v1/tools/test_contract.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:40:6f9b3c541c451c4b9c0d2d394931c1b7e868349bef3e53167160298df703f2f6  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/auth-selftest.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:41:25eaabbddc54235aaafd2f5829c7e8ed9d1defcf76b8327cf347aeefda823ae0  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/forum.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:42:c2cccab25c73ec554d1a51f9dccf32343b50f5ff3efc4d65c55361032f1a2c30  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/pve03-auth-classifier.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:43:5f6e75e0b38671c55129e2975c64ab8522197f997dae370e3f513628452f1783  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/apply.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:44:caec61da54d9c40bd7cfed623617002c06a18e9604195b6057eb9e4e9bbee294  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/dry-run.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:45:92ee9f19e3a83c1c244c033a277ed5ad312bd7396fd2b3fb9bdd4047aa847957  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/preflight.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:46:7c1ba5eb1e973ac5a2dd1651c89a05ba5a133f5bcf59ec216395887f9019ed7b  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/prepare.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:47:1c95a608369828b9da7c5d78fe630b5b4d947a799cbd22006a02be85686d5d75  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/rollback.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:48:2ab9124cc1428a68ca55c86fe6184f9fce8885dc353218a2caa2d8af742f0c89  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/seal.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:49:06e4185e2678a7e8a71514dd41b1845e84b1099f98003e234929aaa23d1c5d4a  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/verify.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:50:40ed940ba18618988294feede2a24d825a95c8a9ba84d5491f46664466be6b2e  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/task.json","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:51:3d0827c41d83923e0672d2d07f0502f42abc55b825f2f5e5c42dafa851c69419  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:52:49c5c42d757ee1e37123a5dc945d2a17631b74c394dbcd621e90ed7ad132cc72  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/tools/test_contract.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:53:011936d623941792240f8687443220e81357b68b17d419ebcdaa721d0473c63b  tasks/skladchik-moderator-v2-cookie-onboarding-v1/assets/edge-cookie-source.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:54:56a9ab7d9169987c3b8fae6de29e6a3adb4538e34664d1b77c8c6203a9003474  tasks/skladchik-moderator-v2-cookie-onboarding-v1/assets/pve03-cookie.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:55:fb70f92b602588b73eb7eec5816387669576b5de2e07b69ff90de328bef3026b  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/apply.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:56:1ed1ad4b17f96dee387b23989b3e3a974ed501cd5d694cade4d085d52dd295a1  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/dry-run.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:57:a839dd24e8b7c786b3130bd716841e0ced43c49ea1ab3314aebbeaca07dfd436  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/preflight.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:58:e377d14af824721cc1986889f1291da70b87901d1837769390d378f4d2fe5e13  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/prepare.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:59:014cf33ef917d193385449fc13201cefa84148608eb4fd6d3e5f30be06d1dd73  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/rollback.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:60:268b03a7b39225bfb2c97c4c87827c819e2ed727138b6158ff976469daf6887a  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/seal.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:61:6dafb047863c6df90898beeb99dd5ef04862afae3b8a3af57eb8290c671434a6  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/verify.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:62:feec58b4018f777a212520a795e7605455c6fb41da7a1792b60e1d57981c4689  tasks/skladchik-moderator-v2-cookie-onboarding-v1/task.json","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:63:4a8ae4ac4d749a4a7d10b8a21d2729dc2242ef4b0cd3b06f28ac89dd2bbff92c  tasks/skladchik-moderator-v2-cookie-onboarding-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:64:93cb00411e45d9bdd9cb035869fe2be230f6147e76a8898a36606c51d9bcb568  tasks/skladchik-moderator-v2-cookie-onboarding-v1/tools/test_contract.py","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:65:2ee3682cb57e7b6d04195a37b8f7acafde5cb2dc9ca28820e25c7143b3db4706  tasks/skladchik-moderator-v2-edge-egress-v1/assets/edge-egress.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:66:207793e2fa360abb88d535912d7d013af8bc822f4ffb1d8f55a3ea0967dc1ad6  tasks/skladchik-moderator-v2-edge-egress-v1/assets/pve03-egress.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:67:3c32c482e3232df8a2c4d25f553e8e7198c33a378e0600f53c01f71d14d9b3f6  tasks/skladchik-moderator-v2-edge-egress-v1/phases/apply.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:68:c51e41420b857f7d0ff2b8a16c8d0a339b4b942020d4ae59f80721e113e37eec  tasks/skladchik-moderator-v2-edge-egress-v1/phases/dry-run.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:69:d5e83720f2d842f4a1a2aba7ae4a55ce5494d16a43aa67f280d21c3cbed74d16  tasks/skladchik-moderator-v2-edge-egress-v1/phases/preflight.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:70:ee7ba739521639244e37ecf63d218bc18202701e53970f46eb987f7f3c6cb3b5  tasks/skladchik-moderator-v2-edge-egress-v1/phases/prepare.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:71:23aa44a61d9a6197ef236cc71b3f5eb4f9c38cdb24ae68eaa52113d34ac96ac0  tasks/skladchik-moderator-v2-edge-egress-v1/phases/rollback.sh","refs/heads/cr-2026-0058-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:72:ef7485307bd7e9b49c9102268db8b729049226f631441362ad3c2c5227516c12  tasks/skladchik-moderator-v2-edge-egress-v1/phases/seal.sh"],"rc":0,"stderr_sha256":null,"stdout_sha256":"b13094744d9f29c47fc973085e76f2db0645d2b5259d8f98bac8280c34c906c8"}},"refs/heads/cr-2026-0066-legacy-backup-target-retirement":{"diff_names":{"lines":["D\t.gitea/workflows/validate-kb.yml","M\tACTIVE_CHANGES.md","M\tAGENTS.md","M\tCURRENT_CONTEXT.md","D\tKB_START_HERE.md","M\tREADME.md","D\tchanges/CR-2026-0018/acceptance.json","D\tchanges/CR-2026-0018/caller-inventory-requirements.md","D\tchanges/CR-2026-0018/design.md","A\tchanges/CR-2026-0018/evidence.md","D\tchanges/CR-2026-0018/execution-contract.md","A\tchanges/CR-2026-0018/plan.json","D\tchanges/CR-2026-0018/plan.md","D\tchanges/CR-2026-0018/regression-cases-draft.json","D\tchanges/CR-2026-0018/request.json","D\tchanges/CR-2026-0018/review-decision.md","M\tchanges/CR-2026-0018/risk.md","M\tchanges/CR-2026-0018/rollback.md","A\tchanges/CR-2026-0018/task-package.sha256","D\tchanges/CR-2026-0018/task-reference.md","M\tchanges/CR-2026-0018/tests.md","D\tchanges/CR-2026-0018/threat-model.md","A\tchanges/CR-2026-0019/evidence.md","A\tchanges/CR-2026-0019/plan.json","A\tchanges/CR-2026-0019/risk.md","A\tchanges/CR-2026-0019/rollback.md","A\tchanges/CR-2026-0019/source-freeze.sha256","A\tchanges/CR-2026-0019/task-package.sha256","A\tchanges/CR-2026-0019/tests.md","A\tchanges/CR-2026-0026/design-package.sha256","A\tchanges/CR-2026-0026/discovery.md","A\tchanges/CR-2026-0026/implementation.md","A\tchanges/CR-2026-0026/plan.json","A\tchanges/CR-2026-0026/risk.md","A\tchanges/CR-2026-0026/rollback.md","A\tchanges/CR-2026-0026/source-provenance.tsv","A\tchanges/CR-2026-0026/task-package.sha256","A\tchanges/CR-2026-0026/tests.md","A\tchanges/CR-2026-0027/design-package.sha256","A\tchanges/CR-2026-0027/discovery.md","A\tchanges/CR-2026-0027/implementation.md","A\tchanges/CR-2026-0027/plan.json","A\tchanges/CR-2026-0027/risk.md","A\tchanges/CR-2026-0027/rollback.md","A\tchanges/CR-2026-0027/source-provenance.tsv","A\tchanges/CR-2026-0027/task-package.sha256","A\tchanges/CR-2026-0027/tests.md","A\tchanges/CR-2026-0028/design-package.sha256","A\tchanges/CR-2026-0028/discovery.md","A\tchanges/CR-2026-0028/implementation.md","A\tchanges/CR-2026-0028/plan.json","A\tchanges/CR-2026-0028/risk.md","A\tchanges/CR-2026-0028/rollback.md","A\tchanges/CR-2026-0028/source-provenance.tsv","A\tchanges/CR-2026-0028/task-package.sha256","A\tchanges/CR-2026-0028/tests.md","A\tchanges/CR-2026-0029/design-package.sha256","A\tchanges/CR-2026-0029/discovery.md","A\tchanges/CR-2026-0029/implementation.md","A\tchanges/CR-2026-0029/plan.json","A\tchanges/CR-2026-0029/risk.md","A\tchanges/CR-2026-0029/rollback.md","A\tchanges/CR-2026-0029/source-provenance.tsv","A\tchanges/CR-2026-0029/task-package.sha256","A\tchanges/CR-2026-0029/tests.md","A\tchanges/CR-2026-0030/design-package.sha256","A\tchanges/CR-2026-0030/discovery.md","A\tchanges/CR-2026-0030/implementation.md","A\tchanges/CR-2026-0030/plan.json","A\tchanges/CR-2026-0030/risk.md","A\tchanges/CR-2026-0030/rollback.md","A\tchanges/CR-2026-0030/source-provenance.tsv","A\tchanges/CR-2026-0030/task-package.sha256","A\tchanges/CR-2026-0030/tests.md","A\tchanges/CR-2026-0031/design-package.sha256","A\tchanges/CR-2026-0031/discovery.md","A\tchanges/CR-2026-0031/implementation.md","A\tchanges/CR-2026-0031/risk.md","A\tchanges/CR-2026-0031/source-provenance.tsv","A\tchanges/CR-2026-0031/task-package.sha256","A\tchanges/CR-2026-0031/tests.md","A\tchanges/CR-2026-0032/README.md","A\tchanges/CR-2026-0032/design-package.sha256","A\tchanges/CR-2026-0032/task-package.sha256","A\tchanges/CR-2026-0033/README.md","A\tchanges/CR-2026-0033/design-package.sha256","A\tchanges/CR-2026-0033/task-package.sha256","A\tchanges/CR-2026-0034/README.md","A\tchanges/CR-2026-0034/design-package.sha256","A\tchanges/CR-2026-0034/task-package.sha256","A\tchanges/CR-2026-0035/discovery.md","A\tchanges/CR-2026-0035/implementation.md","A\tchanges/CR-2026-0035/package.sha256","A\tchanges/CR-2026-0035/risk.md","A\tchanges/CR-2026-0035/source-provenance.tsv","A\tchanges/CR-2026-0035/tests.md","A\tchanges/CR-2026-0036/discovery.md","A\tchanges/CR-2026-0036/implementation.md","A\tchanges/CR-2026-0036/package.sha256","A\tchanges/CR-2026-0036/risk.md","A\tchanges/CR-2026-0036/source-provenance.tsv","A\tchanges/CR-2026-0036/tests.md","A\tchanges/CR-2026-0046/discovery.md","A\tchanges/CR-2026-0046/implementation.md","A\tchanges/CR-2026-0046/risk.md","A\tchanges/CR-2026-0046/source-provenance.tsv","A\tchanges/CR-2026-0046/task-package.sha256","A\tchanges/CR-2026-0046/tests.md","A\tchanges/CR-2026-0047/task-package.sha256","A\tchanges/CR-2026-0048/discovery.md","A\tchanges/CR-2026-0048/implementation.md","A\tchanges/CR-2026-0048/risk.md","A\tchanges/CR-2026-0048/source-provenance.tsv","A\tchanges/CR-2026-0048/task-package.sha256","A\tchanges/CR-2026-0048/tests.md","A\tchanges/CR-2026-0049/discovery.md","A\tchanges/CR-2026-0049/implementation.md","A\tchanges/CR-2026-0049/risk.md","A\tchanges/CR-2026-0049/source-provenance.tsv","A\tchanges/CR-2026-0049/task-package.sha256"],"rc":0,"stderr_sha256":null,"stdout_sha256":"9fa5851c1315be92bf7836d39b07a8ea66bf7530d2842d02f9e0f99a5e23a9e7"},"exists":true,"vm200":{"lines":["refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/discovery.md:3:- Existing `skladchik-moderator-assistant` is an unused MVP on pve01: one Python file, one rules JSON, SQLite analyses count 0.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/implementation.md:3:Task: `skladchik-moderator-ct200-infrastructure-v1`.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/implementation.md:5:The controlled apply creates CT200 on pve03 using the pinned Debian 13 template, 4 vCPU, 6144 MiB RAM, 1024 MiB swap, 40 GiB local-lvm rootfs, unprivileged mode and nesting. It proves boot and DNS, performs an initial vm200 cloud-quorum backup with restore-validation using the candidate worker before changing live backup runtime, then enrolls vm200 in the canonical VM queue/probe/worker/audit/retention runtime on pve01/pve02/pve03 as required.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:6:cf81f24981ad71f84840f0dc3f7c17d25716ae10d09432de023f2332e41b299c  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-audit","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:7:d5e70fca273e67ec272ea44f73558e28fb707902a09e96497a5fb7cecf4e3336  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-retention-gc","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:8:bd6257397c6ea910df2ea0dd57252b33bccd0bbd965175840486dfe5e079bf96  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-freshness-probe","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:9:91bdd116be865560a38105dffbd1a66d687232035e2359e4a5be4d225e9c61d1  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-node-worker","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:10:6994b8750bb3ced52497699738199a77ba9ac28c51ad23ad6eb3f3576aebbef2  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-queue","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:11:43ff350cd9d98bb521bebde51389ff3b90d3dc4a742b0084586ffd0a1b74f47e  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/pve03-ct200.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:12:019a64e294d164e94cb429c63590e2f7e5e607516bdd4e0dd9cf81d7b729b1e9  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/remote-runtime.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:13:7a230f0f29bcbe29c870472ccb8751b04d9f5e6fdd72af226c83ed3ca417f0e0  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/apply.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:14:4b8798cb5035bb026c1e04a655866b5cfd6772ae76ce747b4b1778ed28964886  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/dry-run.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:15:f12792c78635913ef671cf1d0593aed76599617669e75a90cd3462c611df4c74  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/preflight.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:16:3e12eacd397f5a8c10969d20990353993894aa0c6ed94c696724e9a1d3956055  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/prepare.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:17:1b24b43a7167edd0df215951c1c59885a18fffbfe4318939fd5a3a7eafeb181e  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/rollback.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:18:c34680c51e83699b9e93e8e2720cce06d90dc2b94e4adbb92548d82368b448eb  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/seal.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:19:2730fb3920c07b79a59ce32b0bb8b5d0f5b6569b3430565be4c2da84188ba73c  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/verify.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:20:c9ef2aae496c76e4dc955f2eae91eb472c4abdbd83ca6b9019a02fb17cf14d1c  tasks/skladchik-moderator-ct200-infrastructure-v1/task.json","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:21:980b88d51feb9115695985870af4b48af884876de8d23ee6678c633ae00beb95  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/package.sha256:22:974c6181e543c74ea2bb1a1a392960b98aba8bb1fb8ff111f15fc8d6bbc6d06e  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/test_contract.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/risk.md:11:- first vm200 SEALED backup and restore evidence before live enrollment;","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/risk.md:13:- rollback preserves any already sealed vm200 cloud generation/evidence rather than deleting recovery data;","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/tests.md:14:- Regression: retention candidate requires SSH stdin isolation and live plan must emit vm200 after hotfix.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0035/tests.md:15:- Live hotfix proof requires read-only candidate/post-install retention plans to include remote-owned VMIDs and `KEEP|logical=vm200|...|reason=POLICY_NEWEST_2`.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:12:- Recovery after the initial external-network timeout uses a dedicated `skladchik-moderator-v2-edge-egress-v1` task: CT200 alone uses edge-vm `[PRIVATE_IP]` as its default gateway; edge-vm NATs only `[PRIVATE_IP]/32` into its already-existing NetBird `wt0` default exit (table 7120). No NetBird management policy is changed.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:26:Authenticated section evidence on 2026-08-12 showed 107 `discussionListItem` nodes, 106 `PreviewTooltip` markers and 517 root-relative `threads/...` hrefs. `skladchik-moderator-v2-xf1-parser-hotfix-v1` overlays only `forum.py` and `ads.py`, preserving XF2 support while adding XF1 listing/topic/message/search parsing and root-relative URL resolution. Cookie onboarding is fail-closed on the parser hotfix seal and exact installed module SHA values.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:42:The first controlled cookie apply proved the edge-vm source jar before mutation, installed it, then failed only at the v2 `auth-check`; the apply error path removed the CT200 cookie, disabled collector/competitor timers, and removed transient pve03 staging. The divergence was between two authentication classifiers: edge-vm proves the moderator session by authenticated XenForo 1 `discussionListItem` rows, while v2 still downgraded the same cookie-backed section using a text-only login heuristic. `skladchik-moderator-v2-auth-classification-hotfix-v1` preserves the sealed XF1 parser and changes only section authentication classification: a cookie-backed section that parses canonical topic rows is positive auth evidence. This is bounded by the already-observed public response yielding zero rows ","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:54:The authenticated bootstrap reached 104 listed topics and 40 detailed topics but produced zero analyses because every analyzed detail failed at `stage_history.stage = %s` with PostgreSQL `text = bytea`. The application connection inherited `SQL_ASCII`, so Psycopg returned text values as Python bytes and adapted the fetched stage back as `bytea` on the next parameterized query. The fix is at the connection boundary, not an SQL cast: `skladchik-moderator-v2-db-text-encoding-hotfix-v1` pins Psycopg `client_encoding=UTF8`, proves the baseline bytes failure against existing data, then performs a pre-mutation UTF8 probe across every existing app-facing text column and the exact formerly failing stage-history query; apply/verify repeat that proof through the installed module. No schema or data rewr","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:58:The post-cookie health failure after successful authenticated collection (104 listed topics, 17 analyses in the triggering run; 65 analyses persisted overall) was isolated to rule state. The formatting-rule fetch inherited the moderator cookie and was redirected to XenForo `/login/two-step`, creating a non-approved rule-source revision. Rule pages are public policy sources, so `skladchik-moderator-v2-rules-public-sync-hotfix-v1` fetches them through an independent cookie-free Requests session and requires the redirected final URL to preserve the expected rule thread id. Before mutation, the live dry-run requires each current public content hash to already exist as an explicitly approved historical source; a genuinely new rule revision therefore still stops for manual review and is never auto","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:62:The final cookie bootstrap exposed a collector-only SQL defect after all 104 section topics had already been detailed: `global_search_hits` used `ON CONFLICT DO UPDATE` without the unique-key inference target, so PostgreSQL rejected every whole-site duplicate-search upsert for the remaining four topics. Because detail state is committed before duplicate search and analysis, those topics then became ineligible for another detail fetch for two days. `skladchik-moderator-v2-collector-resume-hotfix-v1` fixes the upsert against the existing `UNIQUE(source_topic_id,query_kind,query_text,hit_url)` key and adds a cached-detail analysis backlog that retries topics whose latest committed detail has no analysis at or after that detail timestamp. Its dry-run executes the corrected upsert twice inside a ","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:70:After cookie onboarding is SEALED and current v2 health/timers are re-proven, `skladchik-moderator-v2-old-mvp-retirement-v1` retires only the legacy pve01 operational service. The task pins the exact legacy unit/app/rules bytes and version, captures root-only rollback copies, disables/stops the service, removes `/etc/systemd/system/skladchik-moderator-assistant.service` and `/opt/skladchik-moderator-assistant`, and preserves `/var/lib/skladchik-moderator-assistant` unchanged as inert historical state. Any apply/verify failure before seal restores the exact legacy unit/application and service state. Retirement does not touch CT200, complaints, forum state, or v2 data.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:74:The final retirement task does not delete `/opt/skladchik-moderator-assistant`. The existing app-cloud backup scheduler still schedules `skladchik-moderator-assistant`, and its worker captures `/var/lib/skladchik-moderator-assistant/state.sqlite3` plus `/opt/skladchik-moderator-assistant`. Deleting the legacy app directory would therefore break the next scheduled app backup. Retirement is corrected to disable/stop the old service and remove only its systemd unit/endpoint while preserving the exact legacy app and StateDirectory as inert, byte-pinned historical payload. The task read-only proves the existing queue/audit/worker backup contract before and after retirement; backup runtime itself is not modified.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/implementation.md:76:The old MVP unit uses `DynamicUser=yes` with `StateDirectory=skladchik-moderator-assistant`. Retirement accepts the normal directory layout or the exact systemd-managed `/var/lib/skladchik-moderator-assistant` symlink resolving to `/var/lib/private/skladchik-moderator-assistant`; the SQLite file itself must remain a regular non-symlink file.","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:6:4e119cef286d48ac4675235a82309e0c1087316bcada25bc6f8f43aea665e1dd  tasks/skladchik-moderator-v2-application-v1/assets/app-payload.tar.gz","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:7:cf37824d4bb8d0d412d505cfeca33c81ddc37ac31ceedb6b131181653895fad1  tasks/skladchik-moderator-v2-application-v1/assets/app/config.json","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:8:761de78bd15049d408ed2f109a0fcd87e453d702defdf0e8d1547e1b35a55974  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/__init__.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:9:3e90e6c148a2b7ba52072be35280130f00fb966cfb94b76908fbd2eecd965b35  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/ads.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:10:5664ff8e9d45381a0c08a71a794060e60db8f523bd32911b390d28014066fc6c  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/analyzer.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:11:56f52f89fff1468d5e13da29c3c10cf60bc0aea06d71be871dcfc805aec23b60  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/cli.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:12:122e44d95edfc1c205cdee589ab83a9ccbce724a7951b569995e29171d4cb393  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/collector.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:13:0fd4e356a70e56f7293492b5f3d7677cc1a31156ba1964b3997c8852483edf63  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/competitors.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:14:bb207fe35de98aae0013a15eb27294e24902beeda01daf4f9b404bd8600165bc  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/config.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:15:ba63cc5d4f4e68a0cdd82c985d4fd5989fe9cf4c3beefb94ef1643d4a83bb80e  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/db.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:16:9e3bfd6a9481768800897f4a6be27e68f27e10bec96d3dda567407443b03bc99  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/forum.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:17:5b61133d9b2a72a8e5b86c01627899f60c988dee52fc7fdcc7adb7f82ebe1d47  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/normalize.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:18:88b5d4874b865ebe82ece25448a55bd083f4fb95a2c203621d715b6f0f58df57  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/rules.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:19:4c400f907b0c8fd57a4959a2d3fbc83206fd577e4429b7947e372f15c1637c25  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/schema.sql","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:20:6710a6dae5c3889412c823af20a989d2f1f072dd03451c9b1e00b6078aab570d  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/webapp.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:21:3d7e4c0054a958c6f440ffc2ee112360e1d7a433d3371590deb7575f89323f3b  tasks/skladchik-moderator-v2-application-v1/assets/app/wsgi.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:22:f2f353dd56327395e03d26942deadf4987ac9b3a8a244dc87b3bddbbf9a301d9  tasks/skladchik-moderator-v2-application-v1/assets/pve03-app.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:23:04a441d36e41d30e1190dab7e71d3c05fb5733248ee7308f9b1b675abbf414b9  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-collector.service","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:24:fee9af8ac8ab3f875a2860178b1029a1bc2fa251bf6e42a021585e02eee90c17  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-collector.timer","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:25:d9e99cb8f07c328842f1eebc6d262dca623173cb9cfdd7e2afb4b279449a9519  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-competitor.service","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:26:37cd7bfe11a6c1cd70d5da7c62af19d7147e5f70a9641a0641cac8acbc709bb2  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-competitor.timer","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:27:9789f77fc9d6e246cacbc915b178ed2fedcf1367f7af8fe20a98881abe6597c5  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-rules.service","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:28:a56c7d0c1bef8917f2407cabc9e27d0461b19f5af2698e556365d00673a93180  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-rules.timer","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:29:e9cb92c0702ae26a0c6a063ffaaab0f1bafc08a82c05263509e112ff7847edae  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-web.service","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:30:6e7e7f45c756bec56a64321ebb6ca89d8f4edb8e070a57481e730e2c876deeeb  tasks/skladchik-moderator-v2-application-v1/phases/apply.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:31:d17e4d6f9e9eece7672bccd18dec0fb533810fafb469e0e2ca99753fa5fe4136  tasks/skladchik-moderator-v2-application-v1/phases/dry-run.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:32:8a39aef9926a6cf55c659937817bc5dc12657d5ef1f7edd549dc99530b88ade9  tasks/skladchik-moderator-v2-application-v1/phases/preflight.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:33:5157ec8da4bcfc0b88ccac54bed52a3ffeb676d5513cdb3f6b4ed5955658f76a  tasks/skladchik-moderator-v2-application-v1/phases/prepare.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:34:403263caebb4925ada3957e0dbc852cf1813ba4ceda3fb308c33b2b22107c955  tasks/skladchik-moderator-v2-application-v1/phases/rollback.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:35:11f128d5da0a7c1276b77e10400e825a267633828cd173c0d8e5582902d28443  tasks/skladchik-moderator-v2-application-v1/phases/seal.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:36:3fba9b905dccf09dff024684894443d3b670b973f67c9db7653efde0b1c42fe8  tasks/skladchik-moderator-v2-application-v1/phases/verify.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:37:b9b2aa5fa48836fecbec286136377b8d6af00383df9e1a97b5ba0833c4099d27  tasks/skladchik-moderator-v2-application-v1/task.json","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:38:4b4c8d38c0e6613ec6cf2c6aaf873c506fffe5fd400566255e2a77618da7bb90  tasks/skladchik-moderator-v2-application-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:39:0c23274ab9b0ea843595689536284c86bdc7746220ebb4f140ccd1fff2c752bd  tasks/skladchik-moderator-v2-application-v1/tools/test_contract.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:40:6f9b3c541c451c4b9c0d2d394931c1b7e868349bef3e53167160298df703f2f6  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/auth-selftest.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:41:25eaabbddc54235aaafd2f5829c7e8ed9d1defcf76b8327cf347aeefda823ae0  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/forum.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:42:c2cccab25c73ec554d1a51f9dccf32343b50f5ff3efc4d65c55361032f1a2c30  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/pve03-auth-classifier.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:43:5f6e75e0b38671c55129e2975c64ab8522197f997dae370e3f513628452f1783  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/apply.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:44:caec61da54d9c40bd7cfed623617002c06a18e9604195b6057eb9e4e9bbee294  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/dry-run.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:45:92ee9f19e3a83c1c244c033a277ed5ad312bd7396fd2b3fb9bdd4047aa847957  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/preflight.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:46:7c1ba5eb1e973ac5a2dd1651c89a05ba5a133f5bcf59ec216395887f9019ed7b  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/prepare.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:47:1c95a608369828b9da7c5d78fe630b5b4d947a799cbd22006a02be85686d5d75  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/rollback.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:48:2ab9124cc1428a68ca55c86fe6184f9fce8885dc353218a2caa2d8af742f0c89  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/seal.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:49:06e4185e2678a7e8a71514dd41b1845e84b1099f98003e234929aaa23d1c5d4a  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/verify.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:50:40ed940ba18618988294feede2a24d825a95c8a9ba84d5491f46664466be6b2e  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/task.json","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:51:3d0827c41d83923e0672d2d07f0502f42abc55b825f2f5e5c42dafa851c69419  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:52:49c5c42d757ee1e37123a5dc945d2a17631b74c394dbcd621e90ed7ad132cc72  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/tools/test_contract.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:53:011936d623941792240f8687443220e81357b68b17d419ebcdaa721d0473c63b  tasks/skladchik-moderator-v2-cookie-onboarding-v1/assets/edge-cookie-source.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:54:56a9ab7d9169987c3b8fae6de29e6a3adb4538e34664d1b77c8c6203a9003474  tasks/skladchik-moderator-v2-cookie-onboarding-v1/assets/pve03-cookie.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:55:fb70f92b602588b73eb7eec5816387669576b5de2e07b69ff90de328bef3026b  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/apply.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:56:1ed1ad4b17f96dee387b23989b3e3a974ed501cd5d694cade4d085d52dd295a1  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/dry-run.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:57:a839dd24e8b7c786b3130bd716841e0ced43c49ea1ab3314aebbeaca07dfd436  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/preflight.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:58:e377d14af824721cc1986889f1291da70b87901d1837769390d378f4d2fe5e13  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/prepare.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:59:014cf33ef917d193385449fc13201cefa84148608eb4fd6d3e5f30be06d1dd73  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/rollback.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:60:268b03a7b39225bfb2c97c4c87827c819e2ed727138b6158ff976469daf6887a  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/seal.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:61:6dafb047863c6df90898beeb99dd5ef04862afae3b8a3af57eb8290c671434a6  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/verify.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:62:feec58b4018f777a212520a795e7605455c6fb41da7a1792b60e1d57981c4689  tasks/skladchik-moderator-v2-cookie-onboarding-v1/task.json","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:63:4a8ae4ac4d749a4a7d10b8a21d2729dc2242ef4b0cd3b06f28ac89dd2bbff92c  tasks/skladchik-moderator-v2-cookie-onboarding-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:64:93cb00411e45d9bdd9cb035869fe2be230f6147e76a8898a36606c51d9bcb568  tasks/skladchik-moderator-v2-cookie-onboarding-v1/tools/test_contract.py","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:65:2ee3682cb57e7b6d04195a37b8f7acafde5cb2dc9ca28820e25c7143b3db4706  tasks/skladchik-moderator-v2-edge-egress-v1/assets/edge-egress.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:66:207793e2fa360abb88d535912d7d013af8bc822f4ffb1d8f55a3ea0967dc1ad6  tasks/skladchik-moderator-v2-edge-egress-v1/assets/pve03-egress.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:67:3c32c482e3232df8a2c4d25f553e8e7198c33a378e0600f53c01f71d14d9b3f6  tasks/skladchik-moderator-v2-edge-egress-v1/phases/apply.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:68:c51e41420b857f7d0ff2b8a16c8d0a339b4b942020d4ae59f80721e113e37eec  tasks/skladchik-moderator-v2-edge-egress-v1/phases/dry-run.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:69:d5e83720f2d842f4a1a2aba7ae4a55ce5494d16a43aa67f280d21c3cbed74d16  tasks/skladchik-moderator-v2-edge-egress-v1/phases/preflight.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:70:ee7ba739521639244e37ecf63d218bc18202701e53970f46eb987f7f3c6cb3b5  tasks/skladchik-moderator-v2-edge-egress-v1/phases/prepare.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:71:23aa44a61d9a6197ef236cc71b3f5eb4f9c38cdb24ae68eaa52113d34ac96ac0  tasks/skladchik-moderator-v2-edge-egress-v1/phases/rollback.sh","refs/heads/cr-2026-0066-legacy-backup-target-retirement:changes/CR-2026-0036/package.sha256:72:ef7485307bd7e9b49c9102268db8b729049226f631441362ad3c2c5227516c12  tasks/skladchik-moderator-v2-edge-egress-v1/phases/seal.sh"],"rc":0,"stderr_sha256":null,"stdout_sha256":"9989ff793d051a8863587f029c5c474bae7c794adc87d6e9e566a31f62e43b6c"}},"refs/heads/cr-2026-0070-backup-target-lifecycle-registry":{"diff_names":{"lines":["D\t.gitea/workflows/validate-kb.yml","M\tACTIVE_CHANGES.md","M\tAGENTS.md","M\tCURRENT_CONTEXT.md","D\tKB_START_HERE.md","M\tREADME.md","D\tchanges/CR-2026-0018/acceptance.json","D\tchanges/CR-2026-0018/caller-inventory-requirements.md","D\tchanges/CR-2026-0018/design.md","A\tchanges/CR-2026-0018/evidence.md","D\tchanges/CR-2026-0018/execution-contract.md","A\tchanges/CR-2026-0018/plan.json","D\tchanges/CR-2026-0018/plan.md","D\tchanges/CR-2026-0018/regression-cases-draft.json","D\tchanges/CR-2026-0018/request.json","D\tchanges/CR-2026-0018/review-decision.md","M\tchanges/CR-2026-0018/risk.md","M\tchanges/CR-2026-0018/rollback.md","A\tchanges/CR-2026-0018/task-package.sha256","D\tchanges/CR-2026-0018/task-reference.md","M\tchanges/CR-2026-0018/tests.md","D\tchanges/CR-2026-0018/threat-model.md","A\tchanges/CR-2026-0019/evidence.md","A\tchanges/CR-2026-0019/plan.json","A\tchanges/CR-2026-0019/risk.md","A\tchanges/CR-2026-0019/rollback.md","A\tchanges/CR-2026-0019/source-freeze.sha256","A\tchanges/CR-2026-0019/task-package.sha256","A\tchanges/CR-2026-0019/tests.md","A\tchanges/CR-2026-0026/design-package.sha256","A\tchanges/CR-2026-0026/discovery.md","A\tchanges/CR-2026-0026/implementation.md","A\tchanges/CR-2026-0026/plan.json","A\tchanges/CR-2026-0026/risk.md","A\tchanges/CR-2026-0026/rollback.md","A\tchanges/CR-2026-0026/source-provenance.tsv","A\tchanges/CR-2026-0026/task-package.sha256","A\tchanges/CR-2026-0026/tests.md","A\tchanges/CR-2026-0027/design-package.sha256","A\tchanges/CR-2026-0027/discovery.md","A\tchanges/CR-2026-0027/implementation.md","A\tchanges/CR-2026-0027/plan.json","A\tchanges/CR-2026-0027/risk.md","A\tchanges/CR-2026-0027/rollback.md","A\tchanges/CR-2026-0027/source-provenance.tsv","A\tchanges/CR-2026-0027/task-package.sha256","A\tchanges/CR-2026-0027/tests.md","A\tchanges/CR-2026-0028/design-package.sha256","A\tchanges/CR-2026-0028/discovery.md","A\tchanges/CR-2026-0028/implementation.md","A\tchanges/CR-2026-0028/plan.json","A\tchanges/CR-2026-0028/risk.md","A\tchanges/CR-2026-0028/rollback.md","A\tchanges/CR-2026-0028/source-provenance.tsv","A\tchanges/CR-2026-0028/task-package.sha256","A\tchanges/CR-2026-0028/tests.md","A\tchanges/CR-2026-0029/design-package.sha256","A\tchanges/CR-2026-0029/discovery.md","A\tchanges/CR-2026-0029/implementation.md","A\tchanges/CR-2026-0029/plan.json","A\tchanges/CR-2026-0029/risk.md","A\tchanges/CR-2026-0029/rollback.md","A\tchanges/CR-2026-0029/source-provenance.tsv","A\tchanges/CR-2026-0029/task-package.sha256","A\tchanges/CR-2026-0029/tests.md","A\tchanges/CR-2026-0030/design-package.sha256","A\tchanges/CR-2026-0030/discovery.md","A\tchanges/CR-2026-0030/implementation.md","A\tchanges/CR-2026-0030/plan.json","A\tchanges/CR-2026-0030/risk.md","A\tchanges/CR-2026-0030/rollback.md","A\tchanges/CR-2026-0030/source-provenance.tsv","A\tchanges/CR-2026-0030/task-package.sha256","A\tchanges/CR-2026-0030/tests.md","A\tchanges/CR-2026-0031/design-package.sha256","A\tchanges/CR-2026-0031/discovery.md","A\tchanges/CR-2026-0031/implementation.md","A\tchanges/CR-2026-0031/risk.md","A\tchanges/CR-2026-0031/source-provenance.tsv","A\tchanges/CR-2026-0031/task-package.sha256","A\tchanges/CR-2026-0031/tests.md","A\tchanges/CR-2026-0032/README.md","A\tchanges/CR-2026-0032/design-package.sha256","A\tchanges/CR-2026-0032/task-package.sha256","A\tchanges/CR-2026-0033/README.md","A\tchanges/CR-2026-0033/design-package.sha256","A\tchanges/CR-2026-0033/task-package.sha256","A\tchanges/CR-2026-0034/README.md","A\tchanges/CR-2026-0034/design-package.sha256","A\tchanges/CR-2026-0034/task-package.sha256","A\tchanges/CR-2026-0035/discovery.md","A\tchanges/CR-2026-0035/implementation.md","A\tchanges/CR-2026-0035/package.sha256","A\tchanges/CR-2026-0035/risk.md","A\tchanges/CR-2026-0035/source-provenance.tsv","A\tchanges/CR-2026-0035/tests.md","A\tchanges/CR-2026-0036/discovery.md","A\tchanges/CR-2026-0036/implementation.md","A\tchanges/CR-2026-0036/package.sha256","A\tchanges/CR-2026-0036/risk.md","A\tchanges/CR-2026-0036/source-provenance.tsv","A\tchanges/CR-2026-0036/tests.md","A\tchanges/CR-2026-0046/discovery.md","A\tchanges/CR-2026-0046/implementation.md","A\tchanges/CR-2026-0046/risk.md","A\tchanges/CR-2026-0046/source-provenance.tsv","A\tchanges/CR-2026-0046/task-package.sha256","A\tchanges/CR-2026-0046/tests.md","A\tchanges/CR-2026-0047/task-package.sha256","A\tchanges/CR-2026-0048/discovery.md","A\tchanges/CR-2026-0048/implementation.md","A\tchanges/CR-2026-0048/risk.md","A\tchanges/CR-2026-0048/source-provenance.tsv","A\tchanges/CR-2026-0048/task-package.sha256","A\tchanges/CR-2026-0048/tests.md","A\tchanges/CR-2026-0049/discovery.md","A\tchanges/CR-2026-0049/implementation.md","A\tchanges/CR-2026-0049/risk.md","A\tchanges/CR-2026-0049/source-provenance.tsv","A\tchanges/CR-2026-0049/task-package.sha256"],"rc":0,"stderr_sha256":null,"stdout_sha256":"4ab8dd56aa0daea12c6e08fea70070d993d1984ca1d9ec99b9a210bc995e0d0a"},"exists":true,"vm200":{"lines":["refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/discovery.md:3:- Existing `skladchik-moderator-assistant` is an unused MVP on pve01: one Python file, one rules JSON, SQLite analyses count 0.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/implementation.md:3:Task: `skladchik-moderator-ct200-infrastructure-v1`.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/implementation.md:5:The controlled apply creates CT200 on pve03 using the pinned Debian 13 template, 4 vCPU, 6144 MiB RAM, 1024 MiB swap, 40 GiB local-lvm rootfs, unprivileged mode and nesting. It proves boot and DNS, performs an initial vm200 cloud-quorum backup with restore-validation using the candidate worker before changing live backup runtime, then enrolls vm200 in the canonical VM queue/probe/worker/audit/retention runtime on pve01/pve02/pve03 as required.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:6:cf81f24981ad71f84840f0dc3f7c17d25716ae10d09432de023f2332e41b299c  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-audit","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:7:d5e70fca273e67ec272ea44f73558e28fb707902a09e96497a5fb7cecf4e3336  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-backup-retention-gc","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:8:bd6257397c6ea910df2ea0dd57252b33bccd0bbd965175840486dfe5e079bf96  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-freshness-probe","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:9:91bdd116be865560a38105dffbd1a66d687232035e2359e4a5be4d225e9c61d1  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-node-worker","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:10:6994b8750bb3ced52497699738199a77ba9ac28c51ad23ad6eb3f3576aebbef2  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/homelab-vm-cloud-quorum-queue","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:11:43ff350cd9d98bb521bebde51389ff3b90d3dc4a742b0084586ffd0a1b74f47e  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/pve03-ct200.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:12:019a64e294d164e94cb429c63590e2f7e5e607516bdd4e0dd9cf81d7b729b1e9  tasks/skladchik-moderator-ct200-infrastructure-v1/assets/remote-runtime.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:13:7a230f0f29bcbe29c870472ccb8751b04d9f5e6fdd72af226c83ed3ca417f0e0  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/apply.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:14:4b8798cb5035bb026c1e04a655866b5cfd6772ae76ce747b4b1778ed28964886  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/dry-run.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:15:f12792c78635913ef671cf1d0593aed76599617669e75a90cd3462c611df4c74  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/preflight.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:16:3e12eacd397f5a8c10969d20990353993894aa0c6ed94c696724e9a1d3956055  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/prepare.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:17:1b24b43a7167edd0df215951c1c59885a18fffbfe4318939fd5a3a7eafeb181e  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/rollback.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:18:c34680c51e83699b9e93e8e2720cce06d90dc2b94e4adbb92548d82368b448eb  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/seal.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:19:2730fb3920c07b79a59ce32b0bb8b5d0f5b6569b3430565be4c2da84188ba73c  tasks/skladchik-moderator-ct200-infrastructure-v1/phases/verify.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:20:c9ef2aae496c76e4dc955f2eae91eb472c4abdbd83ca6b9019a02fb17cf14d1c  tasks/skladchik-moderator-ct200-infrastructure-v1/task.json","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:21:980b88d51feb9115695985870af4b48af884876de8d23ee6678c633ae00beb95  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/package.sha256:22:974c6181e543c74ea2bb1a1a392960b98aba8bb1fb8ff111f15fc8d6bbc6d06e  tasks/skladchik-moderator-ct200-infrastructure-v1/tools/test_contract.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/risk.md:11:- first vm200 SEALED backup and restore evidence before live enrollment;","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/risk.md:13:- rollback preserves any already sealed vm200 cloud generation/evidence rather than deleting recovery data;","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/tests.md:14:- Regression: retention candidate requires SSH stdin isolation and live plan must emit vm200 after hotfix.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0035/tests.md:15:- Live hotfix proof requires read-only candidate/post-install retention plans to include remote-owned VMIDs and `KEEP|logical=vm200|...|reason=POLICY_NEWEST_2`.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:12:- Recovery after the initial external-network timeout uses a dedicated `skladchik-moderator-v2-edge-egress-v1` task: CT200 alone uses edge-vm `[PRIVATE_IP]` as its default gateway; edge-vm NATs only `[PRIVATE_IP]/32` into its already-existing NetBird `wt0` default exit (table 7120). No NetBird management policy is changed.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:26:Authenticated section evidence on 2026-08-12 showed 107 `discussionListItem` nodes, 106 `PreviewTooltip` markers and 517 root-relative `threads/...` hrefs. `skladchik-moderator-v2-xf1-parser-hotfix-v1` overlays only `forum.py` and `ads.py`, preserving XF2 support while adding XF1 listing/topic/message/search parsing and root-relative URL resolution. Cookie onboarding is fail-closed on the parser hotfix seal and exact installed module SHA values.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:42:The first controlled cookie apply proved the edge-vm source jar before mutation, installed it, then failed only at the v2 `auth-check`; the apply error path removed the CT200 cookie, disabled collector/competitor timers, and removed transient pve03 staging. The divergence was between two authentication classifiers: edge-vm proves the moderator session by authenticated XenForo 1 `discussionListItem` rows, while v2 still downgraded the same cookie-backed section using a text-only login heuristic. `skladchik-moderator-v2-auth-classification-hotfix-v1` preserves the sealed XF1 parser and changes only section authentication classification: a cookie-backed section that parses canonical topic rows is positive auth evidence. This is bounded by the already-observed public response yielding zero rows","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:54:The authenticated bootstrap reached 104 listed topics and 40 detailed topics but produced zero analyses because every analyzed detail failed at `stage_history.stage = %s` with PostgreSQL `text = bytea`. The application connection inherited `SQL_ASCII`, so Psycopg returned text values as Python bytes and adapted the fetched stage back as `bytea` on the next parameterized query. The fix is at the connection boundary, not an SQL cast: `skladchik-moderator-v2-db-text-encoding-hotfix-v1` pins Psycopg `client_encoding=UTF8`, proves the baseline bytes failure against existing data, then performs a pre-mutation UTF8 probe across every existing app-facing text column and the exact formerly failing stage-history query; apply/verify repeat that proof through the installed module. No schema or data rew","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:58:The post-cookie health failure after successful authenticated collection (104 listed topics, 17 analyses in the triggering run; 65 analyses persisted overall) was isolated to rule state. The formatting-rule fetch inherited the moderator cookie and was redirected to XenForo `/login/two-step`, creating a non-approved rule-source revision. Rule pages are public policy sources, so `skladchik-moderator-v2-rules-public-sync-hotfix-v1` fetches them through an independent cookie-free Requests session and requires the redirected final URL to preserve the expected rule thread id. Before mutation, the live dry-run requires each current public content hash to already exist as an explicitly approved historical source; a genuinely new rule revision therefore still stops for manual review and is never aut","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:62:The final cookie bootstrap exposed a collector-only SQL defect after all 104 section topics had already been detailed: `global_search_hits` used `ON CONFLICT DO UPDATE` without the unique-key inference target, so PostgreSQL rejected every whole-site duplicate-search upsert for the remaining four topics. Because detail state is committed before duplicate search and analysis, those topics then became ineligible for another detail fetch for two days. `skladchik-moderator-v2-collector-resume-hotfix-v1` fixes the upsert against the existing `UNIQUE(source_topic_id,query_kind,query_text,hit_url)` key and adds a cached-detail analysis backlog that retries topics whose latest committed detail has no analysis at or after that detail timestamp. Its dry-run executes the corrected upsert twice inside a","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:70:After cookie onboarding is SEALED and current v2 health/timers are re-proven, `skladchik-moderator-v2-old-mvp-retirement-v1` retires only the legacy pve01 operational service. The task pins the exact legacy unit/app/rules bytes and version, captures root-only rollback copies, disables/stops the service, removes `/etc/systemd/system/skladchik-moderator-assistant.service` and `/opt/skladchik-moderator-assistant`, and preserves `/var/lib/skladchik-moderator-assistant` unchanged as inert historical state. Any apply/verify failure before seal restores the exact legacy unit/application and service state. Retirement does not touch CT200, complaints, forum state, or v2 data.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:74:The final retirement task does not delete `/opt/skladchik-moderator-assistant`. The existing app-cloud backup scheduler still schedules `skladchik-moderator-assistant`, and its worker captures `/var/lib/skladchik-moderator-assistant/state.sqlite3` plus `/opt/skladchik-moderator-assistant`. Deleting the legacy app directory would therefore break the next scheduled app backup. Retirement is corrected to disable/stop the old service and remove only its systemd unit/endpoint while preserving the exact legacy app and StateDirectory as inert, byte-pinned historical payload. The task read-only proves the existing queue/audit/worker backup contract before and after retirement; backup runtime itself is not modified.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/implementation.md:76:The old MVP unit uses `DynamicUser=yes` with `StateDirectory=skladchik-moderator-assistant`. Retirement accepts the normal directory layout or the exact systemd-managed `/var/lib/skladchik-moderator-assistant` symlink resolving to `/var/lib/private/skladchik-moderator-assistant`; the SQLite file itself must remain a regular non-symlink file.","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:6:4e119cef286d48ac4675235a82309e0c1087316bcada25bc6f8f43aea665e1dd  tasks/skladchik-moderator-v2-application-v1/assets/app-payload.tar.gz","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:7:cf37824d4bb8d0d412d505cfeca33c81ddc37ac31ceedb6b131181653895fad1  tasks/skladchik-moderator-v2-application-v1/assets/app/config.json","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:8:761de78bd15049d408ed2f109a0fcd87e453d702defdf0e8d1547e1b35a55974  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/__init__.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:9:3e90e6c148a2b7ba52072be35280130f00fb966cfb94b76908fbd2eecd965b35  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/ads.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:10:5664ff8e9d45381a0c08a71a794060e60db8f523bd32911b390d28014066fc6c  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/analyzer.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:11:56f52f89fff1468d5e13da29c3c10cf60bc0aea06d71be871dcfc805aec23b60  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/cli.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:12:122e44d95edfc1c205cdee589ab83a9ccbce724a7951b569995e29171d4cb393  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/collector.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:13:0fd4e356a70e56f7293492b5f3d7677cc1a31156ba1964b3997c8852483edf63  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/competitors.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:14:bb207fe35de98aae0013a15eb27294e24902beeda01daf4f9b404bd8600165bc  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/config.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:15:ba63cc5d4f4e68a0cdd82c985d4fd5989fe9cf4c3beefb94ef1643d4a83bb80e  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/db.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:16:9e3bfd6a9481768800897f4a6be27e68f27e10bec96d3dda567407443b03bc99  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/forum.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:17:5b61133d9b2a72a8e5b86c01627899f60c988dee52fc7fdcc7adb7f82ebe1d47  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/normalize.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:18:88b5d4874b865ebe82ece25448a55bd083f4fb95a2c203621d715b6f0f58df57  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/rules.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:19:4c400f907b0c8fd57a4959a2d3fbc83206fd577e4429b7947e372f15c1637c25  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/schema.sql","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:20:6710a6dae5c3889412c823af20a989d2f1f072dd03451c9b1e00b6078aab570d  tasks/skladchik-moderator-v2-application-v1/assets/app/skladchik_moderator/webapp.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:21:3d7e4c0054a958c6f440ffc2ee112360e1d7a433d3371590deb7575f89323f3b  tasks/skladchik-moderator-v2-application-v1/assets/app/wsgi.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:22:f2f353dd56327395e03d26942deadf4987ac9b3a8a244dc87b3bddbbf9a301d9  tasks/skladchik-moderator-v2-application-v1/assets/pve03-app.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:23:04a441d36e41d30e1190dab7e71d3c05fb5733248ee7308f9b1b675abbf414b9  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-collector.service","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:24:fee9af8ac8ab3f875a2860178b1029a1bc2fa251bf6e42a021585e02eee90c17  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-collector.timer","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:25:d9e99cb8f07c328842f1eebc6d262dca623173cb9cfdd7e2afb4b279449a9519  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-competitor.service","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:26:37cd7bfe11a6c1cd70d5da7c62af19d7147e5f70a9641a0641cac8acbc709bb2  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-competitor.timer","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:27:9789f77fc9d6e246cacbc915b178ed2fedcf1367f7af8fe20a98881abe6597c5  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-rules.service","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:28:a56c7d0c1bef8917f2407cabc9e27d0461b19f5af2698e556365d00673a93180  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-rules.timer","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:29:e9cb92c0702ae26a0c6a063ffaaab0f1bafc08a82c05263509e112ff7847edae  tasks/skladchik-moderator-v2-application-v1/assets/systemd/skladchik-moderator-v2-web.service","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:30:6e7e7f45c756bec56a64321ebb6ca89d8f4edb8e070a57481e730e2c876deeeb  tasks/skladchik-moderator-v2-application-v1/phases/apply.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:31:d17e4d6f9e9eece7672bccd18dec0fb533810fafb469e0e2ca99753fa5fe4136  tasks/skladchik-moderator-v2-application-v1/phases/dry-run.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:32:8a39aef9926a6cf55c659937817bc5dc12657d5ef1f7edd549dc99530b88ade9  tasks/skladchik-moderator-v2-application-v1/phases/preflight.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:33:5157ec8da4bcfc0b88ccac54bed52a3ffeb676d5513cdb3f6b4ed5955658f76a  tasks/skladchik-moderator-v2-application-v1/phases/prepare.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:34:403263caebb4925ada3957e0dbc852cf1813ba4ceda3fb308c33b2b22107c955  tasks/skladchik-moderator-v2-application-v1/phases/rollback.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:35:11f128d5da0a7c1276b77e10400e825a267633828cd173c0d8e5582902d28443  tasks/skladchik-moderator-v2-application-v1/phases/seal.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:36:3fba9b905dccf09dff024684894443d3b670b973f67c9db7653efde0b1c42fe8  tasks/skladchik-moderator-v2-application-v1/phases/verify.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:37:b9b2aa5fa48836fecbec286136377b8d6af00383df9e1a97b5ba0833c4099d27  tasks/skladchik-moderator-v2-application-v1/task.json","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:38:4b4c8d38c0e6613ec6cf2c6aaf873c506fffe5fd400566255e2a77618da7bb90  tasks/skladchik-moderator-v2-application-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:39:0c23274ab9b0ea843595689536284c86bdc7746220ebb4f140ccd1fff2c752bd  tasks/skladchik-moderator-v2-application-v1/tools/test_contract.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:40:6f9b3c541c451c4b9c0d2d394931c1b7e868349bef3e53167160298df703f2f6  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/auth-selftest.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:41:25eaabbddc54235aaafd2f5829c7e8ed9d1defcf76b8327cf347aeefda823ae0  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/forum.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:42:c2cccab25c73ec554d1a51f9dccf32343b50f5ff3efc4d65c55361032f1a2c30  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/assets/pve03-auth-classifier.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:43:5f6e75e0b38671c55129e2975c64ab8522197f997dae370e3f513628452f1783  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/apply.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:44:caec61da54d9c40bd7cfed623617002c06a18e9604195b6057eb9e4e9bbee294  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/dry-run.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:45:92ee9f19e3a83c1c244c033a277ed5ad312bd7396fd2b3fb9bdd4047aa847957  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/preflight.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:46:7c1ba5eb1e973ac5a2dd1651c89a05ba5a133f5bcf59ec216395887f9019ed7b  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/prepare.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:47:1c95a608369828b9da7c5d78fe630b5b4d947a799cbd22006a02be85686d5d75  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/rollback.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:48:2ab9124cc1428a68ca55c86fe6184f9fce8885dc353218a2caa2d8af742f0c89  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/seal.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:49:06e4185e2678a7e8a71514dd41b1845e84b1099f98003e234929aaa23d1c5d4a  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/phases/verify.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:50:40ed940ba18618988294feede2a24d825a95c8a9ba84d5491f46664466be6b2e  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/task.json","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:51:3d0827c41d83923e0672d2d07f0502f42abc55b825f2f5e5c42dafa851c69419  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:52:49c5c42d757ee1e37123a5dc945d2a17631b74c394dbcd621e90ed7ad132cc72  tasks/skladchik-moderator-v2-auth-classification-hotfix-v1/tools/test_contract.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:53:011936d623941792240f8687443220e81357b68b17d419ebcdaa721d0473c63b  tasks/skladchik-moderator-v2-cookie-onboarding-v1/assets/edge-cookie-source.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:54:56a9ab7d9169987c3b8fae6de29e6a3adb4538e34664d1b77c8c6203a9003474  tasks/skladchik-moderator-v2-cookie-onboarding-v1/assets/pve03-cookie.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:55:fb70f92b602588b73eb7eec5816387669576b5de2e07b69ff90de328bef3026b  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/apply.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:56:1ed1ad4b17f96dee387b23989b3e3a974ed501cd5d694cade4d085d52dd295a1  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/dry-run.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:57:a839dd24e8b7c786b3130bd716841e0ced43c49ea1ab3314aebbeaca07dfd436  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/preflight.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:58:e377d14af824721cc1986889f1291da70b87901d1837769390d378f4d2fe5e13  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/prepare.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:59:014cf33ef917d193385449fc13201cefa84148608eb4fd6d3e5f30be06d1dd73  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/rollback.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:60:268b03a7b39225bfb2c97c4c87827c819e2ed727138b6158ff976469daf6887a  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/seal.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:61:6dafb047863c6df90898beeb99dd5ef04862afae3b8a3af57eb8290c671434a6  tasks/skladchik-moderator-v2-cookie-onboarding-v1/phases/verify.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:62:feec58b4018f777a212520a795e7605455c6fb41da7a1792b60e1d57981c4689  tasks/skladchik-moderator-v2-cookie-onboarding-v1/task.json","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:63:4a8ae4ac4d749a4a7d10b8a21d2729dc2242ef4b0cd3b06f28ac89dd2bbff92c  tasks/skladchik-moderator-v2-cookie-onboarding-v1/tools/runtime-lib.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:64:93cb00411e45d9bdd9cb035869fe2be230f6147e76a8898a36606c51d9bcb568  tasks/skladchik-moderator-v2-cookie-onboarding-v1/tools/test_contract.py","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:65:2ee3682cb57e7b6d04195a37b8f7acafde5cb2dc9ca28820e25c7143b3db4706  tasks/skladchik-moderator-v2-edge-egress-v1/assets/edge-egress.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:66:207793e2fa360abb88d535912d7d013af8bc822f4ffb1d8f55a3ea0967dc1ad6  tasks/skladchik-moderator-v2-edge-egress-v1/assets/pve03-egress.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:67:3c32c482e3232df8a2c4d25f553e8e7198c33a378e0600f53c01f71d14d9b3f6  tasks/skladchik-moderator-v2-edge-egress-v1/phases/apply.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:68:c51e41420b857f7d0ff2b8a16c8d0a339b4b942020d4ae59f80721e113e37eec  tasks/skladchik-moderator-v2-edge-egress-v1/phases/dry-run.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:69:d5e83720f2d842f4a1a2aba7ae4a55ce5494d16a43aa67f280d21c3cbed74d16  tasks/skladchik-moderator-v2-edge-egress-v1/phases/preflight.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:70:ee7ba739521639244e37ecf63d218bc18202701e53970f46eb987f7f3c6cb3b5  tasks/skladchik-moderator-v2-edge-egress-v1/phases/prepare.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:71:23aa44a61d9a6197ef236cc71b3f5eb4f9c38cdb24ae68eaa52113d34ac96ac0  tasks/skladchik-moderator-v2-edge-egress-v1/phases/rollback.sh","refs/heads/cr-2026-0070-backup-target-lifecycle-registry:changes/CR-2026-0036/package.sha256:72:ef7485307bd7e9b49c9102268db8b729049226f631441362ad3c2c5227516c12  tasks/skladchik-moderator-v2-edge-egress-v1/phases/seal.sh"],"rc":0,"stderr_sha256":null,"stdout_sha256":"7fd8c45be9f29ec20392475bb0f6d6e2fe4e944bfd3b954b363ede77248b3bb6"}}},"status":{"lines":[],"rc":0,"stderr_sha256":null,"stdout_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}}
PVE_ACTIVE_INVENTORY={"rc":0,"rows":[{"name":"dns1","node":"pve01","status":"running","type":"lxc","vmid":110},{"name":"dns2","node":"pve02","status":"running","type":"lxc","vmid":111},{"name":"unbound1","node":"pve01","status":"running","type":"lxc","vmid":112},{"name":"unbound2","node":"pve02","status":"running","type":"lxc","vmid":113},{"name":"edge-vm","node":"pve03","status":"running","type":"qemu","vmid":130},{"name":"snikket","node":"pve01","status":"running","type":"qemu","vmid":150},{"name":"forum-prod","node":"pve02","status":"running","type":"qemu","vmid":160},{"name":"core-apps","node":"pve01","status":"running","type":"qemu","vmid":170},{"name":"monitoring","node":"pve01","status":"running","type":"qemu","vmid":171},{"name":"homelab-ops-worker","node":"pve03","status":"running","type":"qemu","vmid":190},{"name":"newfi-prod","node":"pve01","status":"running","type":"qemu","vmid":210},{"name":"newfi-staging","node":"pve03","status":"running","type":"qemu","vmid":211},{"name":"edge-cold-standby","node":"pve02","status":"stopped","type":"qemu","vmid":9130}],"stderr_sha256":null}
STATUS=OK
CHANGES_MADE=false
HOMELAB_RESULT_CONTRACT={"changes_made":false,"command_id":"SUPPORT-260916-INFRA-DR-BACKUPV2-LEGACY-PVE-RETENTION-SOURCE-CAPTURE-489R1","rollback_restored":null,"rollback_started":false,"status":"OK","version":1}

OUTPUT_END
CHAT_OUTPUT_END
