Files
prop-ai-hr/scripts/tests/demo-check-pilot-gates.test.sh
T

141 lines
6.6 KiB
Bash

#!/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 <<SQL >/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"