<?php

declare(strict_types=1);

// B/C archive-read compatibility runner. It is default-deny and owns only
// one CDXAR5 fixture namespace plus one disabled-password test operator.
$lane = (string)getenv('CDX_AR5_LANE');
$mode = (string)($argv[1] ?? '');
$selfSha = (string)hash_file('sha256', __FILE__);
$approved = $mode === '--execute'
    && (string)getenv('CDX_AR5_APPROVE') === 'ROOT_ARCHIVE_READ9_V1'
    && hash_equals($selfSha, (string)getenv('CDX_AR5_SHA'));
if (!in_array($lane, ['B', 'C'], true)
    || count($argv) !== 2
    || !in_array($mode, ['--preflight', '--execute', '--audit'], true)
    || ($mode === '--execute' && !$approved)) {
    echo json_encode(['status' => 'default_deny', 'connected' => false,
        'http_sent' => false, 'dml' => false]), PHP_EOL;
    exit(78);
}

$stage = 'bootstrap';
set_exception_handler(static function (Throwable $error) use (&$stage): void {
    echo json_encode(['status' => 'redacted_stop', 'stage' => $stage,
        'class' => get_class($error), 'code' => (string)$error->getCode(),
        'message_sha' => hash('sha256', $error->getMessage()),
        'recovery' => 'inspect_private_journal_if_present']), PHP_EOL;
    exit(2);
});

[$root, $pid, $port, $dialect] = [
    'B' => ['/tmp/zhct-http-store-mysql.dQTTBP', 10001, 18081, 'mysql'],
    'C' => ['/tmp/zhct-dm-poc-20260928.fcpiiN/store', 112175, 18080, 'dm'],
][$lane];
$sourceHashes = [
    '/application/p/controller/NationalHistory.php' => '3eab69c12c7776433f5e772625c4227a5ecbfba54ac0521ec57d204239bb8c4d',
    '/application/p/controller/PhysicalMature.php' => 'a56042454db4ff6fc7811444eb02883e00cda276b899688c7e5f43708c7f699b',
    '/application/p/controller/ProfessionEvaluation.php' => '8a270a924da649e9ae1ec26718c86cec91d26d60e891b246efbd75d8fd7cc546',
    '/application/p/controller/QuitTeam.php' => '6d8e1f8a44aba739066a7c3709868339eb9096ebf725f1492070e1d909fbbc8f',
    '/application/p/controller/RegisterManagement.php' => '2591c2387293580b87c69d81ed90837a95207153e494afcedca3d742851c34ef',
    '/application/p/controller/RegistrationSheet.php' => 'addab0f535f931364336a0a5c0dc302b9c074b0110675add65baa3a6289ae5dc',
    '/application/p/logic/NationalHistory.php' => '3cbafdff4314877462647087a45be9f436b0df35dc44a8cee099ec56ed41c05a',
    '/application/p/logic/PhysicalMature.php' => 'bd2296eb9567f74633f13c9334e119d9e43e1c5e7be355a8c9357b4272009571',
    '/application/p/logic/ProfessionEvaluation.php' => '43b9abc0b6d99f14f5b88c5fe9ccfc620155cc4fdc93673e69b9ead017a320f7',
    '/application/p/logic/QuitTeam.php' => 'f7bd673a2c02971c131885ae64dc58a4d9cfcbec227eba78bf01d7bd0ae0819c',
    '/application/p/logic/RegisterManagement.php' => 'aaa09bf6982be89a599318147a90a5b9d518602facfb1209a790f8154460f0aa',
    '/application/p/logic/RegistrationSheet.php' => '4fde91d3a761bb31f56f9121db6b45ba6db261c78f1d833b03177cbbd331f904',
    '/application/model/BaseModel.php' => '439740d6cf118e4541dfa719e120afd95979c497e7639f43d8efe01e6a5d3596',
    '/application/model/QuitTeam.php' => 'ad16f110993746b50e7900926cec40b36d0b1b9f741ebcff9ca58b76f66f45f9',
];
if (PHP_VERSION_ID < 70300 || PHP_VERSION_ID >= 70400 || is_link($root)) {
    throw new RuntimeException('Runtime/root drift');
}
foreach ($sourceHashes as $path => $sha) {
    if (!is_file($root . $path) || hash_file('sha256', $root . $path) !== $sha) {
        throw new RuntimeException('Business source drift');
    }
}

$stage = 'http_boundary';
$command = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
$childrenPath = '/proc/' . $pid . '/task/' . $pid . '/children';
$children = trim((string)@file_get_contents($childrenPath));
$base = 'http://127.0.0.1:' . $port;
$boundary = json_decode((string)@file_get_contents($base . '/__poc_boundary'), true);
if (strpos($command, $root . '/public') === false
    || strpos($command, '127.0.0.1:' . $port) === false
    || $children !== '' || !is_array($boundary)
    || ($boundary['external_stubs'] ?? null) !== true
    || ($boundary['redis_isolated'] ?? null) !== true
    || ($boundary['real_queue'] ?? true) !== false) {
    throw new RuntimeException('Isolated HTTP boundary drift');
}

