<?php
declare(strict_types=1);

// PHASED two-worker lifecycle draft. Hard-blocked from stage/health/stop.
const LIFECYCLE_STAGING_REVIEWED = true;
$phase = $argv[1] ?? '';
$lane = (string)getenv('CDX_EM_RACE_LANE');
$flags = [
    '--plan' => ['CDX_EM_RACE_PLAN', 'ROOT_APPROVED_STATIC_RACE_PLAN_V1'],
    '--stage' => ['CDX_EM_RACE_STAGE', 'ROOT_APPROVED_PRIVATE_STAGE_ONLY_V1'],
    '--health' => ['CDX_EM_RACE_HEALTH', 'ROOT_APPROVED_PRIVATE_WORKER_HEALTH_V1'],
    '--stop' => ['CDX_EM_RACE_STOP', 'ROOT_APPROVED_PRIVATE_WORKER_STOP_V1'],
];
if (!in_array($lane, ['A', 'B', 'C'], true)
    || count($argv) !== 2 || !isset($flags[$phase])
    || (string)getenv($flags[$phase][0]) !== $flags[$phase][1]
    || !hash_equals((string)hash_file('sha256', __FILE__),
        (string)getenv('CDX_EM_RACE_LIFECYCLE_SHA'))) {
    echo json_encode(['status' => 'default-deny', 'db_connected' => false,
        'workers_started' => false, 'business_http_sent' => false,
        'dml_sent' => false]), PHP_EOL;
    exit(78);
}
if ($phase !== '--plan') {
    if (!LIFECYCLE_STAGING_REVIEWED) {
        echo json_encode(['status' => 'stage-review-blocked',
            'db_connected' => false, 'workers_started' => false,
            'business_http_sent' => false, 'dml_sent' => false]), PHP_EOL;
        exit(78);
    }
}
$stage = 'static_identity';
$recoveryJournal = '';
set_exception_handler(static function (Throwable $error)
    use (&$stage, &$recoveryJournal): void {
    echo json_encode(['status' => 'redacted_stop', 'stage' => $stage,
        'error_class' => get_class($error), 'code' => (string)$error->getCode(),
        'reason_sha' => hash('sha256', $error->getMessage()),
        'private_recovery_pointer' => $recoveryJournal === ''
            ? null : $recoveryJournal,
        'private_journal_exists' => $recoveryJournal !== ''
            && is_file($recoveryJournal),
        'recovery' => 'retain_private_journal_if_any']), PHP_EOL;
    exit(2);
});
$targets = [
    'A' => ['/tmp/zhct-http-store-a.l5omH8', 21023, 'mysql'],
    'B' => ['/tmp/zhct-http-store-mysql.dQTTBP', 10001, 'mysql'],
    'C' => ['/tmp/zhct-dm-poc-20260928.fcpiiN/store', 112175, 'dm'],
];
[$sourceRoot, $sourcePid, $dialect] = $targets[$lane];
$preflight = __DIR__ . '/preflight_bind_race.php';
$router = __DIR__ . '/race_router.disabled.php';
$archiveLib = __DIR__ . '/race_archive_lib.php';
$exitPolicy = __DIR__ . '/race_worker_exit_policy.php';
if (PHP_VERSION_ID < 70300 || PHP_VERSION_ID >= 70400
    || is_link($sourceRoot)
    || !hash_equals('915131476db82d3ab5c1a22a8fc460d8980bab07785fe53a3556988861717887',
        (string)hash_file('sha256', $preflight))
    || !hash_equals('6948d53a106884f58e772cbbb2afda7e44db6bddb2b513a22c5a93cb6758f700',
        (string)hash_file('sha256', $router))
    || !hash_equals('4b177ec05c2fc73779c837d13fd01f36f9b8e088f7a9b2313ba24c680beaab78',
        (string)hash_file('sha256', $archiveLib))
    || !hash_equals('c0052624d502a095930368fd82d8e6429a387e183a163f0fa8f5b6f5d8ba16ba',
        (string)hash_file('sha256', $exitPolicy))) {
    throw new RuntimeException('Source or runtime preflight drift');
}
require_once $archiveLib;
require_once $exitPolicy;
$runtimeSource = ['application/common/service/ElectronicMenuDevice.php'
        => '3335769aee94126f7abfae2f2a305ba09cca9270df2ab7590657c00fabef855f',
    'application/api/controller/ElectronicMenu.php'
        => '2c1df1125c5ced2abd4f97a460f4290950d8ca5fbb978d63800e76ba5d60e056'];
