#!/usr/bin/env bash
set -euo pipefail
umask 077
E="/home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-certification-deployment-6aaef77de87489c3be493978645781b24b55ab07513ff1f880164741d0bd3c73-st_01a00b39"
C="/home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-inode-test-fix-successor-6aaef77de87489c3be493978645781b24b55ab07513ff1f880164741d0bd3c73"
R=/home/cube/projects/richard/hermes-agent;P=/home/cube/.hermes/profiles/dualcoachtest;S="$P/workspace/checkin_cli";PY="$R/.venv/bin/python";TPY=/home/cube/miniconda3/bin/python;W="$C/artifacts/physique_checkin_cli-0.1.0-py3-none-any.whl";D=6aaef77de87489c3be493978645781b24b55ab07513ff1f880164741d0bd3c73
mkdir -p "$E/artifacts" "$E/receipts";chmod 700 "$E" "$E/artifacts" "$E/receipts"
record(){ local n="$1";shift;local o="$E/artifacts/$n" s e rc;mkdir -p "$o";chmod 700 "$o";printf '%q ' "$@">"$o/command.txt";echo>>"$o/command.txt";env -0|sort -z>"$o/launcher-environment.nul";printf '077\n'>"$o/umask.txt";date -u +%Y-%m-%dT%H:%M:%S.%NZ>"$o/started-at-utc.txt";s=$(date +%s%N);set +e;"$@">"$o/stdout.txt" 2>"$o/stderr.txt";rc=$?;set -e;e=$(date +%s%N);date -u +%Y-%m-%dT%H:%M:%S.%NZ>"$o/ended-at-utc.txt";echo "$rc">"$o/exit-code.txt";echo "$(((e-s)/1000000))">"$o/duration-ms.txt";(cd "$o"&&sha256sum command.txt launcher-environment.nul umask.txt started-at-utc.txt ended-at-utc.txt exit-code.txt duration-ms.txt stdout.txt stderr.txt>files.sha256);return "$rc";}
snapshot(){ local x="$1";sha256sum "$P/customers/registry.json" "$P/data/onboarding/telegram-customer-bootstrap-v1/ledger.json" "$P/data/customers/task26_live_2e_r2_20260815_8527916639/nutrition-onboarding/readiness-receipt-v1.json">"$E/artifacts/live-authority-$x.sha256";find "$S/checkin_cli" -type f -name '*.py' -print0|sort -z|xargs -0 sha256sum>"$E/artifacts/profile-package-$x.sha256";sha256sum "$S/tests/test_adaptive_nutrition.py">"$E/artifacts/profile-test-$x.sha256";systemctl --user show hermes-gateway-dualcoachtest.service -p ActiveState -p SubState -p MainPID -p Result -p InvocationID>"$E/artifacts/service-$x.txt";"$PY" - "$P">"$E/artifacts/live-state-$x.json" <<'PY'
import json,sys
from pathlib import Path
p=Path(sys.argv[1]);r=json.loads((p/'customers/registry.json').read_text());b=json.loads((p/'data/onboarding/telegram-customer-bootstrap-v1/ledger.json').read_text());z=json.loads((p/'data/customers/task26_live_2e_r2_20260815_8527916639/nutrition-onboarding/readiness-receipt-v1.json').read_text());c=next(x for x in r['customers'] if x['customer_key']=='task26_live_2e_r2_20260815_8527916639');s=next(x for x in b['sessions'] if x['generation']==5);print(json.dumps({'customer_enabled':c['enabled'],'adaptive_activation':z['activation_enabled'],'adaptive_delivery':z['delivery_enabled'],'bootstrap_generation':s['generation'],'bootstrap_state':s['state']},sort_keys=True,separators=(',',':')))
PY
}
SANDBOX=(bwrap --die-with-parent --unshare-net --ro-bind / / --bind "$E" "$E" --tmpfs /tmp --dev /dev --proc /proc --setenv HOME /tmp --setenv TMPDIR /tmp --setenv PYTHONDONTWRITEBYTECODE 1 --chdir "$S")
case "${1:-}" in
 baseline) snapshot before;sha256sum "$C/candidate-manifest.json" "$C/candidate-seal.json" "$C/hash-inventory.json" "$W">"$E/artifacts/candidate-pins-before.sha256";record candidate-baseline-verify "$PY" "$C/verify_candidate.py" "$C";;
 gate18) record gate18-candidate-verify "$PY" "$C/verify_candidate.py" "$C";record gate18-wheel-parity "$PY" - "$S" "$W" "$D" <<'PY'
import hashlib,json,sys,zipfile
from pathlib import Path
s,w,d=Path(sys.argv[1]),Path(sys.argv[2]),sys.argv[3];rows=[]
with zipfile.ZipFile(w) as z:
 for p in sorted(x for x in z.namelist() if x.startswith('checkin_cli/') and not x.endswith('/')):
  a=(s/p).read_bytes();b=z.read(p);rows.append({'path':p,'source_sha256':hashlib.sha256(a).hexdigest(),'wheel_sha256':hashlib.sha256(b).hexdigest(),'equal':a==b})
