#!/bin/bash set -euo pipefail ROOT=$(cd "$(dirname "$0")/.." && pwd) RUNTIME="$ROOT/runtime" ATTEMPT_ROOT=${ABG_ATTEMPT_ROOT:?ABG_ATTEMPT_ROOT is required} EVIDENCE=${ABG_EVIDENCE_DIR:?ABG_EVIDENCE_DIR is required} SOURCE_REVISION=${ABG_SOURCE_REVISION:?ABG_SOURCE_REVISION is required} ORIGINAL_HOME=${ABG_ORIGINAL_HOME:?ABG_ORIGINAL_HOME is required} GODOT=${GODOT_BIN:-/Applications/Godot.app/Contents/MacOS/Godot} TEMPLATE_VERSION=${ABG_GODOT_TEMPLATE_VERSION:-4.6.1.stable} TEMPLATE_SOURCE="$ORIGINAL_HOME/Library/Application Support/Godot/export_templates/$TEMPLATE_VERSION" TEMPLATE_PARENT="$HOME/Library/Application Support/Godot/export_templates" WEB="$EVIDENCE/web" LOGS="$EVIDENCE/logs" if [ "$ROOT" != "$ATTEMPT_ROOT/source" ] || [ "$SOURCE_REVISION" = "WORKTREE" ]; then echo "runtime Web export requires an immutable run_test_attempt.py Git archive" >&2 exit 91 fi if [ ! -x "$GODOT" ] || [ ! -d "$TEMPLATE_SOURCE" ]; then echo "Godot or exact Web template is unavailable" >&2 exit 92 fi if [ ! -d "$RUNTIME/tests" ]; then echo "runtime/tests is required before the isolated projection" >&2 exit 93 fi strict_scan() { local log=$1 if grep -En 'SCRIPT ERROR:|Parse Error:|ERROR:|ObjectDB instances leaked|resources still in use at exit|RID allocations of type|RID of type' "$log"; then echo "strict diagnostics in $log" >&2 return 86 fi } test_count=$(find "$RUNTIME/tests" -type f | wc -l | tr -d ' ') find "$RUNTIME/tests" -depth -delete if [ -e "$RUNTIME/tests" ]; then echo "runtime/tests projection removal failed" >&2 exit 94 fi mkdir -p "$LOGS" "$WEB" "$TEMPLATE_PARENT" ln -s "$TEMPLATE_SOURCE" "$TEMPLATE_PARENT/$TEMPLATE_VERSION" "$GODOT" --headless --editor --audio-driver Dummy --path "$RUNTIME" --import \ >"$LOGS/import.log" 2>&1 strict_scan "$LOGS/import.log" "$GODOT" --headless --editor --audio-driver Dummy --path "$RUNTIME" \ --export-release "Web Preview" "$WEB/index.html" >"$LOGS/export.log" 2>&1 strict_scan "$LOGS/export.log" "$GODOT" --headless --audio-driver Dummy --main-pack "$WEB/index.pck" \ --script "$ROOT/tools/pck_inventory.gd" >"$LOGS/pck-inventory.log" 2>&1 strict_scan "$LOGS/pck-inventory.log" inventory_marker=$(grep -E '^ABG_PCK_INVENTORY_OK files=[0-9]+ forbidden=0$' "$LOGS/pck-inventory.log" || true) if [ -z "$inventory_marker" ]; then echo "PCK inventory terminal is missing" >&2 exit 95 fi for path in \ res://fg4/catalog.json \ res://fg4/rg04_catalog.json \ res://fg4/run_state.gdc \ res://fg4/save_v11_service.gdc \ res://campaign/fg4_adapter.gdc \ res://campaign/fg4_runtime_controller.gdc \ res://assets/fg4/asset-manifest.json \ res://assets/fg4/audio-manifest.json; do if ! grep -Fxq "$path" "$LOGS/pck-inventory.log"; then echo "required runtime PCK path missing: $path" >&2 exit 96 fi done web_count=$(find "$WEB" -maxdepth 1 -type f | wc -l | tr -d ' ') if [ "$web_count" -ne 9 ]; then echo "Web export files=$web_count; expected 9" >&2 exit 97 fi ( cd "$WEB" find . -maxdepth 1 -type f -print | sed 's#^./##' | sort | while IFS= read -r path; do shasum -a 256 "$path" done ) >"$EVIDENCE/export.sha256" pck_paths=$(printf '%s\n' "$inventory_marker" | sed -E 's/.*files=([0-9]+).*/\1/') printf '%s\n' \ "source_revision=$SOURCE_REVISION" \ "test_files_removed=$test_count" \ "web_files=$web_count" \ "pck_paths=$pck_paths" \ "forbidden_paths=0" \ >"$EVIDENCE/web-summary.txt" printf 'ABG_RUNTIME_WEB_EXPORT_OK source=%s files=%s pck_paths=%s forbidden=0 test_files_removed=%s\n' \ "$SOURCE_REVISION" "$web_count" "$pck_paths" "$test_count"