Files
aetherbound-guild/tools/run_mvp_first_cycle_audit.sh
T

174 lines
7.2 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# Current first-cycle audit. This is intentionally separate from the historical
# DEV-5 candidate suite: the latter bundled a pre-reconstruction Market test
# that treated the read-only MarketTitle label as a Button.
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 "MVP first-cycle audit 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_headless() {
local id=$1
local folder=$2
local script=$3
local markers=$4
local log="$EVIDENCE/logs/headless/${id}.log"
"$GODOT" --headless --audio-driver Dummy --path "$RUNTIME" \
--script "res://tests/$folder/$script" >"$log" 2>&1
strict_scan "$log"
IFS=',' read -r -a expected_markers <<< "$markers"
for marker in "${expected_markers[@]}"; do
require_marker "$log" "$marker"
done
tail -n 1 "$log"
}
run_normal() {
local id=$1
local folder=$2
local script=$3
local markers=$4
local evidence_subdir="$EVIDENCE/captures/$id"
local log="$EVIDENCE/logs/normal/${id}.log"
mkdir -p "$evidence_subdir"
ABG_EVIDENCE_DIR="$evidence_subdir" \
"$GODOT" --audio-driver Dummy --fixed-fps 60 --disable-vsync \
--path "$RUNTIME" --script "res://tests/$folder/$script" >"$log" 2>&1
strict_scan "$log"
IFS=',' read -r -a expected_markers <<< "$markers"
for marker in "${expected_markers[@]}"; do
require_marker "$log" "$marker"
done
tail -n 1 "$log"
}
run_fixture_capture() {
local id=$1
local folder=$2
local script=$3
local marker=$4
local fixture=$5
shift 5
local evidence_subdir="$EVIDENCE/captures/$id"
local log="$EVIDENCE/logs/normal/${id}.log"
mkdir -p "$evidence_subdir"
ABG_EVIDENCE_DIR="$evidence_subdir" \
ABG_CAPTURE_FIXTURE_INDEX="$fixture" \
"$@" \
"$GODOT" --audio-driver Dummy --fixed-fps 60 --disable-vsync \
--path "$RUNTIME" --script "res://tests/$folder/$script" >"$log" 2>&1
strict_scan "$log"
require_marker "$log" "$marker"
tail -n 1 "$log"
}
assert_capture_count() {
local id=$1
local expected=$2
local actual
actual=$(find "$EVIDENCE/captures/$id" -type f -name '*.png' | wc -l | tr -d ' ')
if [ "$actual" -ne "$expected" ]; then
echo "$id capture count=$actual; expected $expected" >&2
return 89
fi
}
import_log="$EVIDENCE/logs/import.log"
"$GODOT" --headless --editor --audio-driver Dummy --path "$RUNTIME" --import >"$import_log" 2>&1
strict_scan "$import_log"
# Entry, Company and first Contract semantics.
while IFS='|' read -r id folder script markers; do
[ -n "$id" ] || continue
run_headless "$id" "$folder" "$script" "$markers"
done <<'TESTS'
dev1_boot_service|dev1|boot_service_test.gd|ABG_DEV1_BOOT_OK
dev1_boot_runtime|dev1|boot_runtime_test.gd|ABG_DEV1_BOOT_RUNTIME_OK
dev1_first_launch|dev1|first_launch_test.gd|ABG_DEV1_FIRST_LAUNCH_OK
dev1_title|dev1|title_state_test.gd|ABG_DEV1_TITLE_OK
dev1_settings|dev1|settings_credits_test.gd|ABG_DEV1_SETTINGS_OK
dev1_touch|dev1|entry_flow_touch_test.gd|ABG_DEV1_ENTRY_TOUCH_OK
dev2_draft|dev2|initial_company_draft_test.gd|ABG_DEV2_DRAFT_OK
dev2_choice|dev2|initial_company_choice_test.gd|ABG_DEV2_CHOICE_OK
dev2_choice_touch|dev2|initial_company_touch_test.gd|ABG_DEV2_CHOICE_TOUCH_OK
dev2_commit|dev2|initial_company_commit_test.gd|ABG_DEV2_COMMIT_OK
dev2_commit_touch|dev2|initial_company_commit_touch_test.gd|ABG_DEV2_COMMIT_TOUCH_OK
dev2_full_flow_touch|dev2|initial_company_full_flow_touch_test.gd|ABG_DEV2_FULL_FLOW_TOUCH_OK
dev3_contract|dev3|contract_foundation_test.gd|ABG_DEV3_CONTRACT_OK
dev3_guild_contract|dev3|guild_contract_choice_test.gd|ABG_DEV3_GUILD_OK
dev3_market_behavior|dev3|market_recruit_review_test.gd|ABG_DEV3_MARKET_OK
dev3_hire|dev3|hire_transaction_test.gd|ABG_DEV3_HIRE_OK
m09_market_runtime|dev3|market_runtime_reconstruction_test.gd|ABG_M09_MARKET_RUNTIME_OK
m10_recruit_runtime|dev3|shp002_recruit_review_runtime_test.gd|ABG_M10_RECRUIT_REVIEW_OK
dev4_foundation|dev4|formation_risk_foundation_test.gd|ABG_DEV4_FOUNDATION_OK
dev4_party|dev4|party_line_test.gd|ABG_DEV4_PARTY_OK
dev4_readiness|dev4|readiness_review_test.gd|ABG_DEV4_READY_OK
dev4_risk|dev4|risk_selection_test.gd|ABG_DEV4_RISK_OK
rsk002_commitment|rsk002|risk_commitment_runtime_test.gd|ABG_RSK002_COMMITMENT_OK
bat001_foundation|dev5|battle_foundation_test.gd|ABG_DEV5_BATTLE_OK
bat001_opening|dev5|battle_opening_test.gd|ABG_DEV5_BATTLE_OPENING_OK
bat002_runtime|dev5|battle_runtime_test.gd|ABG_DEV5_BATTLE_UI_OK
bat002_observation|dev5|battle_observation_service_test.gd|ABG_DEV5_BATTLE_OBSERVATION_SERVICE_OK
bat002_field|dev5|battle_live_field_test.gd|ABG_DEV5_BATTLE_LIVE_FIELD_OK
bat002_timeline|dev5|battle_live_timeline_test.gd|ABG_DEV5_BATTLE_TIMELINE_OK
bat003_004_runtime|dev5|bat003_bat004_runtime_test.gd|ABG_BAT003_BAT004_RUNTIME_OK
m12_domain|dev5|outcome_recovery_test.gd|ABG_M12_OUTCOME_RECOVERY_DOMAIN_OK
m12_runtime|dev5|m12_runtime_test.gd|ABG_M12_RUNTIME_OK
TESTS
# Current normal 100% page/battle evidence. No 130% fixture is part of this
# MVP gate; the explicit override keeps the older Party/Risk capture helper
# from selecting its historical 130% English fixture.
run_normal m09_market_capture dev3 market_runtime_capture_test.gd ABG_M09_MARKET_CAPTURE_OK
assert_capture_count m09_market_capture 16
run_normal m10_recruit_capture dev3 shp002_recruit_review_capture_test.gd ABG_M10_RECRUIT_REVIEW_CAPTURE_OK
assert_capture_count m10_recruit_capture 4
for fixture in 0 1 2 3; do
run_fixture_capture "dev4_capture_${fixture}" dev4 formation_risk_capture_test.gd ABG_DEV4_CAPTURE_OK "$fixture" env ABG_CAPTURE_TEXT_SCALE=1.0
done
for fixture in 0 1 2 3; do
run_fixture_capture "bat001_capture_${fixture}" dev5 battle_opening_capture_test.gd ABG_DEV5_BATTLE_OPENING_CAPTURE_OK "$fixture"
done
for fixture in 0 1 2 3; do
run_fixture_capture "bat002_capture_${fixture}" dev5 battle_live_capture_test.gd ABG_DEV5_BATTLE_LIVE_CAPTURE_OK "$fixture"
done
for fixture in 0 1 2 3; do
run_fixture_capture "bat003_004_capture_${fixture}" dev5 bat003_bat004_capture_test.gd ABG_BAT003_BAT004_CAPTURE_OK "$fixture"
done
run_normal m12_capture dev5 m12_capture_test.gd ABG_M12_CAPTURE_OK
assert_capture_count m12_capture 32
capture_count=$(find "$EVIDENCE/captures" -type f -name '*.png' | wc -l | tr -d ' ')
printf 'ABG_MVP_FIRST_CYCLE_AUDIT_OK source=%s focused=34 capture_families=8 captures=%s normal_100=true locales=zh_CN,en viewports=760x360,844x390,1280x720 strict=0 parsed_touch=true restart=market stale_market_title_test=fixed non_mvp=second_cycle,regions,endgame,device,package,store,human_comprehension\n' \
"$SOURCE_REVISION" "$capture_count"