import datetime, json, os, shutil, stat, subprocess
from pathlib import Path
ROOT=Path('/home/reavus/projects/spt-core/spt-core')
PROOF=ROOT/'.spt/preserved/304-handoff/consumer-linux-7890ead3'
TARGETS=[ROOT/'.worktrees/consumer-linux-49a08a07/target',ROOT/'.worktrees/consumer-linux-S2-527cd8e8/target',ROOT/'.worktrees/consumer-linux-7890ead3/target']
ENV={k:v for k,v in os.environ.items() if not k.startswith(('OWL_','SPT_'))}
def utc(): return datetime.datetime.now(datetime.timezone.utc).isoformat()
def inside(path,target):
    return path==str(target) or path.startswith(str(target)+'/')
report={'start_utc':utc(),'free_bytes_before':shutil.disk_usage(ROOT).free,'scope':'Read-only classification of two explicitly closed own targets and the released VOID partial7890ead3 target; no deletion, release, claim or producer. Inbound symlink scope: all /home/reavus, no symlink traversal. Linux has symlinks, not Windows reparse points. Process scope: readable /proc exe/cwd/root/fd/map_files/maps.','targets':[],'scan_errors':[],'inbound_links':[],'process_references':[],'unreadable_processes':[]}
inodes={}
for target in TARGETS:
    st=target.lstat()
    row={'path':str(target),'resolved':str(target.resolve()),'is_symlink':target.is_symlink(),'is_real_directory':stat.S_ISDIR(st.st_mode),'device':st.st_dev,'inode':st.st_ino,'pool_record':json.loads((target/'POOL-OWNER.json').read_text()),'outbound_links':[],'files':0,'apparent_bytes':0,'allocated_bytes_unique':0,'shared_hardlink_allocated_bytes':0}
    assert row['is_real_directory'] and not row['is_symlink'] and row['resolved']==str(target)
    row['source_sha']=subprocess.check_output(['git','rev-parse','HEAD'],cwd=target.parent,env=ENV,text=True).strip()
    for dirpath,dirs,files in os.walk(target,followlinks=False):
        for name in dirs+files:
            p=Path(dirpath)/name
            try:
                s=p.lstat()
                if stat.S_ISLNK(s.st_mode): row['outbound_links'].append({'path':str(p),'link_text':os.readlink(p),'resolved':str(p.resolve()),'outside_target':not inside(str(p.resolve()),target)})
                key=(s.st_dev,s.st_ino)
                inode=inodes.setdefault(key,{'blocks':s.st_blocks*512,'nlink':s.st_nlink,'paths':[],'regular':stat.S_ISREG(s.st_mode)})
                inode['paths'].append(str(p))
                row['files']+=1
                row['apparent_bytes']+=s.st_size
            except OSError as e: report['scan_errors'].append({'path':str(p),'error':str(e)})
    report['targets'].append(row)
for inode in inodes.values():
    shared=inode['regular'] and inode['nlink']>len(inode['paths'])
    owner=next(row for row in report['targets'] if inside(inode['paths'][0],row['path']))
    owner['allocated_bytes_unique']+=inode['blocks']
    if shared: owner['shared_hardlink_allocated_bytes']+=inode['blocks']
for row in report['targets']:
    row['measured_recoverable_file_bytes']=row['allocated_bytes_unique']-row['shared_hardlink_allocated_bytes']
def walk_error(e): report['scan_errors'].append({'path':e.filename,'error':str(e)})
for dirpath,dirs,files in os.walk('/home/reavus',followlinks=False,onerror=walk_error):
    for name in dirs+files:
        p=Path(dirpath)/name
        if p.is_symlink():
            try:
                resolved=str(p.resolve())
                matches=[str(t) for t in TARGETS if inside(resolved,t)]
                if matches and not any(inside(str(p),t) for t in TARGETS): report['inbound_links'].append({'path':str(p),'link_text':os.readlink(p),'resolved':resolved,'targets':matches})
            except (OSError,RuntimeError) as e: report['scan_errors'].append({'path':str(p),'error':str(e)})
for p in Path('/proc').iterdir():
    if not p.name.isdigit(): continue
    refs=[]
    denied=[]
    for name in ('exe','cwd','root'):
        try:
            value=os.readlink(p/name)
            if any(inside(value.removesuffix(' (deleted)'),t) for t in TARGETS): refs.append({'kind':name,'path':value})
        except PermissionError: denied.append(name)
        except OSError: pass
    for name in ('fd','map_files'):
        try:
            for f in (p/name).iterdir():
                try:
                    value=os.readlink(f)
                    if any(inside(value.removesuffix(' (deleted)'),t) for t in TARGETS): refs.append({'kind':name,'fd':f.name,'path':value})
                except PermissionError: denied.append(name+'/'+f.name)
                except OSError: pass
        except PermissionError: denied.append(name)
        except OSError: pass
    try:
        for line in (p/'maps').read_text().splitlines():
            if any(str(t)+'/' in line for t in TARGETS): refs.append({'kind':'maps','line':line})
    except PermissionError: denied.append('maps')
    except OSError: pass
    if refs: report['process_references'].append({'pid':int(p.name),'references':refs})
    if denied: report['unreadable_processes'].append({'pid':int(p.name),'items':denied})
report['end_utc']=utc()
report['free_bytes_after']=shutil.disk_usage(ROOT).free
report['measured_recoverable_file_bytes']=sum(row['measured_recoverable_file_bytes'] for row in report['targets'])
(PROOF/'closed-target-classification.json').write_text(json.dumps(report,indent=2)+'\n')
print(json.dumps(report))
