#!/usr/bin/env bash # v0.2.0 n=60 harness on a CUDA GPU host. Runs the decisive cells sequentially: # 1. v02_e6_plain — full v0.2 ensemble, M4 feature-target ON (max transfer) # 2. v02_e6_noM4 — same, M4 feature-target OFF (ablation: does steering earn its keep?) # 3. v02_e6_perc — M4 ON + LPIPS/DCT perceptual budget (stealth arm) # Each writes runs//{adv,results.json}. Cross-arch held-out (dinov2 SSL + # internvit VLM) is scored via M4 centroids, so held-out flips mean cross-architecture transfer. set -u cd ~/workspace/veil-pgd . .venv/bin/activate export HF_HOME=~/workspace/hf-cache export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True COMMON="--manifest examples/testset60.csv --images examples/testset60 --train v0.2 \ --steps 120 --eps 6 --subset 6 --grad-norm --max-per-family 2 --min-feature 1 --metrics" echo "=== [$(date +%H:%M:%S)] CELL 1/3 v02_e6_plain (M4 ON) ===" python -u -m ensemble.run_attack $COMMON --out runs/v02_e6_plain echo "=== [$(date +%H:%M:%S)] CELL 2/3 v02_e6_noM4 (M4 OFF ablation) ===" python -u -m ensemble.run_attack $COMMON --out runs/v02_e6_noM4 --no-feature-target echo "=== [$(date +%H:%M:%S)] CELL 3/3 v02_e6_perc (M4 ON + perceptual) ===" python -u -m ensemble.run_attack $COMMON --out runs/v02_e6_perc \ --lpips-weight 0.3 --lpips-tau 0.08 --dct-keep 0.6 echo "=== [$(date +%H:%M:%S)] ALL CELLS DONE ==="