#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" SCRIPT="$ROOT_DIR/scripts/demo-check.sh" assert_contains() { local text="$1" grep -Fq "$text" "$SCRIPT" || { echo "FAIL: demo-check.sh missing: $text" >&2 exit 1 } } assert_not_contains() { local text="$1" if grep -Fq "$text" "$SCRIPT"; then echo "FAIL: demo-check.sh still contains unsafe match: $text" >&2 exit 1 fi } assert_contains 'AIHR_PILOT_START_DATE' assert_contains 'AIHR_PILOT_END_DATE' assert_contains 'AIHR_DEMO_CHECK_LIBRARY_ONLY' assert_contains 'safe_org AS' assert_contains 'HAVING SUM(s.session_count) >= 10' assert_contains 'HAVING COUNT(DISTINCT ext_party_id) = 1' assert_contains 'finished_time >=' assert_contains 'reviewed_time >=' assert_not_contains 'p.identity_key = o.ext_party_id OR p.identity_key = o.person_phone' assert_not_contains 's.ext_party_id = o.ext_party_id OR s.ext_party_id = o.person_phone' if ! command -v docker >/dev/null || ! docker ps --format '{{.Names}}' | grep -qx 'wygj-mysql'; then echo "SKIP: behavioral pilot gate test requires wygj-mysql" exit 0 fi export AIHR_DEMO_CHECK_LIBRARY_ONLY=true # shellcheck source=../demo-check.sh source "$SCRIPT" unset AIHR_PILOT_DB [[ "$(pilot_sql_scalar 'SELECT 1')" == "1" ]] || { echo "FAIL: default ry-vue pilot database is unavailable" >&2 exit 1 } TEST_DB="wygj_demo_check_test_$$" cleanup() { docker exec wygj-mysql mysql -uroot -proot -e "DROP DATABASE IF EXISTS \`$TEST_DB\`" >/dev/null 2>&1 || true } trap cleanup EXIT docker exec -i wygj-mysql mysql -uroot -proot --default-character-set=utf8mb4 </dev/null CREATE DATABASE \`$TEST_DB\` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; USE \`$TEST_DB\`; CREATE TABLE aihr_practice_scenario (tenant_id varchar(20), position varchar(80), enabled tinyint); CREATE TABLE aihr_practice_session (tenant_id varchar(20), session_id varchar(100), ext_party_id varchar(100), mode varchar(30), finished_time datetime); CREATE TABLE aihr_practice_assignment (tenant_id varchar(20), ext_party_id varchar(100), create_time datetime); CREATE TABLE aihr_org_snapshot ( tenant_id varchar(20), employment_status varchar(20), ext_party_id varchar(100), project_code varchar(50), person_phone varchar(30) ); CREATE TABLE aihr_practice_calibration ( id bigint auto_increment primary key, tenant_id varchar(20), session_id varchar(100), original_score int, corrected_score int, create_time datetime ); CREATE TABLE aihr_sop_answer_review ( tenant_id varchar(20), status varchar(30), usable tinyint, reviewed_time datetime, create_time datetime ); INSERT INTO aihr_practice_scenario SELECT '000000','生活顾问',1 FROM ( SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 ) n; INSERT INTO aihr_org_snapshot VALUES ('000000','active','A','P1','13900000001'), ('000000','active','B','P1','13900000001'), ('000000','active','C','P2','D'), ('000000','active','D','P2','13900000004'), ('000000','active','E','P3','13900000005'), ('000000','active','F','P3','13900000006'); INSERT INTO aihr_practice_assignment VALUES ('000000','D','2026-07-08 08:00:00'), ('000000','13900000001','2026-07-08 08:00:00'), ('000000','E','2026-07-08 08:00:00'), ('000000','13900000005','2026-07-08 08:00:00'), ('000000','F','2026-07-08 08:00:00'); INSERT INTO aihr_practice_session SELECT '000000', CONCAT('e-', n), CASE WHEN n <= 5 THEN 'E' ELSE '13900000005' END, 'mobile', '2026-07-08 09:00:00' FROM ( SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 ) n; INSERT INTO aihr_practice_session SELECT '000000', CONCAT('f-', n), 'F','mobile','2026-07-08 10:00:00' FROM ( SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 ) n; INSERT INTO aihr_practice_session VALUES ('000000','e-out','E','mobile','2026-07-06 10:00:00'), ('000000','unsafe-inside','D','mobile','2026-07-08 10:00:00'); INSERT INTO aihr_practice_calibration (tenant_id,session_id,original_score,corrected_score,create_time) VALUES ('000000','f-1',80,82,'2026-07-08 11:00:00'), ('000000','unsafe-inside',80,40,'2026-07-08 11:00:00'), ('000000','e-out',80,40,'2026-07-06 11:00:00'); INSERT INTO aihr_sop_answer_review VALUES ('000000','已评审',1,'2026-07-08 12:00:00','2026-07-08 11:00:00'), ('000000','已评审',0,'2026-07-06 12:00:00','2026-07-06 11:00:00'), ('000000','待评审',NULL,NULL,'2026-07-08 13:00:00'), ('000000','待评审',NULL,NULL,'2026-07-06 13:00:00'); SQL export AIHR_PILOT_DB="$TEST_DB" pilot_output="$(AIHR_PILOT_START_DATE=2026-07-07 AIHR_PILOT_END_DATE=2026-07-10 check_pilot_samples)" [[ "$pilot_output" == *'ten_sessions=1/5'* ]] || { echo "FAIL: 9/10 boundary or raw window count: $pilot_output" >&2; exit 1; } [[ "$pilot_output" == *'org_login=2/6'* ]] || { echo "FAIL: unsafe org identities were not excluded: $pilot_output" >&2; exit 1; } [[ "$pilot_output" == *'org_pilot=2/20'* ]] || { echo "FAIL: collision or dual-key identity was miscounted: $pilot_output" >&2; exit 1; } [[ "$pilot_output" == *'projects=1/1-2'* ]] || { echo "FAIL: safe pilot project count: $pilot_output" >&2; exit 1; } [[ "$pilot_output" == *'org_ten_sessions=1/2'* ]] || { echo "FAIL: formal 9/10 boundary: $pilot_output" >&2; exit 1; } [[ "$pilot_output" == *'calibration=1/20 consistency=1/1'* ]] || { echo "FAIL: calibration window: $pilot_output" >&2; exit 1; } [[ "$pilot_output" == *'sop_usable=1/1 sop_pending=1'* ]] || { echo "FAIL: SOP window: $pilot_output" >&2; exit 1; } pilot_sql_scalar "INSERT INTO aihr_practice_session VALUES ('000000','e-10','13900000005','mobile','2026-07-09 09:00:00')" >/dev/null pilot_output="$(AIHR_PILOT_START_DATE=2026-07-07 AIHR_PILOT_END_DATE=2026-07-10 check_pilot_samples)" [[ "$pilot_output" == *'org_ten_sessions=2/2'* ]] || { echo "FAIL: formal 10/10 boundary: $pilot_output" >&2; exit 1; } if (AIHR_PILOT_STRICT=true AIHR_PILOT_START_DATE= AIHR_PILOT_END_DATE= check_pilot_samples) >/tmp/wygj-pilot-strict-test.log 2>&1; then echo "FAIL: strict mode accepted an implicit date window" >&2 exit 1 fi grep -Fq 'strict pilot check requires AIHR_PILOT_START_DATE and AIHR_PILOT_END_DATE' /tmp/wygj-pilot-strict-test.log || { echo "FAIL: strict mode missing-date error is unclear" >&2 exit 1 } echo "PASS: demo pilot gates use a bounded window and unique formal identities"