if ($phase !== '--stop') {
    foreach ($runtimeSource as $file => $sha) {
        if (!hash_equals($sha, (string)hash_file('sha256', $sourceRoot . '/' . $file))) {
            throw new RuntimeException('Frozen business source changed');
        }
    }
}
$readWorkerEnvironment = static function (int $pid): array {
    $raw = (string)@file_get_contents('/proc/' . $pid . '/environ');
    if ($raw === '') throw new RuntimeException('Original isolated worker absent');
    $environment = ['PATH' => (string)getenv('PATH')];
    foreach (explode("\0", $raw) as $entry) {
        $at = strpos($entry, '=');
        if ($at === false) continue;
        $key = substr($entry, 0, $at);
        if (strpos($key, 'POC_') === 0
            || in_array($key, ['LD_LIBRARY_PATH', 'DM_SVC_PATH'], true)) {
            $environment[$key] = substr($entry, $at + 1);
        }
    }
    return $environment;
};
$ownsListener = static function (int $pid, int $port): bool {
    $hex = strtoupper(str_pad(dechex($port), 4, '0', STR_PAD_LEFT));
    $lines = @file('/proc/net/tcp', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    if (!is_array($lines)) return false;
    $inodes = [];
    foreach (array_slice($lines, 1) as $line) {
        $parts = preg_split('/\s+/', trim($line));
        if (is_array($parts) && ($parts[1] ?? '') === '0100007F:' . $hex
            && ($parts[3] ?? '') === '0A') $inodes[] = (string)($parts[9] ?? '');
    }
    if (count($inodes) !== 1 || $inodes[0] === '') return false;
    foreach (glob('/proc/' . $pid . '/fd/*') ?: [] as $fd) {
        if (@readlink($fd) === 'socket:[' . $inodes[0] . ']') return true;
    }
    return false;
};
$portListening = static function (int $port): bool {
    $hex = strtoupper(str_pad(dechex($port), 4, '0', STR_PAD_LEFT));
    $lines = @file('/proc/net/tcp', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    if (!is_array($lines)) throw new RuntimeException('Socket table unavailable');
    foreach (array_slice($lines, 1) as $line) {
        $parts = preg_split('/\s+/', trim($line));
        if (is_array($parts) && ($parts[1] ?? '') === '0100007F:' . $hex
            && ($parts[3] ?? '') === '0A') return true;
    }
    return false;
};
$readJournal = static function (string $path) use ($lane): array {
    if (!preg_match('~^/tmp/cdx-em-race-barrier-[a-f0-9]{12}/recovery\.json$~D', $path)
        || is_link($path) || realpath($path) !== $path
        || is_link(dirname($path))
        || (((int)fileperms(dirname($path)) & 0077) !== 0)
        || (((int)fileperms($path) & 0077) !== 0)) {
        throw new RuntimeException('Private phase journal invalid');
    }
    $journal = json_decode((string)file_get_contents($path), true);
    if (!is_array($journal) || ($journal['lane'] ?? null) !== $lane
        || !preg_match('/^CDXEMRACE[A-F0-9]{12}$/D',
            (string)($journal['marker'] ?? ''))
        || !isset($journal['worker_roots'][1], $journal['worker_roots'][2],
            $journal['worker_pids'][1], $journal['worker_pids'][2],
            $journal['worker_ports'][1], $journal['worker_ports'][2])) {
        throw new RuntimeException('Private phase journal identity invalid');
    }
    return $journal;
};
$writeJournal = static function (string $path, array $journal): void {
    $json = json_encode($journal, JSON_UNESCAPED_SLASHES);
    if (!is_string($json) || file_put_contents($path, $json, LOCK_EX) === false
        || !chmod($path, 0600)) {
        throw new RuntimeException('Private phase journal update failed');
    }
};
$checkWorkers = static function (array $journal, bool $requirePristine = false) use ($router, $runtimeSource,
    $ownsListener, $sourceRoot, $sourcePid, $dialect,
    $readWorkerEnvironment): array {
    $status = [];
    $sourceEnv = $readWorkerEnvironment($sourcePid);
    $sourceConfigSha = (string)hash_file('sha256',
        $sourceRoot . '/application/database.php');
    foreach ([1, 2] as $side) {
        $pid = (int)$journal['worker_pids'][$side];
        $port = (int)$journal['worker_ports'][$side];
        $root = (string)$journal['worker_roots'][$side];
        if ($pid <= 0 || $port < 1024 || !is_dir($root)
            || !preg_match('~^/tmp/cdx-em-race-[abc]-[a-f0-9]{12}-[12]$~D', $root)
            || is_link($root) || realpath($root) !== $root
            || (((int)fileperms($root) & 0077) !== 0)
            || !$ownsListener($pid, $port)) {
            throw new RuntimeException('Private worker PID/socket/root drift');
        }
        $observed = raceReadProcStat($pid);
        if ($observed === null
            || ($observed['start_ticks'] ?? null)
                !== (string)($journal['worker_start_ticks'][$side] ?? '')) {
            throw new RuntimeException('Private worker PID generation drift');
        }
        $cmd = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
        $children = trim((string)@file_get_contents('/proc/' . $pid
            . '/task/' . $pid . '/children'));
        if (strpos($cmd, '127.0.0.1:' . $port) === false
            || strpos($cmd, $root . '/public') === false
            || strpos($cmd, $router) === false || $children !== '') {
            throw new RuntimeException('Private worker command/single-worker drift');
        }
        foreach ($runtimeSource as $file => $sha) {
            if (!hash_equals($sha, (string)hash_file('sha256', $root . '/' . $file))) {
                throw new RuntimeException('Private worker business source drift');
            }
        }
        if (!hash_equals($sourceConfigSha,
            (string)hash_file('sha256', $root . '/application/database.php'))) {
            throw new RuntimeException('Private worker database config differs');
        }
        $privateEnv = $readWorkerEnvironment($pid);
        foreach (['POC_HOST', 'POC_PORT', 'POC_SCHEMA', 'POC_USER',
            'POC_PASSWORD', 'POC_AI_HOST', 'POC_AI_PORT', 'POC_AI_SCHEMA',
            'POC_AI_USER', 'POC_AI_PASSWORD', 'POC_REDIS_HOST',
            'POC_REDIS_PORT'] as $key) {
            if (($privateEnv[$key] ?? null) !== ($sourceEnv[$key] ?? null)) {
                throw new RuntimeException('Private worker inherited target drift');
            }
        }
        if (($privateEnv['POC_APP_ROOT'] ?? null) !== $root
            || ($privateEnv['POC_TARGET_ROOT'] ?? null) !== $root
            || ($privateEnv['POC_DIALECT'] ?? null) !== $dialect
            || ($privateEnv['POC_EXTERNAL_STUBS'] ?? null) !== '1'
            || ($privateEnv['POC_REAL_QUEUE'] ?? null) !== '0') {
            throw new RuntimeException('Private worker isolation environment drift');
        }
        $base = 'http://127.0.0.1:' . $port;
        $race = json_decode((string)@file_get_contents($base . '/__poc_race_status',
            false, stream_context_create(['http' => ['timeout' => 3]])), true);
        $boundary = json_decode((string)@file_get_contents($base . '/__poc_boundary',
            false, stream_context_create(['http' => ['timeout' => 3]])), true);
        if (!is_array($race) || !is_array($boundary)
            || ($race['private_race_router'] ?? null) !== true
            || (int)($race['pid'] ?? 0) !== $pid
            || (int)($race['side'] ?? 0) !== $side
            || ($boundary['external_stubs'] ?? null) !== true
            || ($boundary['redis_isolated'] ?? null) !== true
            || ($boundary['real_queue'] ?? true) !== false) {
            throw new RuntimeException('Private worker stub/Redis/queue boundary drift');
        }
        if ($requirePristine && ((int)($race['arrived_count'] ?? -1) !== 0
            || ($race['released'] ?? null) !== false
            || ($race['aborted'] ?? null) !== false)) {
            throw new RuntimeException('Private rendezvous already used before race');
        }
        $status[$side] = true;
    }
    return $status;
};

if ($phase === '--plan') {
    $stage = 'static_plan';
    $existing = $readWorkerEnvironment($sourcePid);
    if (($existing['POC_EXTERNAL_STUBS'] ?? null) !== '1'
        || ($existing['POC_REAL_QUEUE'] ?? null) === '1'
        || (isset($existing['POC_DIALECT'])
            && $existing['POC_DIALECT'] !== $dialect)) {
        throw new RuntimeException('Existing stub/queue mode not safe');
    }
    echo json_encode(['status' => 'static_plan_pass', 'lane' => $lane,
        'business_source_sha_fixed' => true,
        'existing_worker_environment_checked' => true,
        'private_roots_to_create' => 2,
        'private_loopback_workers_to_start' => 2,
        'db_connected' => false, 'workers_started' => false,
        'business_http_sent' => false, 'dml_sent' => false]), PHP_EOL;
    exit(0);
}

$journalPath = (string)getenv('CDX_EM_RACE_JOURNAL');
if ($phase === '--health' || $phase === '--stop') {
    $stage = 'existing_private_manifest';
    $journal = $readJournal($journalPath);
    if ($phase === '--health') {
        if (($journal['phase'] ?? null) !== 'staged'
            && ($journal['phase'] ?? null) !== 'healthy') {
            throw new RuntimeException('Health requested out of phase');
        }
        $checkWorkers($journal, true);
        $journal['phase'] = 'healthy';
        $writeJournal($journalPath, $journal);
        echo json_encode(['status' => 'two_private_workers_healthy',
            'lane' => $lane, 'two_distinct_pids_ports' => true,
            'same_frozen_source_and_db_runtime' => true,
            'external_stubs_and_redis_isolated' => true,
            'business_http_sent' => false, 'dml_sent' => false]), PHP_EOL;
        exit(0);
    }
    // --stop: stage-only drill may stop at healthy; a real race must first
    // reach independent-audit phase. Unknown HTTP/cleanup must retain workers.
    if (!in_array((string)($journal['phase'] ?? ''), ['staged', 'healthy', 'audited'], true)) {
        throw new RuntimeException('Stop refused before safe/no-DML or audited phase');
    }
    // Stop remains possible even if the ORIGINAL isolated service has exited.
    // Identify only this run's two new PIDs from journal, socket and router.
    foreach ([1, 2] as $side) {
        $pid = (int)$journal['worker_pids'][$side];
        $port = (int)$journal['worker_ports'][$side];
        $root = (string)$journal['worker_roots'][$side];
        if ($pid <= 0 || $port < 1024 || !is_dir($root)
            || realpath($root) !== $root
            || !preg_match('~^/tmp/cdx-em-race-[abc]-[a-f0-9]{12}-[12]$~D', $root)
            || !hash_equals((string)($journal['source_config_sha'] ?? ''),
                (string)hash_file('sha256', $root . '/application/database.php'))) {
            throw new RuntimeException('Private worker stop identity drift');
        }
        $expectedTicks = (string)($journal['worker_start_ticks'][$side] ?? '');
        $observed = raceReadProcStat($pid);
        $decision = raceWorkerExitDecision($observed, $expectedTicks,
            $portListening($port));
        if ($decision === 'identity_unknown' || $decision === 'pid_reused'
            || $decision === 'port_reoccupied') {
            throw new RuntimeException('Private worker PID generation/port drift');
        }
        foreach ($runtimeSource as $file => $sha) {
            if (!hash_equals($sha, (string)hash_file('sha256', $root . '/' . $file))) {
                throw new RuntimeException('Private worker source drift before stop');
            }
        }
        if ($decision === 'active') {
            $cmd = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
            if (strpos($cmd, '127.0.0.1:' . $port) === false
                || strpos($cmd, $root . '/public') === false
                || strpos($cmd, $router) === false
                || !$ownsListener($pid, $port)) {
                throw new RuntimeException('Private PID/socket owner changed before stop');
            }
        }
    }
    $stage = 'stop_only_two_private_pids';
    foreach ([1, 2] as $side) {
        $pid = (int)$journal['worker_pids'][$side];
        $port = (int)$journal['worker_ports'][$side];
        $expectedTicks = (string)$journal['worker_start_ticks'][$side];
        $decision = raceWorkerExitDecision(raceReadProcStat($pid),
            $expectedTicks, $portListening($port));
        if ($decision === 'active') {
            if (!function_exists('posix_kill') || !posix_kill($pid, SIGTERM)) {
                $decision = raceWorkerExitDecision(raceReadProcStat($pid),
                    $expectedTicks, $portListening($port));
                if ($decision !== 'exited') {
                    throw new RuntimeException('Private PID termination uncertain');
                }
            }
        }
        for ($attempt = 0; $attempt < 600 && $decision === 'active'; $attempt++) {
            usleep(50000);
            $decision = raceWorkerExitDecision(raceReadProcStat($pid),
                $expectedTicks, $portListening($port));
        }
        if ($decision !== 'exited') {
            $stage = 'stop_wait_' . $decision;
            throw new RuntimeException('Private worker exit or port status uncertain');
        }
    }
    $journal['phase'] = 'workers_stopped';
    $writeJournal($journalPath, $journal);
    $stage = 'no_cover_archive_only_private_paths';
    $nonce = strtolower(substr((string)$journal['marker'], strlen('CDXEMRACE')));
    foreach ([1, 2] as $side) {
        $expected = '/tmp/cdx-em-race-' . strtolower($lane)
            . '-' . $nonce . '-' . $side;
        if (($journal['worker_roots'][$side] ?? null) !== $expected) {
            throw new RuntimeException('Private root path changed');
        }
    }
    if (dirname($journalPath) !== '/tmp/cdx-em-race-barrier-' . $nonce) {
        throw new RuntimeException('Private barrier path changed');
    }
    $archive = raceArchiveNoCover($journalPath, $journal);
    echo json_encode(['status' => 'two_private_workers_stopped',
        'lane' => $lane, 'only_new_pids_stopped' => true,
        'private_roots_and_journal_archived' => true,
        'archive' => $archive['archive'],
        'archived_journal' => $archive['journal'],
        'business_http_sent' => false, 'dml_sent' => false]), PHP_EOL;
    exit(0);
}

// --stage only. No menu/code/device DML, no activate HTTP.
$stage = 'fresh_select_preflight';
putenv('CDX_EM_RACE_PREFLIGHT=BIND_RACE_SCHEMA_SELECT_ONLY_V1');
putenv('CDX_EM_RACE_PREFLIGHT_SHA=915131476db82d3ab5c1a22a8fc460d8980bab07785fe53a3556988861717887');
$outerArgv = $argv;
$argv[1] = '--preflight-only';
ob_start();
require $preflight;
$preflightText = (string)ob_get_clean();
$argv = $outerArgv;
restore_exception_handler();
$summary = json_decode(trim($preflightText), true);
if (!is_array($summary) || ($summary['status'] ?? null) !== 'select_only_pass'
    || ($summary['lane'] ?? null) !== $lane
    || ($summary['bind_code_hash_unique'] ?? null) !== true
    || ($summary['store_device_id_unique'] ?? null) !== true
    || ($summary['old_owned_markers'] ?? null)
        !== ['menu' => 0, 'bind' => 0, 'device' => 0, 'log' => 0]) {
    throw new RuntimeException('Fresh stage preflight failed');
}
$workerEnv = $readWorkerEnvironment($sourcePid);
if (($workerEnv['POC_EXTERNAL_STUBS'] ?? null) !== '1'
    || ($workerEnv['POC_REAL_QUEUE'] ?? null) === '1'
    || (isset($workerEnv['POC_DIALECT'])
        && $workerEnv['POC_DIALECT'] !== $dialect)) {
    throw new RuntimeException('Existing worker environment changed');
}
$workerEnv['POC_REAL_QUEUE'] = '0';
$workerEnv['POC_DIALECT'] = $dialect;
$lock = fopen(sys_get_temp_dir() . '/cdx-em-race-'
    . ($lane === 'C' ? 'c' : 'dev') . '.lock', 'c');
if ($lock === false || !flock($lock, LOCK_EX | LOCK_NB)) {
    throw new RuntimeException('Same-DB stage lock unavailable');
}
if ((int)disk_free_space('/tmp') < 1073741824) {
    throw new RuntimeException('Private-root disk reserve below 1GiB');
}
$nonce = strtolower(bin2hex(random_bytes(6)));
$marker = 'CDXEMRACE' . strtoupper($nonce);
$barrierDir = '/tmp/cdx-em-race-barrier-' . $nonce;
$roots = [1 => '/tmp/cdx-em-race-' . strtolower($lane) . '-' . $nonce . '-1',
    2 => '/tmp/cdx-em-race-' . strtolower($lane) . '-' . $nonce . '-2'];
$journalPath = $barrierDir . '/recovery.json';
$recoveryJournal = $journalPath;
$started = [];
$ownedBarrier = false;
$manifest = ['lane' => $lane, 'marker' => $marker,
    'phase' => 'stage_started', 'worker_roots' => $roots,
    'barrier_dir' => $barrierDir,
    'created_roots' => [1 => false, 2 => false],
    'source_config_sha' => (string)hash_file('sha256',
        $sourceRoot . '/application/database.php'),
    'worker_pids' => [1 => 0, 2 => 0],
    'worker_start_ticks' => [1 => '', 2 => ''],
    'worker_ports' => [1 => 0, 2 => 0],
    'worker_launch' => [1 => 'not_started', 2 => 'not_started'],
    'device_ids' => [1 => $marker . 'A', 2 => $marker . 'B'],
    'menu_id' => 0, 'code_id' => 0, 'source_before' => []];
$copyTree = static function (string $source, string $destination) use (&$copyTree): void {
    if (is_link($source) || !is_dir($source) || !mkdir($destination, 0700)) {
        throw new RuntimeException('Private source copy directory unsafe');
    }
    foreach (new FilesystemIterator($source, FilesystemIterator::SKIP_DOTS) as $item) {
        $target = $destination . '/' . $item->getFilename();
        if ($item->isLink()) throw new RuntimeException('Nested source symlink unsafe');
        if ($item->isDir()) $copyTree($item->getPathname(), $target);
        elseif (!$item->isFile() || !copy($item->getPathname(), $target)) {
            throw new RuntimeException('Private source file copy failed');
        }
    }
};
$reservePort = static function (): int {
    $socket = stream_socket_server('tcp://127.0.0.1:0', $no, $text);
    if ($socket === false) throw new RuntimeException('Private loopback port unavailable');
    $address = stream_socket_get_name($socket, false);
    fclose($socket);
    $port = (int)substr((string)$address, strrpos((string)$address, ':') + 1);
    if ($port < 1024 || $port > 65535) throw new RuntimeException('Private port invalid');
    return $port;
};
$stage = 'create_private_roots_and_detached_workers';
try {
    if (file_exists($barrierDir) || !mkdir($barrierDir, 0700)) {
        throw new RuntimeException('Private barrier path collision');
    }
    $ownedBarrier = true;
    if (!chmod($barrierDir, 0700)) {
        throw new RuntimeException('Private barrier mode unsafe');
    }
    $writeJournal($journalPath, $manifest);
    foreach ($roots as $side => $root) {
        if (file_exists($root) || !mkdir($root, 0700)) {
            throw new RuntimeException('Private worker root collision');
        }
        $manifest['created_roots'][$side] = true;
        $writeJournal($journalPath, $manifest);
        if (!chmod($root, 0700)) {
            throw new RuntimeException('Private worker root mode unsafe');
        }
        $copyTree($sourceRoot . '/application', $root . '/application');
        $copyTree($sourceRoot . '/public', $root . '/public');
        foreach (['env.php', 'external_stubs.php', 'think', 'version.json'] as $file) {
            if (is_file($sourceRoot . '/' . $file)
                && !copy($sourceRoot . '/' . $file, $root . '/' . $file)) {
                throw new RuntimeException('Private root startup file unavailable');
            }
        }
        foreach (['vendor', 'thinkphp', 'extend'] as $name) {
            $target = realpath($sourceRoot . '/' . $name);
            if ($target === false || !is_dir($target)
                || !symlink($target, $root . '/' . $name)) {
                throw new RuntimeException('Private root dependency unavailable');
            }
        }
        foreach (['runtime', 'runtime/cache', 'runtime/log'] as $relative) {
            if (!mkdir($root . '/' . $relative, 0700)) {
                throw new RuntimeException('Private runtime directory unavailable');
            }
        }
        foreach ($runtimeSource as $file => $sha) {
            if (!hash_equals($sha, (string)hash_file('sha256', $root . '/' . $file))) {
                throw new RuntimeException('Copied private business source drift');
            }
        }
    }
    $guard = ['status' => 'prepared', 'marker' => $marker,
        'device_ids' => $manifest['device_ids']];
    $state = ['arrivals' => [1 => null, 2 => null],
        'released' => false, 'aborted' => false,
        'dispatch' => [1 => null, 2 => null]];
    foreach (['guard.json' => $guard, 'state.json' => $state] as $name => $data) {
        $path = $barrierDir . '/' . $name;
        if (file_put_contents($path,
                json_encode($data, JSON_UNESCAPED_SLASHES), LOCK_EX) === false
            || !chmod($path, 0600)) {
            throw new RuntimeException('Private rendezvous state unavailable');
        }
    }
    $ports = [1 => $reservePort(), 2 => $reservePort()];
    if ($ports[1] === $ports[2]) throw new RuntimeException('Private port collision');
    $php = realpath(PHP_BINARY);
    if ($php === false) throw new RuntimeException('Private PHP binary unresolved');
    foreach ([1, 2] as $side) {
        $root = $roots[$side];
        $port = $ports[$side];
        $manifest['worker_ports'][$side] = $port;
        $writeJournal($journalPath, $manifest);
        if ($portListening($port)) {
            throw new RuntimeException('Private port occupied before worker launch');
        }
        $manifest['worker_launch'][$side] = 'starting';
        $manifest['phase'] = 'workers_starting';
        $writeJournal($journalPath, $manifest);
        $env = $workerEnv;
        $env['POC_APP_ROOT'] = $root;
        $env['POC_TARGET_ROOT'] = $root;
        $env['POC_BASE_URL'] = 'http://127.0.0.1:' . $port;
        $env['CDX_EM_RACE_PRIVATE_ROOT'] = $root;
        $env['CDX_EM_RACE_BARRIER_DIR'] = $barrierDir;
        $env['CDX_EM_RACE_SIDE'] = (string)$side;
        $env['CDX_EM_RACE_ROUTER_SHA'] =
            '6948d53a106884f58e772cbbb2afda7e44db6bddb2b513a22c5a93cb6758f700';
        unset($env['PHP_CLI_SERVER_WORKERS']);
        $args = [escapeshellarg($php)];
        if ($lane === 'C') {
            foreach (['POC_DM_PHP_LIB', 'POC_DM_PHP_PDO'] as $key) {
                $extension = (string)($workerEnv[$key] ?? '');
                if ($extension === '' || !is_file($extension)) {
                    throw new RuntimeException('C private DM PHP extension unavailable');
                }
                $args[] = '-d';
                $args[] = escapeshellarg('extension=' . $extension);
            }
        }
        array_push($args, '-S', escapeshellarg('127.0.0.1:' . $port),
            '-t', escapeshellarg($root . '/public'), escapeshellarg($router));
        $pidFile = $barrierDir . '/worker' . $side . '.pid';
        if (file_exists($pidFile)) throw new RuntimeException('Private PID sidecar collision');
        $command = 'umask 077; /usr/bin/nohup ' . implode(' ', $args)
            . ' >' . escapeshellarg($barrierDir . '/worker' . $side . '.out')
            . ' 2>' . escapeshellarg($barrierDir . '/worker' . $side . '.err')
            . ' </dev/null & child_pid=$!; printf "%s" "$child_pid" >'
            . escapeshellarg($pidFile) . '; printf "%s" "$child_pid"';
        $launcher = proc_open($command,
            [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
            $pipes, $root, $env);
        if (!is_resource($launcher)) throw new RuntimeException('Detached worker launch failed');
        fclose($pipes[0]);
        $pidText = trim((string)stream_get_contents($pipes[1], 80));
        $stderr = (string)stream_get_contents($pipes[2], 200);
        fclose($pipes[1]);
        fclose($pipes[2]);
        $launchExit = proc_close($launcher);
        $sidecarPid = is_file($pidFile)
            ? trim((string)file_get_contents($pidFile)) : '';
        if (!ctype_digit($pidText) || $pidText !== $sidecarPid
            || (((int)fileperms($pidFile) & 0077) !== 0)) {
            throw new RuntimeException('Detached worker PID launch uncertain');
        }
        $pid = (int)$pidText;
        $manifest['worker_pids'][$side] = $pid;
        $birth = raceReadProcStat($pid);
        if ($birth === null) {
            throw new RuntimeException('Detached worker process generation unavailable');
        }
        $manifest['worker_start_ticks'][$side] = $birth['start_ticks'];
        $manifest['worker_launch'][$side] = 'pid_recorded';
        $started[$side] = $pid;
        $writeJournal($journalPath, $manifest);
        if ($launchExit !== 0 || $stderr !== '') {
            throw new RuntimeException('Detached worker launcher reported failure');
        }
    }
    for ($attempt = 0; $attempt < 25; $attempt++) {
        try {
            $checkWorkers($manifest, true);
            break;
        } catch (Throwable $temporary) {
            if ($attempt === 24) throw $temporary;
            usleep(100000);
        }
    }
    $manifest['phase'] = 'staged';
    $writeJournal($journalPath, $manifest);
} catch (Throwable $error) {
    // Never kill or delete from this failure path. The separately approved
    // recovery entry checks EXACT recorded PID/socket/root, then archives.
    if ($ownedBarrier && is_dir($barrierDir) && !is_link($barrierDir)) {
        foreach ([1, 2] as $side) {
            if (($manifest['worker_launch'][$side] ?? '') !== 'starting'
                || (int)($manifest['worker_pids'][$side] ?? 0) > 0) continue;
            $sidecar = $barrierDir . '/worker' . $side . '.pid';
            if (!is_file($sidecar) || is_link($sidecar)
                || (((int)fileperms($sidecar) & 0077) !== 0)) continue;
            $candidate = trim((string)file_get_contents($sidecar));
            if (!ctype_digit($candidate) || (int)$candidate <= 0) continue;
            $candidatePid = (int)$candidate;
            if (is_dir('/proc/' . $candidatePid)) {
                $candidateCmd = (string)@file_get_contents(
                    '/proc/' . $candidatePid . '/cmdline');
                if (strpos($candidateCmd,
                        (string)$roots[$side] . '/public') === false
                    || strpos($candidateCmd,
                        '127.0.0.1:' . (int)$manifest['worker_ports'][$side]) === false
                    || strpos($candidateCmd, $router) === false) continue;
            }
            $manifest['worker_pids'][$side] = $candidatePid;
            $manifest['worker_launch'][$side] = 'pid_recorded';
        }
        $manifest['phase'] = 'stage_failed';
        $manifest['failure_stage'] = $stage;
        $manifest['failure_class'] = get_class($error);
        $manifest['failure_message_sha256'] = hash('sha256', $error->getMessage());
        try {
            $writeJournal($journalPath, $manifest);
        } catch (Throwable $journalError) {
            // PID sidecars and exact root names stay untouched for recovery.
        }
    }
    throw $error;
}
echo json_encode(['status' => 'two_private_workers_staged',
    'lane' => $lane, 'journal' => $journalPath,
    'worker_count' => 2, 'business_fixture_rows' => 0,
    'business_http_sent' => false, 'dml_sent' => false],
    JSON_UNESCAPED_SLASHES), PHP_EOL;
