<?php
declare(strict_types=1);

// Three bounded Store PC reads, B/C only. No original A lane.
$mode = (string)($argv[1] ?? '');
$lane = (string)getenv('CDX_READ3_LANE');
$stage = 'entry';
set_exception_handler(static function (Throwable $e) use (&$stage, &$lane): void {
    echo json_encode(['status' => 'uncaught-before-http', 'lane' => $lane,
        'stage' => $stage, 'exception' => get_class($e),
        'message_sha256' => hash('sha256', $e->getMessage())]), PHP_EOL;
    exit(2);
});
if (!in_array($mode, ['--parent', '--execute', '--audit-zero'], true)
    || !in_array($lane, ['B', 'C'], true)
    || ($mode === '--execute' && (
        (string)getenv('CDX_READ3_APPROVAL') !== 'ROOT_APPROVED_BC_READ3_V1'
        || (string)getenv('CDX_READ3_SCRIPT_SHA') !== hash_file('sha256', __FILE__)))) {
    fwrite(STDERR, "READ3 default deny: business HTTP and DML disabled\n");
    exit(78);
}
$target = $lane === 'B'
    ? ['/tmp/zhct-http-store-mysql.dQTTBP', 'http://127.0.0.1:18081', 10001,
        '/usr/local/php7.3/bin/php', 'mysql',
        '003eb5aecf1cd4595b609c1f7f20b9ee325b578309fb9fe14fedaf77584fa401']
    : ['/tmp/zhct-dm-poc-20260928.fcpiiN/store', 'http://127.0.0.1:18080', 112175,
        '/www/server/php/73/bin/php', 'dm',
        'bc98485aed26beab348770a82ae38dbf922b04ab88a210cd7282c4caf0156194'];
[$root, $base, $pid, $php, $dialect, $expectedDbSha] = $target;
$preflightPath = $lane === 'B'
    ? '/workspace/zhct/zhctprompt/work_store/apifox/2026-09-30-dm8-interface-acceptance/parallel-store-read3-bc-20261004/preflight_read3.php'
    : '/tmp/cdx-store-read3-20261004/preflight_read3.php';
