#!/bin/bash set -euo pipefail ROOT=$(cd "$(dirname "$0")/.." && pwd) RUNTIME="$ROOT/runtime" EVIDENCE=${ABG_EVIDENCE_DIR:?ABG_EVIDENCE_DIR is required} SOURCE_REVISION=${ABG_SOURCE_REVISION:?ABG_SOURCE_REVISION is required} GODOT=${GODOT_BIN:-/Applications/Godot.app/Contents/MacOS/Godot} if [[ ! "$SOURCE_REVISION" =~ ^[0-9a-f]{40}$ ]]; then echo "DEV-2 candidate requires a source-bound 40-character revision" >&2 exit 85 fi mkdir -p "$EVIDENCE/logs/headless" "$EVIDENCE/logs/normal" "$EVIDENCE/captures" 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 } require_marker() { local log=$1 local marker=$2 local count count=$(grep -Ec "^${marker}( |$)" "$log" || true) if [ "$count" -ne 1 ]; then echo "marker $marker count=$count in $log" >&2 return 87 fi } run_godot() { local mode=$1 local folder=$2 local script=$3 local marker=$4 local capture_suffix="" if [ -n "${ABG_CAPTURE_FIXTURE_INDEX:-}" ]; then capture_suffix="_fixture_${ABG_CAPTURE_FIXTURE_INDEX}" fi local log="$EVIDENCE/logs/$mode/${folder}_${script%.gd}${capture_suffix}.log" if [ "$mode" = headless ]; then "$GODOT" --headless --audio-driver Dummy --path "$RUNTIME" \ --script "res://tests/$folder/$script" >"$log" 2>&1 else ABG_EVIDENCE_DIR="$EVIDENCE/captures" \ "$GODOT" --audio-driver Dummy --fixed-fps 60 --disable-vsync \ --path "$RUNTIME" --script "res://tests/$folder/$script" >"$log" 2>&1 fi strict_scan "$log" require_marker "$log" "$marker" tail -n 1 "$log" } import_log="$EVIDENCE/logs/import.log" "$GODOT" --headless --editor --audio-driver Dummy --path "$RUNTIME" --import >"$import_log" 2>&1 strict_scan "$import_log" while IFS='|' read -r folder script marker; do [ -n "$folder" ] || continue run_godot headless "$folder" "$script" "$marker" done <<'TESTS' dev1|boot_service_test.gd|ABG_DEV1_BOOT_OK dev1|boot_runtime_test.gd|ABG_DEV1_BOOT_RUNTIME_OK dev1|first_launch_test.gd|ABG_DEV1_FIRST_LAUNCH_OK dev1|title_state_test.gd|ABG_DEV1_TITLE_OK dev1|settings_credits_test.gd|ABG_DEV1_SETTINGS_OK dev1|entry_flow_touch_test.gd|ABG_DEV1_ENTRY_TOUCH_OK dev2|initial_company_draft_test.gd|ABG_DEV2_DRAFT_OK dev2|initial_company_choice_test.gd|ABG_DEV2_CHOICE_OK dev2|initial_company_touch_test.gd|ABG_DEV2_CHOICE_TOUCH_OK dev2|initial_company_commit_test.gd|ABG_DEV2_COMMIT_OK dev2|initial_company_commit_touch_test.gd|ABG_DEV2_COMMIT_TOUCH_OK dev2|initial_company_full_flow_touch_test.gd|ABG_DEV2_FULL_FLOW_TOUCH_OK TESTS for fixture_index in 0 1 2 3; do ABG_CAPTURE_FIXTURE_INDEX=$fixture_index \ run_godot normal dev2 initial_company_capture_test.gd ABG_DEV2_INITIAL_COMPANY_CAPTURE_OK done capture_count=$(find "$EVIDENCE/captures" -type f -name '*.png' | wc -l | tr -d ' ') if [ "$capture_count" -ne 24 ]; then echo "capture count=$capture_count; expected 24" >&2 exit 89 fi printf 'ABG_DEV2_CANDIDATE_SUITE_OK source=%s dev1_headless=6 dev2_headless=6 normal=1 captures=%s strict=0 parsed_touch=true\n' \ "$SOURCE_REVISION" "$capture_count"