$stage = 'database_boundary';
$runtime = require $root . '/application/database.php';
if ($dialect === 'mysql') {
    $local = require '/workspace/zhct/zhctproject/store/application/config/local/database.php';
    $expectedLocal = $local;
    $expectedLocal['hostport'] = (int)($local['hostport'] ?? 3306);
    $expectedLocal['type'] = (string)($local['type'] ?? 'mysql');
    foreach (['hostname', 'database', 'username', 'password'] as $key) {
        if (($runtime[$key] ?? null) !== ($expectedLocal[$key] ?? null)) {
            throw new RuntimeException('Not code-local development MySQL');
        }
    }
    if ((int)($runtime['hostport'] ?? 3306) !== $expectedLocal['hostport']
        || strtolower((string)($runtime['type'] ?? 'mysql')) !== strtolower($expectedLocal['type'])) {
        throw new RuntimeException('Not code-local development MySQL');
    }
    $dsn = 'mysql:host=' . $runtime['hostname'] . ';port=' . (int)$runtime['hostport']
        . ';dbname=' . $runtime['database'] . ';charset=' . ($runtime['charset'] ?? 'utf8');
} else {
    foreach (['hostname' => 'POC_HOST', 'hostport' => 'POC_PORT',
        'database' => 'POC_SCHEMA', 'username' => 'POC_USER',
        'password' => 'POC_PASSWORD'] as $key => $env) {
        if ((string)($runtime[$key] ?? '') !== (string)getenv($env)) {
            throw new RuntimeException('C runtime/worker DB drift');
        }
    }
    if ((string)getenv('POC_HOST') !== '127.0.0.1'
        || (string)getenv('POC_PORT') !== '5237'
        || strtoupper((string)getenv('POC_SCHEMA')) !== 'ZHCT_APP') {
        throw new RuntimeException('Not approved nonproduction DM');
    }
    $dsn = 'dm:host=127.0.0.1;port=5237;schema=ZHCT_APP';
}
$connect = static function () use ($dsn, $runtime): PDO {
    return new PDO($dsn, (string)$runtime['username'], (string)$runtime['password'], [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_CASE => PDO::CASE_LOWER,
        PDO::ATTR_TIMEOUT => 5,
    ]);
};
$db = $connect();
if ($dialect === 'mysql') {
    $identity = (string)$db->query(
        "SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")
        ->fetchColumn();
    if (hash('sha256', $identity)
        !== '003eb5aecf1cd4595b609c1f7f20b9ee325b578309fb9fe14fedaf77584fa401') {
        throw new RuntimeException('B DB identity drift');
    }
} elseif (strtoupper((string)$db->query(
    "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn()) !== 'ZHCT_APP') {
    throw new RuntimeException('C schema drift');
}

$logicalTables = ['user', 'department', 'staff', 'staff_department',
    'national_history', 'physical_mature', 'profession_evaluation',
    'quit_team', 'quit_team_ext', 'register_management', 'registration_sheet'];
$table = static function (string $name) use ($logicalTables, $dialect): string {
    if (!in_array($name, $logicalTables, true)) {
        throw new RuntimeException('Unapproved table');
    }
    return $dialect === 'dm' ? strtoupper('ydy_' . $name) : 'ydy_' . $name;
};
$required = [
    'user' => ['UUID','ACCOUNT','PWD','SALT','NAME','TYPE','STATUS','CREATE_TIME','CREATE_BY','IS_DELETE'],
    'department' => ['UUID','PUUID','NAME','CHARGE_BY','LEADER','LEAF_FLAG','STATUS','IS_SHOW','CREATE_TIME','CREATE_BY'],
    'staff' => ['UUID','STATION_UUID','IS_ATHLETE','NAME','BIRTHDAY','SPORT_UUID','SPORT_EVENT_UUID','IN_TIME','CREATE_TIME','CREATE_BY','PERSONNEL_UMBER','PERMANENT_ADDRESS','COACH_NAME','SPORT_YEAR','STATUS','IS_SHOW'],
    'staff_department' => ['DEPARTMENT_UUID','STAFF_UUID','CREATE_TIME','CREATE_BY'],
    'national_history' => ['UUID','STAFF_UUID','TEAM_NAME','TEAM_COACH','IN_TEAM_DATE','OUT_TEAM_DATE','DEMO','CREATE_TIME','CREATE_BY'],
    'physical_mature' => ['UUID','STAFF_UUID','TIME','HEIGHT','WEIGHT','FINGER_SPAN','LUNG','CREATE_TIME','CREATE_BY'],
    'profession_evaluation' => ['UUID','STAFF_UUID','PROFESSION','TIME','DEMO','CREATE_TIME','CREATE_BY'],
    'quit_team' => ['UUID','STAFF_UUID','PLACE','GRADE','PROJECT','CHARGE_COACH1','WHEREABOUTS','CHARGE_COACH2','CREATE_TIME','CREATE_BY'],
    'quit_team_ext' => ['UUID','STAFF_UUID','QUIT_TEAM_UUID','UPPER_NOTCH_TYPE','CHARGE_BY','TIME','ADVICE'],
    'register_management' => ['UUID','STAFF_UUID','REGISTER_ORGANIZATION','REGISTER_CERTIFICATE_NUMBER','REGISTER_NATURE','NATURE','SPORT_YEAR','TYPE','CREATE_TIME','CREATE_BY'],
    'registration_sheet' => ['UUID','STAFF_UUID','POLITIC_COUNTENANCE','CURRENT_COACH','MOBILE','BLOOD_TYPE','IDENTITY_NUMBER','ADDRESS','POLICE_STATION','FATHER','MOTHER','RESUME1','RESUME2','RESUME3','BONE_AGE','HEIGHT','WEIGHT','OFFICIAL_DATE','PREVIOUS_SCHOOL','FEEDING_UNIT','FEEDING_COACH','DEMO','CHARGE_COACH_ADVICE','SCIENTIFIC_ADVICE','LEADER_ADVICE','LEAVE_TEAM_DATE','TRAIN_LEVEL','WHEREABOUTS','TYPE','CREATE_TIME','CREATE_BY'],
];

$stage = 'metadata';
$columnsByTable = [];
$metadataDigestRows = [];
foreach ($logicalTables as $logical) {
    $physical = $table($logical);
    if ($dialect === 'mysql') {
        $stmt = $db->prepare('SELECT COLUMN_NAME,DATA_TYPE,COLUMN_TYPE,IS_NULLABLE,'
            . 'COLUMN_DEFAULT,EXTRA FROM INFORMATION_SCHEMA.COLUMNS'
            . ' WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY ORDINAL_POSITION');
        $stmt->execute([$physical]);
    } else {
        $stmt = $db->prepare('SELECT COLUMN_NAME,DATA_TYPE,DATA_LENGTH,DATA_PRECISION,'
            . 'DATA_SCALE,NULLABLE,DATA_DEFAULT FROM ALL_TAB_COLUMNS'
            . ' WHERE OWNER=? AND TABLE_NAME=? ORDER BY COLUMN_ID');
        $stmt->execute(['ZHCT_APP', $physical]);
    }
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    if ($rows === []) throw new RuntimeException('Required table absent');
    $columns = [];
    foreach ($rows as $row) {
        $name = strtoupper((string)$row['column_name']);
        $columns[$name] = $row;
        $metadataDigestRows[] = [$physical, $name, array_values($row)];
    }
    foreach ($required[$logical] as $name) {
        if (!isset($columns[$name])) throw new RuntimeException('Required column absent');
    }
    $columnsByTable[$logical] = $columns;
}

if ($dialect === 'mysql') {
    $names = implode(',', array_fill(0, count($logicalTables), '?'));
    $physicalNames = array_map($table, $logicalTables);
    $stmt = $db->prepare('SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS'
        . ' WHERE TRIGGER_SCHEMA=DATABASE() AND EVENT_OBJECT_TABLE IN (' . $names . ')');
    $stmt->execute($physicalNames); $triggerCount = (int)$stmt->fetchColumn();
    $stmt = $db->prepare('SELECT COUNT(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS'
        . ' WHERE CONSTRAINT_SCHEMA=DATABASE() AND (TABLE_NAME IN (' . $names . ')'
        . ' OR REFERENCED_TABLE_NAME IN (' . $names . '))');
    $stmt->execute(array_merge($physicalNames, $physicalNames));
    $foreignKeyCount = (int)$stmt->fetchColumn();
} else {
    $physicalNames = array_map($table, $logicalTables);
    $quotedNames = "'" . implode("','", $physicalNames) . "'";
    $triggerCount = (int)$db->query("SELECT COUNT(*) FROM ALL_TRIGGERS"
        . " WHERE OWNER='ZHCT_APP' AND TABLE_NAME IN (" . $quotedNames . ")")
        ->fetchColumn();
    $foreignKeyCount = (int)$db->query("SELECT COUNT(*) FROM ALL_CONSTRAINTS"
        . " WHERE OWNER='ZHCT_APP' AND CONSTRAINT_TYPE='R'"
        . " AND TABLE_NAME IN (" . $quotedNames . ")")->fetchColumn();
}
if ($triggerCount !== 0 || $foreignKeyCount !== 0) {
    throw new RuntimeException('Unreviewed trigger or foreign key');
}

$oldMarkerCount = 0;
foreach ($logicalTables as $logical) {
    $markerColumns = array_values(array_intersect(array_keys($columnsByTable[$logical]),
        ['UUID','STAFF_UUID','DEPARTMENT_UUID','QUIT_TEAM_UUID','CREATE_BY','ACCOUNT','NAME']));
    if ($markerColumns === []) continue;
    $where = implode(' OR ', array_map(static function (string $name): string {
        return $name . " LIKE 'CDXAR5%'";
    }, $markerColumns));
    $oldMarkerCount += (int)$db->query('SELECT COUNT(*) FROM ' . $table($logical)
        . ' WHERE ' . $where)->fetchColumn();
}

$journalPath = (string)getenv('CDX_AR5_JOURNAL');
$prefixZero = static function (PDO $pdo) use ($logicalTables, $columnsByTable, $table): int {
    $count = 0;
    foreach ($logicalTables as $logical) {
        $columns = array_values(array_intersect(array_keys($columnsByTable[$logical]),
            ['UUID','STAFF_UUID','DEPARTMENT_UUID','QUIT_TEAM_UUID','CREATE_BY','ACCOUNT','NAME']));
        if ($columns === []) continue;
        $where = implode(' OR ', array_map(static function (string $name): string {
            return $name . " LIKE 'CDXAR5%'";
        }, $columns));
        $count += (int)$pdo->query('SELECT COUNT(*) FROM ' . $table($logical)
            . ' WHERE ' . $where)->fetchColumn();
    }
    return $count;
};

if ($mode === '--audit') {
    $stage = 'independent_audit';
    if (!preg_match('~^/tmp/cdx-ar5-[a-f0-9]{12}/recovery\.json$~D', $journalPath)
        || is_link($journalPath) || is_link(dirname($journalPath))
        || !is_file($journalPath)
        || (fileperms(dirname($journalPath)) & 0777) !== 0700
        || (fileperms($journalPath) & 0777) !== 0600) {
        throw new RuntimeException('Audit journal invalid');
    }
    $saved = json_decode((string)file_get_contents($journalPath), true);
    if (!is_array($saved) || ($saved['lane'] ?? null) !== $lane
        || ($saved['phase'] ?? null) !== 'fixture_deleted'
        || !preg_match('/^CDXAR5[A-F0-9]{12}$/D', (string)($saved['marker'] ?? ''))) {
        throw new RuntimeException('Audit ownership invalid');
    }
    $fresh = $connect();
    $remaining = $prefixZero($fresh);
    if ($remaining !== 0) throw new RuntimeException('Fixture remains after cleanup');
    unlink($journalPath);
    rmdir(dirname($journalPath));
    echo json_encode(['status' => 'independent_zero_pass', 'lane' => $lane,
        'marker_rows' => 0, 'private_journal_removed' => true]), PHP_EOL;
    exit(0);
}

if ($mode === '--preflight') {
    echo json_encode(['status' => $oldMarkerCount === 0 ? 'select_only_ready' : 'marker_stop',
        'lane' => $lane, 'tables' => count($logicalTables),
        'metadata_sha' => hash('sha256', serialize($metadataDigestRows)),
        'foreign_keys' => $foreignKeyCount, 'triggers' => $triggerCount,
        'old_marker_rows' => $oldMarkerCount, 'http_sent' => false, 'dml' => false]), PHP_EOL;
    exit($oldMarkerCount === 0 ? 0 : 2);
}
if ($oldMarkerCount !== 0) throw new RuntimeException('Old fixture marker present');

$marker = 'CDXAR5' . strtoupper(bin2hex(random_bytes(6)));
$uuids = [
    'user' => $marker . 'U', 'department' => $marker . 'D', 'staff' => $marker . 'S',
    'national_history' => $marker . 'N', 'physical_mature' => $marker . 'P',
    'profession_evaluation' => $marker . 'E', 'quit_team' => $marker . 'Q',
    'register_management' => $marker . 'R', 'registration_sheet' => $marker . 'G',
    'quit_ext_1' => $marker . 'X1', 'quit_ext_2' => $marker . 'X2',
    'quit_ext_3' => $marker . 'X3', 'quit_ext_4' => $marker . 'X4',
];
$directory = '/tmp/cdx-ar5-' . strtolower(bin2hex(random_bytes(6)));
if (file_exists($directory) || !mkdir($directory, 0700)) {
    throw new RuntimeException('Private directory unavailable');
}
chmod($directory, 0700);
$journalPath = $directory . '/recovery.json';
$saved = ['lane' => $lane, 'marker' => $marker, 'phase' => 'before_insert',
    'uuids' => $uuids, 'ids' => []];
$save = static function () use (&$saved, $journalPath): void {
    if (file_put_contents($journalPath, json_encode($saved), LOCK_EX) === false
        || !chmod($journalPath, 0600)) {
        throw new RuntimeException('Journal write failed');
    }
};
$save();

$insert = static function (PDO $pdo, string $physical, array $data): void {
    $columns = array_keys($data);
    $sql = 'INSERT INTO ' . $physical . ' (' . implode(',', $columns) . ') VALUES ('
        . implode(',', array_fill(0, count($columns), '?')) . ')';
    $stmt = $pdo->prepare($sql);
    $stmt->execute(array_values($data));
    if ($stmt->rowCount() !== 1) throw new RuntimeException('Fixture insert mismatch');
};
$findId = static function (PDO $pdo, string $physical, array $where): int {
    $parts = [];
    foreach (array_keys($where) as $column) $parts[] = $column . '=?';
    $stmt = $pdo->prepare('SELECT ID FROM ' . $physical . ' WHERE ' . implode(' AND ', $parts));
    $stmt->execute(array_values($where));
    $ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
    if (count($ids) !== 1 || (int)$ids[0] <= 0) throw new RuntimeException('Fixture ownership ambiguous');
    return (int)$ids[0];
};
$fetchRows = static function (PDO $pdo, string $sql, array $params): array {
    $stmt = $pdo->prepare($sql); $stmt->execute($params);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
};
$snapshot = static function (PDO $pdo) use ($table, $marker, $uuids, $fetchRows): array {
    return [
        'user' => $fetchRows($pdo, 'SELECT * FROM ' . $table('user') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['user'], $marker]),
        'department' => $fetchRows($pdo, 'SELECT * FROM ' . $table('department') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['department'], $marker]),
        'staff' => $fetchRows($pdo, 'SELECT * FROM ' . $table('staff') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['staff'], $marker]),
        'staff_department' => $fetchRows($pdo, 'SELECT * FROM ' . $table('staff_department') . ' WHERE STAFF_UUID=? AND DEPARTMENT_UUID=? AND CREATE_BY=?', [$uuids['staff'], $uuids['department'], $marker]),
        'national_history' => $fetchRows($pdo, 'SELECT * FROM ' . $table('national_history') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['national_history'], $marker]),
        'physical_mature' => $fetchRows($pdo, 'SELECT * FROM ' . $table('physical_mature') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['physical_mature'], $marker]),
        'profession_evaluation' => $fetchRows($pdo, 'SELECT * FROM ' . $table('profession_evaluation') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['profession_evaluation'], $marker]),
        'quit_team' => $fetchRows($pdo, 'SELECT * FROM ' . $table('quit_team') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['quit_team'], $marker]),
        'quit_team_ext' => $fetchRows($pdo, 'SELECT * FROM ' . $table('quit_team_ext') . ' WHERE QUIT_TEAM_UUID=? AND STAFF_UUID=? ORDER BY UPPER_NOTCH_TYPE', [$uuids['quit_team'], $uuids['staff']]),
        'register_management' => $fetchRows($pdo, 'SELECT * FROM ' . $table('register_management') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['register_management'], $marker]),
        'registration_sheet' => $fetchRows($pdo, 'SELECT * FROM ' . $table('registration_sheet') . ' WHERE UUID=? AND CREATE_BY=?', [$uuids['registration_sheet'], $marker]),
    ];
};
$snapshotDigest = static function (array $rows): string {
    return hash('sha256', serialize($rows));
};
$now = date('Y-m-d H:i:s');
$result = ['status' => 'FAIL', 'lane' => $lane, 'cases' => []];
$failure = '';
$httpUncertain = false;
$fixtureCommitted = false;