$preflightSha = '5f9a9832895def14060e9a32b07bb038a86853cb5256302e9aef138345dc49ed';
if (!is_file($preflightPath) || is_link($preflightPath)
    || hash_file('sha256', $preflightPath) !== $preflightSha) {
    throw new RuntimeException('Read-three preflight source drift');
}
$spawn = static function (string $mode, array $environment) use ($php, $lane): array {
    $command = escapeshellarg($php) . ' -d display_errors=0 -d log_errors=0';
    if ($lane === 'C') {
        $command .= ' -d extension=/home/dmdba/dmdbms/drivers/php_pdo/php73_pdo_dm.so';
    }
    $command .= ' ' . escapeshellarg(__FILE__) . ' ' . escapeshellarg($mode);
    $process = proc_open($command, [1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
        $pipes, null, $environment);
    if (!is_resource($process)) throw new RuntimeException('Read-three child unavailable');
    $stdout = stream_get_contents($pipes[1]);
    $stderr = stream_get_contents($pipes[2]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    return [proc_close($process), (string)$stdout, (string)$stderr];
};
if ($mode === '--parent') {
    $cmdline = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
    if (strpos($cmdline, $root . '/public') === false
        || strpos($cmdline, (string)parse_url($base, PHP_URL_PORT)) === false) {
        throw new RuntimeException('Read-three worker drift');
    }
    $environment = [];
    foreach (explode("\0", (string)@file_get_contents('/proc/' . $pid . '/environ')) as $entry) {
        $at = strpos($entry, '=');
        if ($at !== false) $environment[substr($entry, 0, $at)] = substr($entry, $at + 1);
    }
    if (!$environment || (string)($environment['POC_EXTERNAL_STUBS'] ?? '') !== '1'
        || ($lane === 'C' && (!is_file((string)($environment['DM_SVC_PATH'] ?? '') . '/dm_svc.conf')
            || strpos((string)file_get_contents((string)$environment['DM_SVC_PATH'] . '/dm_svc.conf'),
                'CHAR_CODE=(PG_UTF8)') === false))) {
        throw new RuntimeException('Read-three worker environment drift');
    }
    $environment['CDX_READ3_LANE'] = $lane;
    $environment['CDX_NEXT5_LANE'] = $lane;
    $environment['CDX_READ3_APPROVAL'] = (string)getenv('CDX_READ3_APPROVAL');
    $environment['CDX_READ3_SCRIPT_SHA'] = (string)getenv('CDX_READ3_SCRIPT_SHA');
    $environment['POC_APP_ROOT'] = $root;
    $environment['POC_BASE_URL'] = $base;
    $environment['POC_DIALECT'] = $dialect;
    [$exit, $stdout, $stderr] = $spawn('--execute', $environment);
    $lines = array_values(array_filter(explode("\n", trim($stdout)), 'strlen'));
    $result = json_decode((string)end($lines), true);
    if (!is_array($result)) {
        echo json_encode(['status' => 'child-output-unknown', 'exit' => $exit,
            'stdout_sha12' => substr(hash('sha256', $stdout), 0, 12),
            'stderr_sha12' => substr(hash('sha256', $stderr), 0, 12)]), PHP_EOL;
        exit(2);
    }
    echo json_encode($result, JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit($exit);
}

$stage = 'runtime-config';
$runtime = require $root . '/application/database.php';
if (!is_array($runtime) || (string)getenv('POC_APP_ROOT') !== $root
    || (string)getenv('POC_BASE_URL') !== $base
    || (string)getenv('POC_DIALECT') !== $dialect
    || (string)($runtime['prefix'] ?? '') !== 'ydy_') {
    throw new RuntimeException('Read-three target config drift');
}
$prefix = $dialect === 'dm' ? 'YDY_' : 'ydy_';
$table = static function (string $name) use ($prefix, $dialect): string {
    if (!preg_match('/^[a-z_]+$/', $name)) throw new RuntimeException('Table not allowed');
    return $prefix . ($dialect === 'dm' ? strtoupper($name) : strtolower($name));
};
$dsn = $dialect === 'dm'
    ? 'dm:host=127.0.0.1;port=5237;schema=ZHCT_APP'
    : 'mysql:host=' . $runtime['hostname'] . ';port=' . (int)($runtime['hostport'] ?? 3306)
        . ';dbname=' . $runtime['database'] . ';charset=' . $runtime['charset'];
$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]);
};
$identity = static function (PDO $pdo) use ($dialect, $expectedDbSha): bool {
    $actual = $dialect === 'dm'
        ? 'ZHCT_APP|5237|' . (string)$pdo->query(
            "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn()
        : (string)$pdo->query(
            "SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")
            ->fetchColumn();
    return hash_equals($expectedDbSha, hash('sha256', $actual));
};
$rows = static function (PDO $pdo, string $sql, array $args = [], int $cap = 5000): array {
    if (!preg_match('/^SELECT\b/i', $sql)) throw new RuntimeException('SELECT-only source');
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    $result = [];
    while (($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== false) {
        if (count($result) >= $cap) throw new RuntimeException('Source row cap exceeded');
        $clean = [];
        foreach (array_change_key_case($row, CASE_LOWER) as $key => $value) {
            $clean[$key] = is_resource($value) ? stream_get_contents($value) : $value;
        }
        ksort($clean);
        $result[] = $clean;
    }
    return $result;
};
$count = static function (PDO $pdo, string $sql, array $args = []) use ($rows): int {
    $result = $rows($pdo, $sql, $args, 1);
    return (int)($result[0]['n'] ?? -1);
};
$stage = 'db-connect';
$db = $connect();
if (!$identity($db)) throw new RuntimeException('Read-three DB identity drift');
if ($mode === '--audit-zero') {
    $marker = (string)getenv('CDX_READ3_MARKER');
    if (!preg_match('/^CDXR3[A-F0-9]{12}$/', $marker)) {
        throw new RuntimeException('Audit marker invalid');
    }
    $remaining = $count($db, 'SELECT COUNT(*) AS N FROM ' . $table('user')
        . ' WHERE UUID=? OR ACCOUNT=?', [$marker, $marker]);
    echo json_encode(['status' => $remaining === 0 ? 'actor-zero' : 'actor-remains',
        'remaining' => $remaining, 'lane' => $lane]), PHP_EOL;
    exit($remaining === 0 ? 0 : 3);
}

$stage = 'old-boundary-preflight';
$preflightCommand = escapeshellarg($php) . ' -d display_errors=0 -d log_errors=0';
if ($lane === 'C') {
    $preflightCommand .= ' -d extension=/home/dmdba/dmdbms/drivers/php_pdo/php73_pdo_dm.so';
}
$preflightCommand .= ' ' . escapeshellarg($preflightPath) . ' --child';
$pf = proc_open($preflightCommand, [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pfPipes);
if (!is_resource($pf)) throw new RuntimeException('Read-three preflight unavailable');
$pfOut = stream_get_contents($pfPipes[1]);
$pfErr = stream_get_contents($pfPipes[2]);
fclose($pfPipes[1]);
fclose($pfPipes[2]);
$pfExit = proc_close($pf);
$pfMarker = 'READ3_JSON ';
$pfAt = strrpos((string)$pfOut, $pfMarker);
$pfData = $pfAt === false ? null : json_decode(substr((string)$pfOut, $pfAt + strlen($pfMarker)), true);
if ($pfExit !== 0 || !is_array($pfData) || ($pfData['status'] ?? '') !== 'preflight-pass'
    || ($pfData['lane'] ?? '') !== $lane) {
    throw new RuntimeException('Read-three source/environment preflight failed:'
        . hash('sha256', (string)$pfOut . (string)$pfErr));
}
$stage = 'natural-candidates';
$candidates = $rows($db, 'SELECT sd.DEPARTMENT_UUID AS D, COUNT(DISTINCT u.ID) AS N'
    . ' FROM ' . $table('staff_department') . ' sd'
    . ' JOIN ' . $table('user') . ' u ON u.STAFF_UUID=sd.STAFF_UUID AND u.IS_DELETE=0'
    . ' JOIN ' . $table('staff') . ' s ON s.UUID=sd.STAFF_UUID AND s.IS_SHOW=1 AND s.AI_USER_ID>0'
    . ' JOIN ' . $table('department') . ' d ON d.UUID=sd.DEPARTMENT_UUID AND d.IS_SHOW=1'
    . ' GROUP BY sd.DEPARTMENT_UUID HAVING COUNT(DISTINCT u.ID) BETWEEN 1 AND 8'
    . ' ORDER BY N, D');
$dept = '';
$supplementCount = 0;
$cashCount = 0;
foreach ($candidates as $candidate) {
    $candidateDept = (string)$candidate['d'];
    $n = $count($db, 'SELECT COUNT(DISTINCT u.ID) AS N FROM '
        . $table('staff_department') . ' sd JOIN ' . $table('user')
        . ' u ON u.STAFF_UUID=sd.STAFF_UUID AND u.IS_DELETE=0'
        . ' JOIN ' . $table('staff') . ' s ON s.UUID=sd.STAFF_UUID AND s.IS_SHOW=1'
        . ' WHERE sd.DEPARTMENT_UUID=?', [$candidateDept]);
    if ($n >= 1 && $n <= 8) {
        $dept = $candidateDept;
        $supplementCount = $n;
        $cashCount = (int)$candidate['n'];
        break;
    }
}
if ($dept === '' || substr(hash('sha256', $dept), 0, 12)
    !== (string)$pfData['bounded_department_sha12']
    || $supplementCount !== (int)$pfData['supplement_staff_rows']
    || $cashCount !== (int)$pfData['cash_staff_rows']) {
    throw new RuntimeException('Read-three bounded source changed before HTTP');
}
$source = static function (PDO $pdo) use ($rows, $table, $dept): array {
    $queries = [
        'restaurants' => ['SELECT ID,NAME FROM ' . $table('restaurants')
            . ' WHERE STATUS=1 AND IS_DELETE=2 ORDER BY ID', []],
        'departments' => ['SELECT UUID,NAME,PUUID FROM ' . $table('department')
            . ' WHERE IS_SHOW=1 ORDER BY ID', []],
        'equipments' => ['SELECT CODE,NAME,RESTAURANT_ID FROM ' . $table('equipment')
            . ' WHERE DEL_FLAG=0 AND TYPE=9 ORDER BY ID', []],
        'supplement_staff' => ['SELECT u.ID,u.NAME,u.STAFF_UUID,s.PERSONNEL_UMBER'
            . ' FROM ' . $table('staff_department') . ' sd'
            . ' JOIN ' . $table('user') . ' u ON u.STAFF_UUID=sd.STAFF_UUID AND u.IS_DELETE=0'
            . ' LEFT JOIN ' . $table('staff') . ' s ON s.UUID=sd.STAFF_UUID AND s.IS_SHOW=1'
            . ' WHERE sd.DEPARTMENT_UUID=? ORDER BY u.ID', [$dept]],
        'cash_staff' => ['SELECT DISTINCT s.UUID,s.NAME,s.MOBILE,s.PERSONNEL_UMBER,s.AI_USER_ID'
            . ' FROM ' . $table('staff') . ' s'
            . ' JOIN ' . $table('staff_department') . ' sd ON sd.STAFF_UUID=s.UUID'
            . ' WHERE sd.DEPARTMENT_UUID=? AND s.IS_SHOW=1 AND s.AI_USER_ID>0'
            . ' ORDER BY s.UUID', [$dept]],
    ];
    $out = [];
    foreach ($queries as $key => [$sql, $params]) {
        $values = $rows($pdo, $sql, $params);
        $out[$key] = $values;
    }
    return $out;
};
$fingerprint = static function (array $tables): array {
    $out = [];
    foreach ($tables as $name => $values) {
        $json = json_encode($values, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        if (!is_string($json)) throw new RuntimeException('Source fingerprint failed');
        $out[$name] = ['count' => count($values), 'sha256' => hash('sha256', $json)];
    }
    return $out;
};
$stage = 'source-snapshot';
$sourceBefore = $source($db);
$beforeHash = $fingerprint($sourceBefore);
if ($beforeHash['restaurants']['count'] < 1
    || $beforeHash['departments']['count'] < 1
    || $beforeHash['supplement_staff']['count'] < 1
    || $beforeHash['supplement_staff']['count'] > 8
    || $beforeHash['cash_staff']['count'] < 1
    || $beforeHash['cash_staff']['count'] > 8) {
    throw new RuntimeException('Read-three natural positive source absent');
}
$queue = static function (PDO $pdo) use ($count, $table): array {
    return [
        $count($pdo, 'SELECT COUNT(*) AS N FROM ' . $table('export_log')),
        $count($pdo, 'SELECT COUNT(*) AS N FROM ' . $table('export_log') . ' WHERE STATUS=0'),
    ];
};
$stage = 'queue-snapshot';
$queueBefore = $queue($db);
if ($queueBefore[0] < 0 || $queueBefore[1] !== 0) {
    throw new RuntimeException('Read-three queue not idle');
}
$marker = 'CDXR3' . strtoupper(bin2hex(random_bytes(6)));
if ($count($db, 'SELECT COUNT(*) AS N FROM ' . $table('user')
    . ' WHERE UUID=? OR ACCOUNT=?', [$marker, $marker]) !== 0) {
    throw new RuntimeException('Read-three marker collision');
}
$stage = 'pre-actor-journal';
$privateDir = sys_get_temp_dir() . '/zhct-read3-' . $marker;
if (file_exists($privateDir) || !mkdir($privateDir, 0700)) {
    throw new RuntimeException('Read-three private journal unavailable');
}
$journalPath = $privateDir . '/recovery.json';
$actorId = 0;
$httpSent = false;
$httpConfirmed = true;
$cleaned = false;
$sourceUnchanged = false;
$queueUnchanged = false;
$result = ['lane' => $lane, 'status' => 'running', 'routes' => [],
    'source_counts' => array_map(static function (array $item): int {
        return (int)$item['count'];
    }, $beforeHash),
    'bounded_department_sha12' => substr(hash('sha256', $dept), 0, 12)];
$journal = ['lane' => $lane, 'marker' => $marker, 'state' => 'prepared',
    'source_hashes' => $beforeHash, 'queue' => $queueBefore];
$saveJournal = static function () use (&$journal, $journalPath): void {
    if (file_put_contents($journalPath, json_encode($journal, JSON_UNESCAPED_SLASHES)) === false) {
        throw new RuntimeException('Read-three journal write failed');
    }
    chmod($journalPath, 0600);
};
$saveJournal();
$runtimeReady = static function () use ($pid, $base, $root): bool {
    $cmdline = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
    $children = trim((string)@file_get_contents('/proc/' . $pid . '/task/' . $pid . '/children'));
    $boundary = json_decode((string)@file_get_contents($base . '/__poc_boundary'), true);
    return strpos($cmdline, $root . '/public') !== false
        && strpos($cmdline, (string)parse_url($base, PHP_URL_PORT)) !== false
        && $children === '' && is_array($boundary)
        && !empty($boundary['external_stubs']) && !empty($boundary['redis_isolated'])
        && empty($boundary['real_queue']);
};
$post = static function (string $path, array $form, string $token, int $cap)
    use ($base, $runtimeReady, &$httpSent, &$httpConfirmed): array {
    if (!in_array($path, ['/p/supplementMealOrder/options',
        '/p/supplementMealOrder/staffOptions', '/p/cashRefund/staffOptions'], true)
        || !$runtimeReady()) throw new RuntimeException('Read-three path/runtime drift');
    $headers = "Content-Type: application/x-www-form-urlencoded\r\ntoken: " . $token . "\r\n";
    $context = stream_context_create(['http' => ['method' => 'POST',
        'header' => $headers,
        'content' => http_build_query($form, '', '&', PHP_QUERY_RFC3986),
        'timeout' => 20, 'ignore_errors' => true]]);
    $httpSent = true;
    $httpConfirmed = false;
    $stream = @fopen($base . $path, 'rb', false, $context);
    $body = is_resource($stream) ? stream_get_contents($stream, $cap + 1) : false;
    $meta = is_resource($stream) ? stream_get_meta_data($stream) : [];
    if (is_resource($stream)) fclose($stream);
    if (!is_string($body) || !empty($meta['timed_out']) || strlen($body) > $cap) {
        throw new RuntimeException('Read-three HTTP outcome incomplete');
    }
    $httpConfirmed = true;
    $headersOut = $http_response_header ?? [];
    if (strpos((string)($headersOut[0] ?? ''), ' 200 ') === false) {
        throw new RuntimeException('Read-three HTTP status mismatch');
    }
    $json = json_decode($body, true);
    if (!is_array($json) || (int)($json['code'] ?? -1) !== 0
        || !isset($json['data']) || !is_array($json['data'])) {
        throw new RuntimeException('Read-three business envelope mismatch');
    }
    return $json;
};
$shape = static function (array $value): array {
    $out = [];
    foreach ($value as $key => $item) $out[(string)$key] = gettype($item);
    ksort($out);
    return $out;
};
$failure = '';
try {
    if (!$runtimeReady() || !$identity($connect())
        || $fingerprint($source($connect())) !== $beforeHash
        || $queue($connect()) !== $queueBefore) {
        throw new RuntimeException('Read-three pre-actor boundary/source drift');
    }
    $stmt = $db->prepare('INSERT INTO ' . $table('user')
        . ' (UUID,ACCOUNT,PWD,SALT,NAME,TYPE,CREATE_TIME,CREATE_BY,IS_DELETE)'
        . ' VALUES (?,?,?,?,?,?,?,?,?)');
    $stmt->execute([$marker, $marker, 'DISABLED', strtoupper(bin2hex(random_bytes(8))),
        $marker, 0, date('Y-m-d H:i:s'), 'CODEX', 0]);
    if ($stmt->rowCount() !== 1) throw new RuntimeException('Read-three actor insert failed');
    $actor = $rows($db, 'SELECT ID FROM ' . $table('user')
        . ' WHERE UUID=? AND ACCOUNT=? AND NAME=? AND TYPE=0 AND CREATE_BY=?',
        [$marker, $marker, $marker, 'CODEX'], 2);
    if (count($actor) !== 1 || (int)$actor[0]['id'] <= 0) {
        throw new RuntimeException('Read-three actor ID ambiguous');
    }
    $actorId = (int)$actor[0]['id'];
    $journal['actor_id'] = $actorId;
    $journal['state'] = 'actor_committed';
    $saveJournal();
    require_once $root . '/application/base/Security.php';
    $token = \app\base\Security::encrypt(implode("\t",
        [(string)$actorId, $marker, $marker, '0', '', '', $marker]));
    if (!is_string($token) || $token === '') {
        throw new RuntimeException('Read-three isolated token unavailable');
    }
    $calls = [
        'supplement_options' => ['/p/supplementMealOrder/options', [], 4194304],
        'supplement_staff' => ['/p/supplementMealOrder/staffOptions',
            ['department_uuid' => $dept], 524288],
        'cash_staff' => ['/p/cashRefund/staffOptions',
            ['department_uuid' => $dept, 'keyword' => ''], 524288],
    ];
    foreach ($calls as $key => [$path, $form, $cap]) {
        $json = $post($path, $form, $token, $cap);
        $data = $json['data'];
        if ($key === 'supplement_options') {
            foreach (['restaurants', 'equipments', 'departments'] as $group) {
                if (!isset($data[$group]) || !is_array($data[$group])
                    || count($data[$group]) !== count($sourceBefore[$group])) {
                    throw new RuntimeException('Read-three option source cardinality mismatch');
                }
                $id = $group === 'restaurants' ? 'id'
                    : ($group === 'equipments' ? 'code' : 'uuid');
                $src = [];
                foreach ($sourceBefore[$group] as $row) $src[(string)$row[$id]] = $row;
                foreach ($data[$group] as $row) {
                    if (!is_array($row) || !isset($row[$id])
                        || !isset($src[(string)$row[$id]])
                        || (string)($row['name'] ?? '') !== (string)$src[(string)$row[$id]]['name']) {
                        throw new RuntimeException('Read-three option source value mismatch');
                    }
                }
            }
            $rowCount = count($data['restaurants']) + count($data['departments'])
                + count($data['equipments']);
            $type = [
                'envelope' => $shape($json), 'data' => $shape($data),
                'restaurants' => $shape($data['restaurants'][0]),
                'departments' => $shape($data['departments'][0]),
                'equipments' => $data['equipments'] ? $shape($data['equipments'][0]) : [],
            ];
        } else {
            $src = [];
            $id = $key === 'supplement_staff' ? 'id' : 'uuid';
            foreach ($sourceBefore[$key] as $row) $src[(string)$row[$id]] = $row;
            if (count($data) !== count($src) || !$data) {
                throw new RuntimeException('Read-three staff source cardinality mismatch');
            }
            foreach ($data as $row) {
                if (!is_array($row) || !isset($row[$id])
                    || !isset($src[(string)$row[$id]])) {
                    throw new RuntimeException('Read-three staff source identity mismatch');
                }
                foreach ($src[(string)$row[$id]] as $field => $sourceValue) {
                    if (!array_key_exists($field, $row)
                        || (string)$row[$field] !== (string)$sourceValue) {
                        throw new RuntimeException('Read-three staff source value mismatch');
                    }
                }
            }
            $rowCount = count($data);
            $type = ['envelope' => $shape($json), 'row' => $shape($data[0])];
        }
        $result['routes'][$key] = [
            'path' => $path, 'code' => $json['code'], 'nonempty_rows' => $rowCount,
            'type_shape' => $type,
            'type_sha256' => hash('sha256', json_encode($type, JSON_UNESCAPED_SLASHES)),
            'source_match' => true,
        ];
    }
    $afterDb = $connect();
    if (!$identity($afterDb)) throw new RuntimeException('Read-three post-HTTP identity drift');
    $sourceUnchanged = $fingerprint($source($afterDb)) === $beforeHash;
    $queueUnchanged = $queue($afterDb) === $queueBefore;
    if (!$sourceUnchanged || !$queueUnchanged) {
        throw new RuntimeException('Read-three source/queue changed in window');
    }
} catch (Throwable $e) {
    $failure = get_class($e) . ':' . hash('sha256', $e->getMessage());
} finally {
    $cleanupSafe = (!$httpSent || $httpConfirmed || !is_dir('/proc/' . $pid))
        && (!is_dir('/proc/' . $pid) || $runtimeReady());
    if ($cleanupSafe) {
        try {
            $cleanup = $connect();
            if (!$identity($cleanup)) throw new RuntimeException('Read-three cleanup DB drift');
            $owned = $rows($cleanup, 'SELECT ID,UUID,ACCOUNT,NAME,TYPE,CREATE_BY'
                . ' FROM ' . $table('user') . ' WHERE UUID=? OR ACCOUNT=?',
                [$marker, $marker], 2);
            if (count($owned) > 1) throw new RuntimeException('Read-three cleanup owner ambiguous');
            foreach ($owned as $row) {
                if ((int)$row['id'] !== $actorId || (string)$row['uuid'] !== $marker
                    || (string)$row['account'] !== $marker
                    || (string)$row['name'] !== $marker
                    || (int)$row['type'] !== 0
                    || (string)$row['create_by'] !== 'CODEX'
                    || $count($cleanup, 'SELECT COUNT(*) AS N FROM ' . $table('user_role')
                        . ' WHERE USER_UUID=?', [$marker]) !== 0
                    || $count($cleanup, 'SELECT COUNT(*) AS N FROM ' . $table('user_data')
                        . ' WHERE USER_UUID=?', [$marker]) !== 0) {
                    throw new RuntimeException('Read-three cleanup ownership/relation drift');
                }
                $cleanup->beginTransaction();
                try {
                    $del = $cleanup->prepare('DELETE FROM ' . $table('user')
                        . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND NAME=?'
                        . ' AND TYPE=0 AND CREATE_BY=?');
                    $del->execute([$actorId, $marker, $marker, $marker, 'CODEX']);
                    if ($del->rowCount() !== 1) throw new RuntimeException('Read-three delete affected mismatch');
                    $cleanup->commit();
                } catch (Throwable $e) {
                    if ($cleanup->inTransaction()) $cleanup->rollBack();
                    throw $e;
                }
            }
            $auditEnv = [];
            foreach (explode("\0", (string)@file_get_contents('/proc/' . $pid . '/environ')) as $entry) {
                $at = strpos($entry, '=');
                if ($at !== false) $auditEnv[substr($entry, 0, $at)] = substr($entry, $at + 1);
            }
            $auditEnv['CDX_READ3_LANE'] = $lane;
            $auditEnv['CDX_READ3_MARKER'] = $marker;
            $auditEnv['POC_APP_ROOT'] = $root;
            $auditEnv['POC_BASE_URL'] = $base;
            $auditEnv['POC_DIALECT'] = $dialect;
            [$auditExit, $auditOut] = $spawn('--audit-zero', $auditEnv);
            $audit = json_decode(trim($auditOut), true);
            if ($auditExit !== 0 || !is_array($audit)
                || ($audit['status'] ?? '') !== 'actor-zero') {
                throw new RuntimeException('Read-three independent actor-zero failed');
            }
            $cleaned = true;
        } catch (Throwable $e) {
            $failure .= ($failure === '' ? '' : ';') . 'cleanup:'
                . get_class($e) . ':' . hash('sha256', $e->getMessage());
        }
    } else {
        $failure .= ($failure === '' ? '' : ';') . 'cleanup:unknown_http_outcome';
    }
    if ($cleaned) {
        @unlink($journalPath);
        @rmdir($privateDir);
    } else {
        $journal['state'] = 'requires_manual_recovery';
        try { $saveJournal(); } catch (Throwable $e) { /* retain prior file */ }
    }
}
$result['status'] = $failure === '' && count($result['routes']) === 3
    && $sourceUnchanged && $queueUnchanged && $cleaned ? 'pass' : 'stop';
$result['source_unchanged'] = $sourceUnchanged;
$result['queue_unchanged'] = $queueUnchanged;
$result['actor_independent_zero'] = $cleaned;
$result['private_journal_removed'] = $cleaned && !file_exists($journalPath);
$result['recovery_pointer'] = $cleaned ? null : $privateDir;
$result['failure'] = $failure;
echo json_encode($result, JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE), PHP_EOL;
exit($result['status'] === 'pass' ? 0 : 1);