o={'candidate':d,'members':rows,'status':'PASS' if len(rows)==46 and all(x['equal'] for x in rows) else 'FAIL'};print(json.dumps(o,sort_keys=True,separators=(',',':')));raise SystemExit(o['status']!='PASS')
PY
 record gate18-token-golden "${SANDBOX[@]}" "$PY" -B -W error -m pytest -q -p no:cacheprovider -o asyncio_default_fixture_loop_scope=function --junitxml="$E/artifacts/gate18-token-golden.junit.xml" tests/test_customer_admin.py -k activation_token_rotation_waiver;record gate18-inode-golden "${SANDBOX[@]}" "$TPY" -B -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate18-inode-golden.junit.xml" tests/test_adaptive_nutrition.py::test_overlay_recovery_rejects_symlink_and_data_inode_replacement;;
 gate19) record gate19-predecessor "${SANDBOX[@]}" --ro-bind "$C/historical/predecessor-candidate/source-delta/before/checkin_cli/customer_admin.py" "$S/checkin_cli/customer_admin.py" --ro-bind "$C/historical/predecessor-candidate/source-delta/before/tests/test_customer_admin.py" "$S/tests/test_customer_admin.py" "$PY" -B -W error -m pytest -q -p no:cacheprovider -o asyncio_default_fixture_loop_scope=function --junitxml="$E/artifacts/gate19-predecessor.junit.xml" tests/test_customer_admin.py;record gate19-successor "${SANDBOX[@]}" "$PY" -B -W error -m pytest -q -p no:cacheprovider -o asyncio_default_fixture_loop_scope=function --junitxml="$E/artifacts/gate19-successor.junit.xml" tests/test_customer_admin.py
 if record gate19-inode-predecessor "${SANDBOX[@]}" --ro-bind "$C/test-delta/before/tests/test_adaptive_nutrition.py" "$S/tests/test_adaptive_nutrition.py" "$TPY" -B -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate19-inode-predecessor.junit.xml" tests/test_adaptive_nutrition.py::test_overlay_recovery_rejects_symlink_and_data_inode_replacement;then echo 'predecessor unexpectedly passed' >&2;exit 1;else rc=$?;[[ $rc -eq 1 ]];fi
 record gate19-inode-successor "${SANDBOX[@]}" "$TPY" -B -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate19-inode-successor.junit.xml" tests/test_adaptive_nutrition.py::test_overlay_recovery_rejects_symlink_and_data_inode_replacement;;
 gate20) record gate20-candidate-verify "$PY" "$C/verify_candidate.py" "$C";T=/tmp/task26-gate20-6aaef77d-source;rm -rf "$T";mkdir -p "$T";cp -a "$S"/. "$T"/;chmod -R u+rwX "$T";rm -rf "$T"/.ruff_cache "$T"/.pytest_cache "$T"/.venv "$T"/build "$T"/dist "$T"/*.egg-info "$T"/checkin_cli/__pycache__ "$T"/tests/__pycache__;sha256sum "$S/checkin_cli"/*.py "$T/checkin_cli"/*.py>"$E/artifacts/gate20-writable-copy-hashes.txt"
 record gate20-source-package env -C "$T" -u TMPDIR HOME=/home/cube PYTHONPATH="$T" PYTHONDONTWRITEBYTECODE=1 PYTHONPYCACHEPREFIX=/tmp/task26-pyc-6aaef77d "$TPY" -B -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate20-source-package.junit.xml" tests
 record gate20-full-gateway env -C "$R" -u TMPDIR HOME=/home/cube PYTHONPATH="$R:$S" PYTHONDONTWRITEBYTECODE=1 "$PY" -B -m pytest -q -p no:cacheprovider -o asyncio_default_fixture_loop_scope=function --junitxml="$E/artifacts/gate20-full-gateway.junit.xml" tests/gateway
 I="$E/artifacts/installed-wheel-root";mkdir -p "$I";record gate20-wheel-install "$PY" -m pip install --no-deps --no-compile --target "$I" "$W";record gate20-installed-tests env -C /tmp -u TMPDIR HOME=/home/cube PYTHONPATH="$I" PYTHONDONTWRITEBYTECODE=1 PYTHONPYCACHEPREFIX=/tmp/task26-pyc-installed-6aaef77d "$TPY" -B -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate20-installed-tests.junit.xml" "$T/tests/test_customer_admin.py"
 record gate20-installed-parity env -C /tmp -u TMPDIR HOME=/home/cube PYTHONPATH="$I" PYTHONDONTWRITEBYTECODE=1 "$TPY" -B - "$I" "$W" "$D" <<'PY'
import hashlib,importlib,json,sys,zipfile
from pathlib import Path
r,w,d=Path(sys.argv[1]).resolve(),Path(sys.argv[2]),sys.argv[3];rows=[]
with zipfile.ZipFile(w) as z:
 for n in ['checkin_cli/customer_admin.py','checkin_cli/activation_token_rotation_policy.py']:
  p=r/n;rows.append({'member':n,'installed_path':str(p),'installed_sha256':hashlib.sha256(p.read_bytes()).hexdigest(),'wheel_sha256':hashlib.sha256(z.read(n)).hexdigest(),'equal':p.read_bytes()==z.read(n)})
mods=[]
for n in ['checkin_cli.customer_admin','checkin_cli.activation_token_rotation_policy']:
 m=importlib.import_module(n);p=Path(m.__file__).resolve();mods.append({'module':n,'path':str(p),'inside_target':p.is_relative_to(r)})
o={'candidate':d,'files':rows,'imports':mods,'status':'PASS' if all(x['equal'] for x in rows) and all(x['inside_target'] for x in mods) else 'FAIL'};print(json.dumps(o,sort_keys=True,separators=(',',':')));raise SystemExit(o['status']!='PASS')
PY
 ;;
 after-gates) snapshot after-gates;sha256sum "$C/candidate-manifest.json" "$C/candidate-seal.json" "$C/hash-inventory.json" "$W">"$E/artifacts/candidate-pins-after-gates.sha256";;
 *) echo "usage: $0 baseline|gate18|gate19|gate20|after-gates" >&2;exit 64;;esac