try {
    $stage = 'fixture_insert';
    $db->beginTransaction();
    $insert($db, $table('user'), [
        'UUID'=>$uuids['user'],'ACCOUNT'=>$marker,'PWD'=>'DISABLED','SALT'=>strtoupper(bin2hex(random_bytes(8))),
        'NAME'=>$marker,'TYPE'=>0,'STATUS'=>0,'CREATE_TIME'=>$now,'CREATE_BY'=>$marker,'IS_DELETE'=>0,
    ]);
    $insert($db, $table('department'), [
        'UUID'=>$uuids['department'],'PUUID'=>'0','CODE'=>$marker,'NAME'=>$marker,
        'CHARGE_BY'=>$marker,'LEADER'=>$marker,'LEAF_FLAG'=>1,'ORDER_NO'=>0,
        'STATUS'=>0,'IS_SHOW'=>0,'DEPARTMENT_PATH'=>$marker,'DEMO'=>'归档兼容测试',
        'CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    $insert($db, $table('staff'), [
        'UUID'=>$uuids['staff'],'STATION_UUID'=>'0','IS_ATHLETE'=>1,'GRADE'=>1,
        'NAME'=>$marker,'SEX'=>1,'BIRTHDAY'=>'1999-02-03','HEIGHT'=>178,'WEIGHT'=>'70.50',
        'NATION'=>'测试','NATIVE_PLACE'=>'测试','IDENTITY_TYPE'=>1,'IDENTITY_NUMBER'=>$marker,
        'HEAD_IMG'=>$marker,'SPORT_UUID'=>'0','SPORT_EVENT_UUID'=>$marker,'IN_TIME'=>'2020-01-02',
        'MOBILE'=>'13900000000','EMAIL'=>'test@example.invalid','CREATE_TIME'=>$now,
        'CREATE_BY'=>$marker,'PERSONNEL_UMBER'=>substr($marker, -8),'IS_SHOW'=>0,'STATUS'=>0,
        'PERMANENT_ADDRESS'=>'测试地址','COACH_NAME'=>'测试教练','SPORT_YEAR'=>'1',
    ]);
    $insert($db, $table('staff_department'), [
        'DEPARTMENT_UUID'=>$uuids['department'],'STAFF_UUID'=>$uuids['staff'],
        'CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    $insert($db, $table('national_history'), [
        'UUID'=>$uuids['national_history'],'STAFF_UUID'=>$uuids['staff'],
        'TEAM_NAME'=>'测试国家队','TEAM_COACH'=>'测试教练','IN_TEAM_DATE'=>'2020-01-02',
        'OUT_TEAM_DATE'=>'2021-02-03','DEMO'=>'中文备注','CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    $insert($db, $table('physical_mature'), [
        'UUID'=>$uuids['physical_mature'],'STAFF_UUID'=>$uuids['staff'],'TIME'=>'2022-03-04',
        'HEIGHT'=>178,'WEIGHT'=>71,'FINGER_SPAN'=>180,'LUNG'=>4200,
        'CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    $insert($db, $table('profession_evaluation'), [
        'UUID'=>$uuids['profession_evaluation'],'STAFF_UUID'=>$uuids['staff'],
        'PROFESSION'=>'测试职称','TIME'=>'2023-04-05','DEMO'=>'中文说明',
        'CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    $insert($db, $table('quit_team'), [
        'UUID'=>$uuids['quit_team'],'STAFF_UUID'=>$uuids['staff'],'PLACE'=>'测试学籍地',
        'GRADE'=>'测试年级','PROJECT'=>'测试项目','CHARGE_COACH1'=>'教练甲',
        'WHEREABOUTS'=>'测试去向','CHARGE_COACH2'=>'教练乙','CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    for ($i = 1; $i <= 4; $i++) {
        $insert($db, $table('quit_team_ext'), [
            'UUID'=>$uuids['quit_ext_' . $i],'STAFF_UUID'=>$uuids['staff'],
            'QUIT_TEAM_UUID'=>$uuids['quit_team'],'UPPER_NOTCH_TYPE'=>$i,
            'CHARGE_BY'=>'审批人' . $i,'TIME'=>'2024-0' . $i . '-06','ADVICE'=>'测试意见' . $i,
        ]);
    }
    $insert($db, $table('register_management'), [
        'UUID'=>$uuids['register_management'],'STAFF_UUID'=>$uuids['staff'],
        'REGISTER_ORGANIZATION'=>'测试注册单位','REGISTER_CERTIFICATE_NUMBER'=>'10001',
        'REGISTER_NATURE'=>'测试注册性质','NATURE'=>'测试人员性质','SPORT_YEAR'=>'2025',
        'TYPE'=>1,'CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    $insert($db, $table('registration_sheet'), [
        'UUID'=>$uuids['registration_sheet'],'STAFF_UUID'=>$uuids['staff'],
        'POLITIC_COUNTENANCE'=>'测试','CURRENT_COACH'=>'测试教练','MOBILE'=>'13900000000',
        'BLOOD_TYPE'=>1,'IDENTITY_NUMBER'=>$marker,'ADDRESS'=>'测试地址','POLICE_STATION'=>'测试派出所',
        'FATHER'=>'父亲|单位甲|13900000001|175','MOTHER'=>'母亲|单位乙|13900000002|165',
        'RESUME1'=>'2020|学校甲|证明甲','RESUME2'=>'2021|学校乙|证明乙','RESUME3'=>'2022|学校丙|证明丙',
        'BONE_AGE'=>18,'HEIGHT'=>178,'WEIGHT'=>71,'OFFICIAL_DATE'=>null,
        'PREVIOUS_SCHOOL'=>'测试学校','FEEDING_UNIT'=>'测试单位','FEEDING_COACH'=>'测试教练',
        'DEMO'=>'中文备注','CHARGE_COACH_ADVICE'=>'同意','SCIENTIFIC_ADVICE'=>'同意',
        'LEADER_ADVICE'=>'同意','LEAVE_TEAM_DATE'=>'2025-05-06','TRAIN_LEVEL'=>'测试水平',
        'WHEREABOUTS'=>'测试去向','TYPE'=>1,'CREATE_TIME'=>$now,'CREATE_BY'=>$marker,
    ]);
    $saved['ids'] = [
        'user'=>$findId($db,$table('user'),['UUID'=>$uuids['user'],'ACCOUNT'=>$marker]),
        'department'=>$findId($db,$table('department'),['UUID'=>$uuids['department'],'CREATE_BY'=>$marker]),
        'staff'=>$findId($db,$table('staff'),['UUID'=>$uuids['staff'],'CREATE_BY'=>$marker]),
        'staff_department'=>$findId($db,$table('staff_department'),['STAFF_UUID'=>$uuids['staff'],'DEPARTMENT_UUID'=>$uuids['department']]),
        'national_history'=>$findId($db,$table('national_history'),['UUID'=>$uuids['national_history'],'CREATE_BY'=>$marker]),
        'physical_mature'=>$findId($db,$table('physical_mature'),['UUID'=>$uuids['physical_mature'],'CREATE_BY'=>$marker]),
        'profession_evaluation'=>$findId($db,$table('profession_evaluation'),['UUID'=>$uuids['profession_evaluation'],'CREATE_BY'=>$marker]),
        'quit_team'=>$findId($db,$table('quit_team'),['UUID'=>$uuids['quit_team'],'CREATE_BY'=>$marker]),
        'register_management'=>$findId($db,$table('register_management'),['UUID'=>$uuids['register_management'],'CREATE_BY'=>$marker]),
        'registration_sheet'=>$findId($db,$table('registration_sheet'),['UUID'=>$uuids['registration_sheet'],'CREATE_BY'=>$marker]),
    ];
    $db->commit();
    $fixtureCommitted = true;
    $saved['phase'] = 'fixture_committed'; $save();

    $source = $snapshot($connect());
    $expectedCounts = ['user'=>1,'department'=>1,'staff'=>1,'staff_department'=>1,
        'national_history'=>1,'physical_mature'=>1,'profession_evaluation'=>1,
        'quit_team'=>1,'quit_team_ext'=>4,'register_management'=>1,'registration_sheet'=>1];
    foreach ($expectedCounts as $name => $count) {
        if (count($source[$name]) !== $count) throw new RuntimeException('Fixture readback mismatch');
    }
    $sourceDigest = $snapshotDigest($source);

    require_once $root . '/application/base/Security.php';
    $token = \app\base\Security::encrypt(implode("\t", [
        (string)$saved['ids']['user'], $uuids['user'], $marker, '0', '', '', $marker,
    ]));
    $request = static function (string $path, array $form, string $token = '') use ($base, &$httpUncertain): array {
        $headers = "Content-Type: application/x-www-form-urlencoded\r\n";
        if ($token !== '') $headers .= 'token: ' . $token . "\r\n";
        $stream = @fopen($base . $path, 'rb', false,
            stream_context_create(['http' => ['method'=>'POST','timeout'=>20,
                'ignore_errors'=>true,'header'=>$headers,
                'content'=>http_build_query($form, '', '&', PHP_QUERY_RFC3986)]]));
        $raw = $stream === false ? false : stream_get_contents($stream, 1048577);
        $responseHeaders = $http_response_header ?? [];
        if (is_resource($stream)) fclose($stream);
        preg_match('/HTTP\/\S+\s+(\d+)/', (string)($responseHeaders[0] ?? ''), $match);
        $http = (int)($match[1] ?? 0);
        if ($stream === false || $raw === false || $http === 0) $httpUncertain = true;
        return [$http, is_string($raw) ? json_decode($raw, true) : null];
    };
    $shape = static function ($node) use (&$shape) {
        if (!is_array($node)) return gettype($node);
        if ($node === []) return [];
        $keys = array_keys($node);
        $isList = $keys === range(0, count($node) - 1);
        if ($isList) return ['[]' => $shape($node[0])];
        $out = [];
        foreach ($node as $key => $value) $out[(string)$key] = $shape($value);
        ksort($out);
        return $out;
    };
    $caseResult = static function (array $body, array $selectedTypes) use ($shape): array {
        $data = $body['data'] ?? null;
        $typeShape = $shape($data);
        $keyShape = is_array($data) ? array_keys($data) : [];
        sort($keyShape);
        return ['source_match'=>true,
            'key_sha'=>hash('sha256', serialize($keyShape)),
            'type_sha'=>hash('sha256', serialize($typeShape)),
            'selected_types'=>$selectedTypes];
    };
    $str = static function ($value): ?string {
        return $value === null ? null : rtrim((string)$value);
    };
    $findByUuid = static function ($rows, string $uuid) use ($str): ?array {
        if (!is_array($rows)) return null;
        foreach ($rows as $row) {
            if (is_array($row) && $str($row['uuid'] ?? null) === $uuid) return $row;
        }
        return null;
    };
    $routes = [
        'nationalHistory.lists'=>['/p/nationalHistory/lists',['staff_uuid'=>$uuids['staff'],'page'=>1]],
        'nationalHistory.info'=>['/p/nationalHistory/info',['uuid'=>$uuids['national_history']]],
        'physicalMature.lists'=>['/p/physicalMature/lists',['staff_uuid'=>$uuids['staff'],'page'=>1]],
        'physicalMature.info'=>['/p/physicalMature/info',['uuid'=>$uuids['physical_mature']]],
        'professionEvaluation.lists'=>['/p/professionEvaluation/lists',['staff_uuid'=>$uuids['staff'],'page'=>1]],
        'professionEvaluation.info'=>['/p/professionEvaluation/info',['uuid'=>$uuids['profession_evaluation']]],
        'quitTeam.info'=>['/p/quitTeam/info',['staff_uuid'=>$uuids['staff']]],
        'registerManagement.info'=>['/p/registerManagement/info',['staff_uuid'=>$uuids['staff'],'type'=>1]],
        'registrationSheet.info'=>['/p/registrationSheet/info',['staff_uuid'=>$uuids['staff']]],
    ];
    $stage = 'unauthenticated_http';
    foreach ($routes as $name => [$path, $form]) {
        [$http, $body] = $request($path, $form);
        if ($http !== 200 || !is_array($body) || (int)($body['code'] ?? 0) === 0) {
            throw new RuntimeException('Unauthenticated request not rejected');
        }
    }
    if ($snapshotDigest($snapshot($connect())) !== $sourceDigest) {
        throw new RuntimeException('Unauthenticated request changed fixture');
    }

    foreach ($routes as $name => [$path, $form]) {
        $stage = 'http_' . $name;
        [$http, $body] = $request($path, $form, $token);
        if ($http !== 200 || !is_array($body) || (int)($body['code'] ?? -1) !== 0) {
            throw new RuntimeException('Authenticated route failed');
        }
        $types = [];
        if ($name === 'nationalHistory.lists') {
            $row = $findByUuid($body['data']['rows'] ?? null, $uuids['national_history']);
            if (!is_array($row) || (int)($body['data']['total'] ?? -1) !== 1
                || $str($row['team_name'] ?? null) !== '测试国家队'
                || $str($row['in_team_date'] ?? null) !== '2020-01-02') {
                throw new RuntimeException('National list source mismatch');
            }
            $types = ['total'=>gettype($body['data']['total']),
                'in_team_date'=>gettype($row['in_team_date'])];
            [$h2,$b2] = $request($path,['staff_uuid'=>$uuids['staff'],'page'=>2],$token);
            if ($h2 !== 200 || (int)($b2['code'] ?? -1) !== 0
                || !isset($b2['data']['rows']) || $b2['data']['rows'] !== []
                || (int)($b2['data']['total'] ?? -1) !== 1) {
                throw new RuntimeException('National pagination mismatch');
            }
        } elseif ($name === 'nationalHistory.info') {
            $row = $body['data'] ?? null;
            if (!is_array($row) || $str($row['uuid'] ?? null) !== $uuids['national_history']
                || $str($row['out_team_date'] ?? null) !== '2021-02-03') {
                throw new RuntimeException('National info source mismatch');
            }
            $types = ['id'=>gettype($row['id'] ?? null),'out_team_date'=>gettype($row['out_team_date'] ?? null)];
        } elseif ($name === 'physicalMature.lists') {
            $row = $findByUuid($body['data']['rows'] ?? null, $uuids['physical_mature']);
            if (!is_array($row) || (int)($body['data']['total'] ?? -1) !== 1
                || (int)($row['height'] ?? -1) !== 178 || (int)($row['lung'] ?? -1) !== 4200
                || $str($row['time'] ?? null) !== '2022-03-04') {
                throw new RuntimeException('Physical list source mismatch');
            }
            $types = ['total'=>gettype($body['data']['total']),'height'=>gettype($row['height']),
                'weight'=>gettype($row['weight']),'finger_span'=>gettype($row['finger_span']),
                'lung'=>gettype($row['lung']),'time'=>gettype($row['time'])];
            [$h2,$b2] = $request($path,['staff_uuid'=>$uuids['staff'],'page'=>2],$token);
            if ($h2 !== 200 || (int)($b2['code'] ?? -1) !== 0
                || !isset($b2['data']['rows']) || $b2['data']['rows'] !== []
                || (int)($b2['data']['total'] ?? -1) !== 1) {
                throw new RuntimeException('Physical pagination mismatch');
            }
        } elseif ($name === 'physicalMature.info') {
            $row = $body['data'] ?? null;
            if (!is_array($row) || $str($row['uuid'] ?? null) !== $uuids['physical_mature']
                || (int)($row['weight'] ?? -1) !== 71) {
                throw new RuntimeException('Physical info source mismatch');
            }
            $types = ['id'=>gettype($row['id'] ?? null),'height'=>gettype($row['height'] ?? null),
                'weight'=>gettype($row['weight'] ?? null),'time'=>gettype($row['time'] ?? null)];
        } elseif ($name === 'professionEvaluation.lists') {
            $row = $findByUuid($body['data']['rows'] ?? null, $uuids['profession_evaluation']);
            if (!is_array($row) || (int)($body['data']['total'] ?? -1) !== 1
                || $str($row['profession'] ?? null) !== '测试职称'
                || $str($row['time'] ?? null) !== '2023-04-05') {
                throw new RuntimeException('Profession list source mismatch');
            }
            $types = ['total'=>gettype($body['data']['total']),'time'=>gettype($row['time'])];
            [$h2,$b2] = $request($path,['staff_uuid'=>$uuids['staff'],'page'=>2],$token);
            if ($h2 !== 200 || (int)($b2['code'] ?? -1) !== 0
                || !isset($b2['data']['rows']) || $b2['data']['rows'] !== []
                || (int)($b2['data']['total'] ?? -1) !== 1) {
                throw new RuntimeException('Profession pagination mismatch');
            }
        } elseif ($name === 'professionEvaluation.info') {
            $row = $body['data'] ?? null;
            if (!is_array($row) || $str($row['uuid'] ?? null) !== $uuids['profession_evaluation']
                || $str($row['profession'] ?? null) !== '测试职称') {
                throw new RuntimeException('Profession info source mismatch');
            }
            $types = ['id'=>gettype($row['id'] ?? null),'time'=>gettype($row['time'] ?? null)];
        } elseif ($name === 'quitTeam.info') {
            $row = $body['data'] ?? null; $ext = $row['quit_team_ext_result'] ?? null;
            if (!is_array($row) || $str($row['uuid'] ?? null) !== $uuids['quit_team']
                || !is_array($ext) || count($ext) !== 4) {
                throw new RuntimeException('Quit team source mismatch');
            }
            $seen = [];
            foreach ($ext as $item) {
                $kind = (int)($item['upper_notch_type'] ?? 0);
                if ($kind < 1 || $kind > 4 || isset($seen[$kind])
                    || $str($item['time'] ?? null) !== '2024-0' . $kind . '-06') {
                    throw new RuntimeException('Quit team ext mismatch');
                }
                $seen[$kind] = true;
            }
            $types = ['id'=>gettype($row['id'] ?? null),
                'upper_notch_type'=>gettype($ext[0]['upper_notch_type'] ?? null),
                'time'=>gettype($ext[0]['time'] ?? null),
                'raw_order'=>array_map(static function (array $item): int {
                    return (int)$item['upper_notch_type'];
                }, $ext)];
        } elseif ($name === 'registerManagement.info') {
            $row = $body['data'] ?? null;
            if (!is_array($row) || $str($row['uuid'] ?? null) !== $uuids['register_management']
                || (int)($row['type'] ?? 0) !== 1) {
                throw new RuntimeException('Register management source mismatch');
            }
            $types = ['id'=>gettype($row['id'] ?? null),'type'=>gettype($row['type'] ?? null)];
            [$h2,$b2] = $request($path,['staff_uuid'=>$uuids['staff'],'type'=>2],$token);
            if ($h2 !== 200 || (int)($b2['code'] ?? -1) !== 2
                || ($b2['data'] ?? null) !== []) {
                throw new RuntimeException('Register empty branch mismatch');
            }
        } elseif ($name === 'registrationSheet.info') {
            $row = $body['data'] ?? null;
            if (!is_array($row) || $str($row['staff_uuid'] ?? null) !== $uuids['staff']
                || $str($row['father_name'] ?? null) !== '父亲'
                || $str($row['father_height'] ?? null) !== '175'
                || $str($row['resume1_name'] ?? null) !== '证明甲'
                || !array_key_exists('official_date', $row) || $row['official_date'] !== null
                || $str($row['leave_team_date'] ?? null) !== '2025-05-06') {
                throw new RuntimeException('Registration sheet source mismatch');
            }
            $types = ['blood_type'=>gettype($row['blood_type'] ?? null),
                'bone_age'=>gettype($row['bone_age'] ?? null),'height'=>gettype($row['height'] ?? null),
                'weight'=>gettype($row['weight'] ?? null),'official_date'=>gettype($row['official_date'] ?? null),
                'father_height'=>gettype($row['father_height'] ?? null)];
        }
        $result['cases'][$name] = $caseResult($body, $types);
    }
    $stage = 'fixture_unchanged';
    if ($snapshotDigest($snapshot($connect())) !== $sourceDigest) {
        throw new RuntimeException('Read routes changed fixture');
    }
    $result['status'] = 'HTTP_PASS_PENDING_CLEANUP';
    $result['fixture_unchanged'] = true;
} catch (Throwable $error) {
    if ($db->inTransaction()) $db->rollBack();
    $failure = get_class($error) . ':' . (string)$error->getCode()
        . ':' . hash('sha256', $error->getMessage());
    $result['failure_stage'] = $stage;
}

if (!$fixtureCommitted) {
    $saved['phase'] = 'insert_rolled_back'; $save();
    unlink($journalPath); rmdir($directory);
    $result['cleanup'] = 'rollback_zero';
    $result['failure'] = $failure;
    echo json_encode($result, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), PHP_EOL;
    exit(2);
}
$afterBoundary = json_decode((string)@file_get_contents($base . '/__poc_boundary'), true);
if ($httpUncertain || !is_array($afterBoundary)
    || ($afterBoundary['external_stubs'] ?? null) !== true
    || ($afterBoundary['redis_isolated'] ?? null) !== true
    || ($afterBoundary['real_queue'] ?? true) !== false
    || trim((string)@file_get_contents($childrenPath)) !== '') {
    $saved['phase'] = 'uncertain_http_retain_fixture'; $save();
    echo json_encode(['status'=>'uncertain_http_retain_fixture','lane'=>$lane,
        'journal'=>$journalPath], JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(3);
}

$stage = 'reference_scan';
$scanReference = static function (PDO $pdo, string $column, string $value) use ($dialect): array {
    if ($dialect === 'mysql') {
        $stmt = $pdo->prepare('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS'
            . ' WHERE TABLE_SCHEMA=DATABASE() AND COLUMN_NAME=? ORDER BY TABLE_NAME');
        $stmt->execute([strtolower($column)]);
    } else {
        $stmt = $pdo->prepare('SELECT TABLE_NAME FROM ALL_TAB_COLUMNS'
            . ' WHERE OWNER=? AND COLUMN_NAME=? ORDER BY TABLE_NAME');
        $stmt->execute(['ZHCT_APP', strtoupper($column)]);
    }
    $out = [];
    foreach ($stmt->fetchAll(PDO::FETCH_COLUMN) as $physical) {
        if (!preg_match('/^YDY_[A-Z0-9_]+$/i', (string)$physical)) continue;
        $q = $pdo->prepare('SELECT COUNT(*) FROM ' . $physical . ' WHERE ' . strtoupper($column) . '=?');
        $q->execute([$value]); $count = (int)$q->fetchColumn();
        if ($count > 0) $out[strtoupper((string)$physical)] = $count;
    }
    ksort($out); return $out;
};
$expectedStaffRefs = [
    'YDY_NATIONAL_HISTORY'=>1,'YDY_PHYSICAL_MATURE'=>1,'YDY_PROFESSION_EVALUATION'=>1,
    'YDY_QUIT_TEAM'=>1,'YDY_QUIT_TEAM_EXT'=>4,'YDY_REGISTER_MANAGEMENT'=>1,
    'YDY_REGISTRATION_SHEET'=>1,'YDY_STAFF_DEPARTMENT'=>1,
];
ksort($expectedStaffRefs);
$expectedDepartmentRefs = ['YDY_STAFF_DEPARTMENT'=>1];
$refs = $connect();
$staffRefs = $scanReference($refs, 'STAFF_UUID', $uuids['staff']);
$departmentRefs = $scanReference($refs, 'DEPARTMENT_UUID', $uuids['department']);
if ($staffRefs !== $expectedStaffRefs || $departmentRefs !== $expectedDepartmentRefs) {
    $saved['phase'] = 'unexpected_reference_retain_fixture'; $save();
    echo json_encode(['status'=>'unexpected_reference_retain_fixture','lane'=>$lane,
        'journal'=>$journalPath,'staff_ref_sha'=>hash('sha256',serialize($staffRefs)),
        'department_ref_sha'=>hash('sha256',serialize($departmentRefs))],
        JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(4);
}

$stage = 'fixture_cleanup';
$clean = $connect();
$clean->beginTransaction();
$delete = static function (PDO $pdo, string $sql, array $params, int $expected): void {
    $stmt = $pdo->prepare($sql); $stmt->execute($params);
    if ($stmt->rowCount() !== $expected) throw new RuntimeException('Cleanup count mismatch');
};
try {
    $delete($clean, 'DELETE FROM ' . $table('quit_team_ext')
        . ' WHERE STAFF_UUID=? AND QUIT_TEAM_UUID=?', [$uuids['staff'],$uuids['quit_team']], 4);
    foreach (['national_history','physical_mature','profession_evaluation','quit_team',
        'register_management','registration_sheet'] as $logical) {
        $delete($clean, 'DELETE FROM ' . $table($logical)
            . ' WHERE ID=? AND UUID=? AND STAFF_UUID=? AND CREATE_BY=?',
            [$saved['ids'][$logical],$uuids[$logical],$uuids['staff'],$marker], 1);
    }
    $delete($clean, 'DELETE FROM ' . $table('staff_department')
        . ' WHERE ID=? AND STAFF_UUID=? AND DEPARTMENT_UUID=? AND CREATE_BY=?',
        [$saved['ids']['staff_department'],$uuids['staff'],$uuids['department'],$marker], 1);
    $delete($clean, 'DELETE FROM ' . $table('staff')
        . ' WHERE ID=? AND UUID=? AND CREATE_BY=?',
        [$saved['ids']['staff'],$uuids['staff'],$marker], 1);
    $delete($clean, 'DELETE FROM ' . $table('department')
        . ' WHERE ID=? AND UUID=? AND CREATE_BY=?',
        [$saved['ids']['department'],$uuids['department'],$marker], 1);
    $delete($clean, 'DELETE FROM ' . $table('user')
        . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?',
        [$saved['ids']['user'],$uuids['user'],$marker,$marker], 1);
    $clean->commit();
} catch (Throwable $error) {
    if ($clean->inTransaction()) $clean->rollBack();
    $saved['phase'] = 'cleanup_failed_retain_fixture'; $save();
    throw $error;
}
$saved['phase'] = 'fixture_deleted'; $save();
$remaining = $prefixZero($connect());
if ($remaining !== 0) throw new RuntimeException('Post-cleanup marker remains');
$result['cleanup'] = ['marker_rows'=>0,'staff_refs_before'=>$staffRefs,
    'department_refs_before'=>$departmentRefs,'journal'=>$journalPath];
if ($failure !== '') {
    $result['status'] = 'HTTP_FAIL_CLEANED'; $result['failure'] = $failure;
} else {
    $result['status'] = 'HTTP_PASS_CLEANED_PENDING_AUDIT';
}
echo json_encode($result, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), PHP_EOL;
exit($failure === '' ? 0 : 2);
