#!/usr/bin/env bash
set -uo pipefail
umask 077
readonly E="/home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-gates18-20-summary-production-e2f1699e8586ed3f835eaa2a3eaeaecaf5e52a4ad82aa931caade0ed377077ce-st_01a0080c"
readonly C="/home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-summary-production-successor-e2f1699e8586ed3f835eaa2a3eaeaecaf5e52a4ad82aa931caade0ed377077ce"
readonly R="/home/cube/projects/richard/hermes-agent"
readonly PY="$R/.venv/bin/python"
readonly W="$C/artifacts/hermes_agent-0.17.0-py3-none-any.whl"
readonly MATRIX="/home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-gate19-50685ac2c063c5b18fa895cc1991e3473368d177c7309bf54af0374ea67ba1d1-matrix.json"
readonly DIGEST="e2f1699e8586ed3f835eaa2a3eaeaecaf5e52a4ad82aa931caade0ed377077ce"
mkdir -p "$E/artifacts" "$E/receipts"; chmod 700 "$E" "$E/artifacts" "$E/receipts"
run_recorded() {
 local name="$1"; shift; local d="$E/artifacts/$name"; mkdir -p "$d"; chmod 700 "$d"
 printf '%q ' "$@" >"$d/command.txt"; printf '\n' >>"$d/command.txt"; date --utc +%Y-%m-%dT%H:%M:%S.%NZ >"$d/started-at-utc.txt"
 local s e rc pid; s=$(date +%s%N); "$@" >"$d/stdout.txt" 2>"$d/stderr.txt" & pid=$!; wait "$pid"; rc=$?; e=$(date +%s%N)
 date --utc +%Y-%m-%dT%H:%M:%S.%NZ >"$d/ended-at-utc.txt"; printf '%s\n' "$rc" >"$d/exit-code.txt"; printf '%s\n' "$(((e-s)/1000000))" >"$d/duration-ms.txt"
 (cd "$d" && sha256sum command.txt started-at-utc.txt ended-at-utc.txt exit-code.txt duration-ms.txt stdout.txt stderr.txt >files.sha256); chmod 600 "$d"/*; chmod 700 "$d"; return 0
}
cd "$R"
git status --porcelain=v1 -z >"$E/artifacts/git-status-before.nul"
sha256sum "$C/candidate-manifest.json" "$W" "$C/source-delta/exact.diff" >"$E/artifacts/candidate-pins-before.sha256"
systemctl --user show hermes-gateway-dualcoachtest.service -p ActiveState -p SubState -p MainPID >"$E/artifacts/service-before.txt" 2>&1 || true
find /home/cube/projects/richard/traning\ coach/.omo/evidence/task26 -path '*st_01a0080c/receipts/*.json' -type f -print0 | sort -z | xargs -0 sha256sum >"$E/artifacts/prior-receipts-before.sha256"
run_recorded candidate-preverify "$PY" "$C/verify_candidate.py" "$C"
run_recorded delta-authority-proof "$PY" -c '
import ast,hashlib,json,sys,zipfile
from pathlib import Path
c=Path(sys.argv[1]); repo=Path(sys.argv[2]); delta=json.loads((c/"bindings/source-delta.json").read_text()); expected={"gateway/platforms/nutrition_onboarding_reconciliation.py","gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py","tests/gateway/test_nutrition_onboarding_reconciliation.py"}; paths={x["path"] for x in delta["files"]}
added=[line[1:] for line in (c/"source-delta/exact.diff").read_text().splitlines() if line.startswith("+") and not line.startswith("+++")]; forbidden=("activate_customer","set_customer_enabled","transition(","mark_committed(","delivery_committed","consent_granted =","role_claims","authorization")
mods=[]
with zipfile.ZipFile(c/"artifacts/hermes_agent-0.17.0-py3-none-any.whl") as z:
 for p in sorted(expected-set(["tests/gateway/test_nutrition_onboarding_reconciliation.py"])):
  a=(repo/p).read_bytes(); b=z.read(p); mods.append({"path":p,"source_sha256":hashlib.sha256(a).hexdigest(),"wheel_sha256":hashlib.sha256(b).hexdigest(),"byte_identical":a==b})
r={"candidate_digest":sys.argv[3],"diff_sha256":hashlib.sha256((c/"source-delta/exact.diff").read_bytes()).hexdigest(),"delta_paths":sorted(paths),"production_modules":mods,"forbidden_authority_or_state_additions":[line for line in added if any(x in line for x in forbidden)],"changed_functions":["render_authoritative_customer_summary","TelegramNutritionOnboardingRuntime._publish"],"status":"PASS" if paths==expected and all(x["byte_identical"] for x in mods) and not any(any(x in line for x in forbidden) for line in added) else "FAIL"}; print(json.dumps(r,sort_keys=True,separators=(",",":"))); raise SystemExit(r["status"]!="PASS")
' "$C" "$R" "$DIGEST"
run_recorded source-wheel-parity "$PY" -c '
import hashlib,json,sys,zipfile
from pathlib import Path
repo=Path(sys.argv[1]); wheel=Path(sys.argv[2]); paths=["gateway/platforms/dualcoach_activation_cutover.py","gateway/platforms/dualcoach_admin.py","gateway/platforms/telegram_customer_bootstrap.py","gateway/platforms/nutrition_onboarding_reconciliation.py","gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py"]; rows=[]
with zipfile.ZipFile(wheel) as z:
 for p in paths:
  a=(repo/p).read_bytes(); b=z.read(p); rows.append({"path":p,"source_sha256":hashlib.sha256(a).hexdigest(),"wheel_sha256":hashlib.sha256(b).hexdigest(),"byte_identical":a==b})
r={"candidate_digest":sys.argv[3],"modules":rows,"status":"PASS" if all(x["byte_identical"] for x in rows) else "FAIL"}; print(json.dumps(r,sort_keys=True,separators=(",",":"))); raise SystemExit(r["status"]!="PASS")
' "$R" "$W" "$DIGEST"
run_recorded gate18 bwrap --die-with-parent --unshare-net --ro-bind / / --bind "$E" "$E" --tmpfs /tmp --tmpfs "$R/.pytest-cache" --dev /dev --proc /proc --setenv HOME /tmp --setenv TMPDIR /tmp --setenv PYTHONDONTWRITEBYTECODE 1 --chdir "$R" "$PY" -B -W error -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate18.junit.xml" tests/gateway/test_nutrition_onboarding_reconciliation.py::test_production_attestation_card_includes_advisory_summary tests/gateway/test_nutrition_onboarding_reconciliation.py::test_resolved_clarification_discards_stale_advisory_sections
mapfile -t GATE19_NODES < <("$PY" -c 'import json,sys; print("\n".join(json.load(open(sys.argv[1]))["exact_nodes"]))' "$MATRIX")
run_recorded gate19-predecessor bwrap --die-with-parent --unshare-net --ro-bind / / --bind "$E" "$E" --tmpfs /tmp --tmpfs "$R/.pytest-cache" --dev /dev --proc /proc --setenv HOME /tmp --setenv TMPDIR /tmp --setenv PYTHONDONTWRITEBYTECODE 1 --chdir "$R" "$PY" -B -W error -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate19-predecessor.junit.xml" "${GATE19_NODES[@]}"
run_recorded gate19-summary-matrix bwrap --die-with-parent --unshare-net --ro-bind / / --bind "$E" "$E" --tmpfs /tmp --tmpfs "$R/.pytest-cache" --dev /dev --proc /proc --setenv HOME /tmp --setenv TMPDIR /tmp --setenv PYTHONDONTWRITEBYTECODE 1 --chdir "$R" "$PY" -B -W error -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate19-summary-matrix.junit.xml" tests/gateway/test_nutrition_onboarding_reconciliation.py
run_recorded ruff "$R/.venv/bin/ruff" check --no-cache gateway/platforms/nutrition_onboarding_reconciliation.py gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py tests/gateway/test_nutrition_onboarding_reconciliation.py
run_recorded compile "$PY" -B -c 'import sys; from pathlib import Path; [compile(Path(p).read_bytes(),p,"exec",dont_inherit=True) for p in sys.argv[1:]]' gateway/platforms/nutrition_onboarding_reconciliation.py gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py tests/gateway/test_nutrition_onboarding_reconciliation.py
run_recorded basedpyright-changed uvx --offline basedpyright --outputjson gateway/platforms/nutrition_onboarding_reconciliation.py gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py tests/gateway/test_nutrition_onboarding_reconciliation.py
readonly PARENT="$E/artifacts/predecessor-type-input"; mkdir -p "$PARENT/gateway/platforms" "$PARENT/tests/gateway"
cp gateway/platforms/nutrition_onboarding_reconciliation.py "$PARENT/gateway/platforms/"; cp gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py "$PARENT/gateway/platforms/"; cp tests/gateway/test_nutrition_onboarding_reconciliation.py "$PARENT/tests/gateway/"
run_recorded reconstruct-predecessor /bin/bash -c 'cd "$1" && patch --batch -R -p1 < "$2" && sha256sum gateway/platforms/nutrition_onboarding_reconciliation.py gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py tests/gateway/test_nutrition_onboarding_reconciliation.py' _ "$PARENT" "$C/source-delta/exact.diff"
run_recorded basedpyright-predecessor bwrap --die-with-parent --ro-bind / / --ro-bind "$PARENT/gateway/platforms/nutrition_onboarding_reconciliation.py" "$R/gateway/platforms/nutrition_onboarding_reconciliation.py" --ro-bind "$PARENT/gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py" "$R/gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py" --ro-bind "$PARENT/tests/gateway/test_nutrition_onboarding_reconciliation.py" "$R/tests/gateway/test_nutrition_onboarding_reconciliation.py" --dev /dev --proc /proc --chdir "$R" uvx --offline basedpyright --outputjson gateway/platforms/nutrition_onboarding_reconciliation.py gateway/platforms/telegram_nutrition_onboarding_runtime_publication.py tests/gateway/test_nutrition_onboarding_reconciliation.py
readonly BUILD="$E/artifacts/reproducible-build-output"; mkdir -p "$BUILD"
run_recorded reproducible-build bwrap --die-with-parent --unshare-net --ro-bind / / --tmpfs /tmp --bind /home/cube/.cache/uv /home/cube/.cache/uv --bind "$BUILD" /tmp/wheel-out --dev /dev --proc /proc --setenv HOME /tmp --setenv TMPDIR /tmp --setenv UV_CACHE_DIR /home/cube/.cache/uv --chdir "$R" /bin/bash -c 'umask 0002; exec scripts/reproducible-wheel-build "$PWD" /tmp/wheel-out'
sha256sum "$BUILD"/*.whl >"$E/artifacts/reproducible-build.sha256" 2>&1 || true
readonly INSTALL="$E/artifacts/installed-wheel-root"; mkdir -p "$INSTALL"
run_recorded wheel-install "$PY" -m pip install --no-deps --no-compile --target "$INSTALL" "$W"
mkdir -p "$E/artifacts/wheel-tests"; cp tests/gateway/test_dualcoach_activation_cutover.py tests/gateway/test_dualcoach_admin_provider_auth.py tests/gateway/test_telegram_customer_bootstrap.py tests/gateway/test_nutrition_onboarding_reconciliation.py "$E/artifacts/wheel-tests/"
run_recorded installed-wheel-tests 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 --setenv PYTHONPATH "$INSTALL" --chdir /tmp "$PY" -B -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/installed-wheel-tests.junit.xml" "$E/artifacts/wheel-tests/test_dualcoach_activation_cutover.py" "$E/artifacts/wheel-tests/test_dualcoach_admin_provider_auth.py" "$E/artifacts/wheel-tests/test_telegram_customer_bootstrap.py::test_customer_activation_commits_only_the_exact_bound_session" "$E/artifacts/wheel-tests/test_nutrition_onboarding_reconciliation.py"
run_recorded installed-wheel-import-closure bwrap --die-with-parent --unshare-net --ro-bind / / --tmpfs /tmp --dev /dev --proc /proc --setenv HOME /tmp --setenv TMPDIR /tmp --setenv PYTHONDONTWRITEBYTECODE 1 --setenv PYTHONPATH "$INSTALL" --chdir /tmp "$PY" -B -c '
import importlib,json,sys
from pathlib import Path
root=Path(sys.argv[1]).resolve(); names=["gateway.platforms.dualcoach_activation_cutover","gateway.platforms.dualcoach_admin","gateway.platforms.telegram_customer_bootstrap","gateway.platforms.nutrition_onboarding_reconciliation","gateway.platforms.telegram_nutrition_onboarding_runtime_publication"]; rows=[]
for n in names:
 m=importlib.import_module(n); p=Path(m.__file__).resolve(); rows.append({"module":n,"origin":str(p),"inside_installed_wheel":p.is_relative_to(root)})
leaks=[]
for n,m in sorted(sys.modules.items()):
 if n=="gateway" or n.startswith("gateway."):
  f=getattr(m,"__file__",None)
  if f and not Path(f).resolve().is_relative_to(root): leaks.append({"module":n,"origin":str(Path(f).resolve())})
r={"candidate_digest":sys.argv[2],"imports":rows,"gateway_source_fallbacks":leaks,"status":"PASS" if all(x["inside_installed_wheel"] for x in rows) and not leaks else "FAIL"}; print(json.dumps(r,sort_keys=True,separators=(",",":"))); raise SystemExit(r["status"]!="PASS")
' "$INSTALL" "$DIGEST"
run_recorded installed-wheel-cli bwrap --die-with-parent --unshare-net --ro-bind / / --tmpfs /tmp --dev /dev --proc /proc --setenv HOME /tmp --setenv TMPDIR /tmp --setenv PYTHONDONTWRITEBYTECODE 1 --setenv PYTHONPATH "$INSTALL" --chdir /tmp "$PY" -B -m gateway.platforms.dualcoach_admin customer activate --help
run_recorded gate20-full-gateway env PYTHONDONTWRITEBYTECODE=1 "$PY" -B -m pytest -q -p no:cacheprovider --junitxml="$E/artifacts/gate20-full-gateway.junit.xml" tests/gateway
run_recorded candidate-postverify "$PY" "$C/verify_candidate.py" "$C"
git status --porcelain=v1 -z >"$E/artifacts/git-status-after.nul"; sha256sum "$C/candidate-manifest.json" "$W" "$C/source-delta/exact.diff" >"$E/artifacts/candidate-pins-after.sha256"
systemctl --user show hermes-gateway-dualcoachtest.service -p ActiveState -p SubState -p MainPID >"$E/artifacts/service-after.txt" 2>&1 || true
find /home/cube/projects/richard/traning\ coach/.omo/evidence/task26 -path '*st_01a0080c/receipts/*.json' -type f -print0 | sort -z | xargs -0 sha256sum | grep -v "$E/receipts" >"$E/artifacts/prior-receipts-after.sha256"
