"""Explicitly resume the user-requested backup and verified workstation transfer. This script connects to the permanent test stand. Run only at the user's request. Does not launch training, alter drivers, remove runs, or overwrite original KNP code. """ from datetime import datetime, timezone import hashlib import json from pathlib import Path import subprocess import sys import tarfile ROOT = Path(__file__).resolve().parent STATE = ROOT / 'handoff-state' HOST = 'int@10.9.8.230' KEY = str(Path.home() / '.ssh/id_ed25519_snw') SSH = ['ssh', '-i', KEY, '-o', 'IdentitiesOnly=yes', '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=15', '-o', 'ServerAliveCountMax=2', HOST] def manifest(): excluded = {'SHA256SUMS', 'preservation-manifest.json', 'preservation-status.json'} rows = [] for path in sorted(ROOT.rglob('*')): if not path.is_file() or '__pycache__' in path.parts or path.name.endswith('.part'): continue relative = path.relative_to(ROOT).as_posix() if relative in excluded: continue digest = hashlib.sha256() with path.open('rb') as stream: for block in iter(lambda: stream.read(1024 * 1024), b''): digest.update(block) rows.append({'path': relative, 'bytes': path.stat().st_size, 'sha256': digest.hexdigest()}) (ROOT / 'preservation-manifest.json').write_text(json.dumps({'files': rows}, indent=2) + '\n') (ROOT / 'SHA256SUMS').write_text(''.join(f"{r['sha256']} {r['path']}\n" for r in rows)) return len(rows) def status(success, detail): (ROOT / 'preservation-status.json').write_text(json.dumps({ 'updated_utc': datetime.now(timezone.utc).isoformat(), 'remote_verified': success, 'detail': detail, 'destination': HOST + ':/mnt/c/KNP/cats-dogs', }, ensure_ascii=False, indent=2) + '\n') def capture(name, command): result = subprocess.run(SSH + [command], capture_output=True, check=True) (STATE / name).write_bytes(result.stdout) def archive(name, command): path = STATE / name temporary = path.with_suffix(path.suffix + '.part') try: with temporary.open('wb') as output: subprocess.run(SSH + [command], stdout=output, check=True) with tarfile.open(temporary, 'r:gz') as saved: for _ in saved: pass temporary.replace(path) finally: temporary.unlink(missing_ok=True) def main(): STATE.mkdir(exist_ok=True) if '--local-manifest-only' in sys.argv: print('Local files hashed:', manifest()) return status(False, 'Backup/transfer in progress; no success claimed yet') try: subprocess.run(SSH + ['true'], check=True) commands = { 'remote-inventory.txt': 'date -u; uname -a; ls -la /mnt/c/KNP; ls -la /mnt/c/KNP/cats-dogs; find /home/int/run/cats-dogs -maxdepth 2 -type f; ps -eo pid,etime,args | grep -E "cats_dogs|http.server|nvcc|build_fast|build_tuned" | grep -v grep || true', 'original-knp-status.txt': 'git -C /mnt/c/KNP/examples rev-parse HEAD; git -C /mnt/c/KNP/examples status --short', 'original-knp-changes.patch': 'git -C /mnt/c/KNP/examples diff --binary', 'visualizer-status.txt': 'git -C /mnt/c/KNP/viz rev-parse HEAD; git -C /mnt/c/KNP/viz status --short', 'visualizer-changes.patch': 'git -C /mnt/c/KNP/viz diff --binary', 'compiler-flags.txt': 'cat /home/int/knp-build/knp/backends/cpu/cpu-single-threaded-backend/CMakeFiles/knp-cpu-single-threaded-backend.dir/flags.make /home/int/knp-build/knp/backends/cpu/cpu-single-threaded-backend/CMakeFiles/knp-cpu-single-threaded-backend.dir/link.txt; /usr/bin/c++ --version; /home/int/cuda-12.9/bin/nvcc --version; /usr/lib/wsl/lib/nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader', } for name, command in commands.items(): capture(name, command) print('Captured state', flush=True) # First deliver the existing local context, even if a later full backup fails. manifest() transport = 'ssh -i ' + KEY + ' -o IdentitiesOnly=yes -o BatchMode=yes -o ConnectTimeout=10' def upload(): available = subprocess.run(SSH + ['command -v rsync'], capture_output=True) if available.returncode == 0: subprocess.run(['rsync', '-a', '--exclude=__pycache__', '--exclude=*.part', '-e', transport, str(ROOT) + '/', HOST + ':/mnt/c/KNP/cats-dogs/'], check=True) else: pack = subprocess.Popen(['tar', '--exclude=__pycache__', '--exclude=*.part', '-cf', '-', '-C', str(ROOT), '.'], stdout=subprocess.PIPE) try: subprocess.run(SSH + ['mkdir -p /mnt/c/KNP/cats-dogs && tar -xf - -C /mnt/c/KNP/cats-dogs'], stdin=pack.stdout, check=True) finally: pack.stdout.close() result = pack.wait() if result: raise RuntimeError(f'Upload tar exited {result}') subprocess.run(SSH + ['cp /mnt/c/KNP/cats-dogs/HANDOFF.md /mnt/c/KNP/HANDOFF-2026-10-14.md && ' 'cd /mnt/c/KNP/cats-dogs && sha256sum -c SHA256SUMS >/tmp/knp-handoff-check.log'], check=True) upload() print('Existing local context delivered and verified', flush=True) archive('remote-runtime.tar.gz', 'tar -czf - -C /home/int/run cats-dogs') archive('prior-context-and-source.tar.gz', 'tar -czf - -C / mnt/c/KNP/cats-dogs/source mnt/c/KNP/viz/altai_viz.html ' 'mnt/c/KNP/viz/app.html mnt/c/KNP/Отчёт_MNIST_точность.md ' 'mnt/c/KNP/Отчёт_altai.md mnt/c/KNP/Отчёт_колонки_altai.md ' 'mnt/c/KNP/Отчёт_размер_колонки_и_одежда.md ' 'home/int/.claude/projects/-mnt-c-knp/memory ' 'home/int/.claude/projects/-mnt-c-KNP/memory') print('Archives validated; local files hashed:', manifest(), flush=True) upload() status(True, 'Runtime/context archives validated, files transferred, remote SHA256SUMS passed') subprocess.run(['scp', '-i', KEY, '-o', 'IdentitiesOnly=yes', '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10', str(ROOT / 'preservation-status.json'), HOST + ':/mnt/c/KNP/cats-dogs/preservation-status.json'], check=True) print('Verified workstation copy: /mnt/c/KNP/HANDOFF-2026-10-14.md') except Exception as error: status(False, str(error)) manifest() raise if __name__ == '__main__': main()