$scenario, 'options' => [], 'errno' => 0]; } function curl_setopt_array(object $handle, array $options): bool { $handle->options = $options; $GLOBALS['iiOptions'][] = $options; $GLOBALS['iiClock'] += $handle->scenario['setup_ns'] ?? 0; return ($handle->scenario['set_ok'] ?? true) === true; } function curl_exec(object $handle): bool { ++$GLOBALS['iiExecuted']; $GLOBALS['iiClock'] += $handle->scenario['advance_ns'] ?? 0; if ($handle->scenario['throw'] ?? false) throw new \RuntimeException('private-independent-provider-error'); foreach ($handle->scenario['chunks'] ?? [$handle->scenario['body']] as $chunk) { if (($handle->options[CURLOPT_WRITEFUNCTION])($handle, $chunk) !== strlen($chunk)) { $handle->errno = CURLE_WRITE_ERROR; return false; } } return true; } function curl_errno(object $handle): int { return $handle->errno; } function curl_getinfo(object $handle, int $option): int { return $handle->scenario['status'] ?? 200; } function curl_close(object $handle): void { ++$GLOBALS['iiClosed']; $GLOBALS['iiClock'] += $handle->scenario['close_ns'] ?? 0; } } namespace { require dirname(__DIR__, 2) . '/app/artifacts/ai_concurrency/private_tcm_r25b_run_input_inspector.php'; use PrivateTcmR25b\RunInputInspector as Inspector; $checks = 0; $iiClock = 10000000000; $iiCreated = 0; $iiClosed = 0; $iiExecuted = 0; $iiScenarios = []; $iiOptions = []; $expect = static function (bool $value, string $label) use (&$checks): void { ++$checks; if (!$value) throw new RuntimeException($label); }; $json = static fn (mixed $value): string => json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR); $base = sys_get_temp_dir() . '/tcm-r25b-inspector-independent-' . bin2hex(random_bytes(8)); $root = $base . '/server'; $auditDir = $root . '/runtime/tcm-r25-wire-audits'; $resultDir = $base . '/app/artifacts/ai_concurrency'; mkdir($auditDir, 0700, true); mkdir($resultDir, 0700, true); $number = 0; $query = "independent-private-query/中文\nsecond-line\r\n"; $config = ['enable' => true, 'base_url' => 'http://independent.synthetic.invalid:8088/v1/chat-messages', 'models' => ['qwen' => ['api_key' => 'private-independent-qwen-key']]]; $fixtureHash = 'b54c47ec11f6a99dc87bdda78629e18c8a6f37a64017e42a72db399c727cb1c6'; $questionHash = '28fbaee8585d4fbde3be3b1a6ee046c1a60f18a1fe67c0769211b08afdd5d306'; $make = static function (int $count = 1) use (&$number, $query, $fixtureHash, $questionHash): array { $id = sprintf('44444444-4444-4444-8444-%012d', ++$number); $records = [['event' => 'request', 'contract' => 'v43r25_private_run_wire', 'request_id' => $id, 'request_label' => 'independent_row_qwen', 'profile' => 'qwen']]; for ($i = 1; $i <= $count; ++$i) { $body = json_encode(['inputs' => (object) [], 'query' => $query], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR); $records[] = ['event' => 'serialized_request', 'generation' => $i, 'report_stage' => $i === 1 ? 1 : 2, 'stage_attempt' => $i <= 2 ? 1 : $i - 1, 'protocol' => 'dify', 'body_sha256' => hash('sha256', $body), 'body_bytes' => strlen($body), 'query_sha256' => hash('sha256', $query), 'query_bytes' => strlen($query), 'inputs_sha256' => hash('sha256', '{}'), 'inputs_bytes' => 2, 'report_continuation_query' => $i > 1]; $records[] = ['event' => 'original_identity', 'generation' => $i, 'original_task_id' => 'private-independent-task-' . $i, 'original_workflow_run_id' => '']; $records[] = ['event' => 'original_identity', 'generation' => $i, 'original_task_id' => 'private-independent-task-' . $i, 'original_workflow_run_id' => 'private-independent-run-' . $i]; } $records[] = ['event' => 'after_control_cleanup', 'state' => ['transport_closed' => true, 'upstream_terminal_confirmed' => true, 'upstream_stop_confirmed' => false, 'cancel_requested' => false, 'timeout_reached' => false, 'upstream_pending_task_count' => 0]]; return ['records' => $records, 'summary' => ['persisted' => true, 'serialized_request_count' => $count, 'original_task_count' => $count, 'original_run_count' => $count], 'id' => $id, 'number' => $number, 'fixture' => $fixtureHash, 'question' => $questionHash]; }; $save = static function (array $fixture) use ($auditDir, $resultDir, $json): array { $content = implode("\n", array_map($json, $fixture['records'])) . "\n"; $summary = $fixture['summary'] + ['audit_bytes' => strlen($content), 'audit_sha256' => hash('sha256', $content)]; $auditPath = $auditDir . '/' . hash('sha256', $fixture['id']) . '.private.jsonl'; file_put_contents($auditPath, $content); $row = ['test_label' => 'independent_row', 'profile' => 'qwen', 'private_wire_audit' => $summary, 'harness_contract' => 'v43r25_private_run_wire', 'synthetic' => true, 'preparation_isolated' => true, 'preparation_isolation_verified' => true, 'production_acceptance_path' => true, 'diagnostic_only' => false, 'case_id' => 11, 'production_hashes' => ['fixture' => $fixture['fixture'], 'question' => $fixture['question']]]; $document = ['harness_contract' => 'v43r25_private_run_wire', 'synthetic_only' => true, 'preparation_isolated' => true, 'fixture_sha256' => $fixture['fixture'], 'canonical_question_sha256' => $fixture['question'], 'rows' => [$row]]; $resultFile = 'tcm_complete_independent_inspector_' . $fixture['number'] . '.safe.json'; $resultPath = $resultDir . '/' . $resultFile; file_put_contents($resultPath, $json($document)); return [['result_file' => $resultFile, 'test_label' => 'independent_row', 'profile' => 'qwen', 'audit_sha256' => $summary['audit_sha256']], $auditPath, $resultPath]; }; $response = static fn (int $i = 1): array => ['id' => 'private-independent-run-' . $i, 'status' => 'succeeded', 'inputs' => ['sys.query' => $query], 'outputs' => ['secret' => 'private-independent-output']]; $call = static function (array $selector, array $scenarios, ?array $override = null) use ($root, $config): array { $GLOBALS['iiScenarios'] = $scenarios; $configCalls = 0; $value = Inspector::inspectResultRow($root, $selector, static function () use (&$configCalls, $config, $override): array { ++$configCalls; return $override ?? $config; }); return [$value, $configCalls]; }; $privacy = static function (array $value) use ($expect, $json, $query): void { $text = $json($value); foreach (['private-independent-', 'independent.synthetic', 'independent_row', '44444444-', $query] as $secret) $expect(!str_contains($text, $secret), 'safe reply excludes private identity/body/config/selector text'); $expect(($value['model_calls'] ?? null) === 0 && ($value['llm_expanded_prompt_observed'] ?? null) === false, 'query evidence never becomes model/node visibility'); }; try { [$selected, , $resultPath] = $save($make(2)); [$ok, $configured] = $call($selected, [['body' => $json($response())], ['body' => $json($response(2))]]); $expect($ok['ok'] && $configured === 1 && $ok['inspected_run_count'] === 2 && $ok['matched_run_count'] === 2, 'full saved-row bridge selects exactly two original runs'); $expect($ok['result_file_sha256'] === hash_file('sha256', $resultPath) && $ok['audit_sha256'] === $selected['audit_sha256'], 'whole result and audit digests retained'); $privacy($ok); foreach ($iiOptions as $options) { $expect($options[CURLOPT_HTTPGET] === true && !isset($options[CURLOPT_POSTFIELDS]) && !isset($options[CURLOPT_POST]), 'GET only'); $expect($options[CURLOPT_PROTOCOLS] === CURLPROTO_HTTP && $options[CURLOPT_REDIR_PROTOCOLS] === CURLPROTO_HTTP && str_starts_with($options[CURLOPT_URL], 'http://independent.synthetic.invalid:8088/v1/workflows/run/'), 'exact configured HTTP scheme/host/port/path only'); $expect($options[CURLOPT_TIMEOUT_MS] > 0 && $options[CURLOPT_TIMEOUT_MS] <= 2000 && $options[CURLOPT_CONNECTTIMEOUT_MS] <= 2000 && !$options[CURLOPT_FOLLOWLOCATION] && $options[CURLOPT_MAXREDIRS] === 0, 'bounded deadline and redirects disabled'); } foreach (['open_transport', 'no_terminal', 'pending', 'pending_string', 'extra_footer', 'header_upper_uuid', 'header_neighbor_label', 'identity_downgrade', 'identity_other_task', 'identity_before_serialization', 'wrong_query_hash_type', 'stage_backwards', 'non_dify', 'summary_bool_count', 'summary_byte_mismatch', 'summary_run_mismatch', 'too_many_runs'] as $kind) { $fixture = $make(in_array($kind, ['stage_backwards', 'too_many_runs'], true) ? 3 : 1); $last = count($fixture['records']) - 1; if ($kind === 'open_transport') $fixture['records'][$last]['state']['transport_closed'] = false; if ($kind === 'no_terminal') $fixture['records'][$last]['state']['upstream_terminal_confirmed'] = false; if ($kind === 'pending') $fixture['records'][$last]['state']['upstream_pending_task_count'] = 1; if ($kind === 'pending_string') $fixture['records'][$last]['state']['upstream_pending_task_count'] = '0'; if ($kind === 'extra_footer') $fixture['records'][$last]['state']['raw_body'] = 'private-independent-injection'; if ($kind === 'header_upper_uuid') $fixture['records'][0]['request_id'] = strtoupper(str_replace('44444444', 'abcdefab', $fixture['id'])); if ($kind === 'header_neighbor_label') $fixture['records'][0]['request_label'] = 'neighbor_qwen'; if ($kind === 'identity_downgrade') $fixture['records'][3]['original_workflow_run_id'] = ''; if ($kind === 'identity_other_task') $fixture['records'][3]['original_task_id'] = 'private-independent-other-task'; if ($kind === 'identity_before_serialization') [$fixture['records'][1], $fixture['records'][2]] = [$fixture['records'][2], $fixture['records'][1]]; if ($kind === 'wrong_query_hash_type') $fixture['records'][1]['query_sha256'] = ['private-independent-injection']; if ($kind === 'stage_backwards') { $fixture['records'][7]['report_stage'] = 1; $fixture['records'][7]['report_continuation_query'] = false; } if ($kind === 'non_dify') $fixture['records'][1]['protocol'] = 'openai'; if ($kind === 'summary_bool_count') $fixture['summary']['original_task_count'] = true; if ($kind === 'summary_byte_mismatch') $fixture['summary']['audit_bytes'] = 1; if ($kind === 'summary_run_mismatch') $fixture['summary']['original_run_count'] = 0; [$selector] = $save($fixture); $before = $iiExecuted; [$value, $configured] = $call($selector, []); $expect(!$value['ok'] && $configured === 0 && $iiExecuted === $before, 'invalid exact-own bridge fails before config/GET: ' . $kind); $privacy($value); } foreach (['object_sys', 'lookalike_dot', 'trailing_space', 'wrong_case', 'array_inputs', 'null_query', 'different_crlf', 'different_unicode', 'wrong_byte_count', 'optional_null_run', 'optional_null_task', 'output_only', 'both_same', 'running_input_only'] as $kind) { $fixture = $make(); $value = $response(); if ($kind === 'object_sys') $value['inputs'] = ['sys' => ['query' => $query]]; if ($kind === 'lookalike_dot') $value['inputs'] = ['sys.query' => $query]; if ($kind === 'trailing_space') $value['inputs'] = ['sys.query ' => $query]; if ($kind === 'wrong_case') $value['inputs'] = ['SYS.QUERY' => $query]; if ($kind === 'array_inputs') $value['inputs'] = [['sys.query' => $query]]; if ($kind === 'null_query') $value['inputs']['query'] = null; if ($kind === 'different_crlf') $value['inputs']['sys.query'] = str_replace("\r\n", "\n", $query); if ($kind === 'different_unicode') $value['inputs']['sys.query'] .= "\u{0301}"; if ($kind === 'wrong_byte_count') ++$fixture['records'][1]['query_bytes']; if ($kind === 'optional_null_run') $value['workflow_run_id'] = null; if ($kind === 'optional_null_task') $value['task_id'] = null; if ($kind === 'output_only') { $value['inputs'] = (object) []; $value['outputs']['query'] = $query; } if ($kind === 'both_same') $value['inputs']['query'] = $query; if ($kind === 'running_input_only') $value['status'] = 'running'; [$selector] = $save($fixture); $before = $iiExecuted; [$answer] = $call($selector, [['body' => $json($value)]]); $expect($answer['ok'] === in_array($kind, ['both_same', 'running_input_only'], true) && $iiExecuted === $before + 1, 'only exact whitelisted byte-identical query evidence: ' . $kind); if ($kind === 'running_input_only') $expect($answer['runs'][0]['run_status'] === 'running', 'matching query does not assert a fresh terminal or cleanup proof'); $privacy($answer); } [$selector] = $save($make(2)); $before = $iiExecuted; [$answer] = $call($selector, [['body' => $json($response()), 'advance_ns' => 2000000000], ['body' => $json($response(2))]]); $expect(!$answer['ok'] && $iiExecuted === $before + 2 && $answer['matched_run_count'] === 1 && $answer['runs'][0]['status'] === 'run_timeout' && $answer['runs'][1]['query_matches_wire'], 'timeout plus successor uses exactly two original GETs and cannot hide first failure'); $privacy($answer); foreach (['setup_deadline', 'setopt_failure', 'chunk_overflow', 'throw'] as $kind) { [$selector] = $save($make()); $scenario = ['body' => $json($response())]; if ($kind === 'setup_deadline') $scenario['setup_ns'] = 2000000000; if ($kind === 'setopt_failure') $scenario['set_ok'] = false; if ($kind === 'chunk_overflow') $scenario['chunks'] = [str_repeat('x', 1048576), str_repeat('x', 1048576), 'x']; if ($kind === 'throw') $scenario['throw'] = true; $before = $iiExecuted; [$answer] = $call($selector, [$scenario]); $expect(!$answer['ok'] && $iiExecuted === $before + (in_array($kind, ['setup_deadline', 'setopt_failure'], true) ? 0 : 1), 'bounded setup/write/error closes without retry: ' . $kind); $privacy($answer); } // NEW r25b controls: retain all old independent expectations above. // Handcrafted body metadata is recomputed for these distinct strings; // no private audit writer is used to derive expected query values. $queryFixture = static function (array $fixture, array $queries) use ($json): array { foreach ($fixture['records'] as &$record) { if ($record['event'] !== 'serialized_request') continue; $actual = $queries[$record['generation'] - 1]; $body = $json(['inputs' => (object) [], 'query' => $actual]); $record['query_sha256'] = hash('sha256', $actual); $record['query_bytes'] = strlen($actual); $record['body_sha256'] = hash('sha256', $body); $record['body_bytes'] = strlen($body); } unset($record); return $fixture; }; $exact = "literal\\u660e\\n/中文 \"quote\" & é e\u{0301} 😀\r\nNUL:\0\t "; foreach ([0, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT, JSON_PRETTY_PRINT] as $number => $flags) { [$selector] = $save($queryFixture($make(), [$exact])); $value = $response(); $value['status'] = 'running'; $value['inputs'] = json_encode(['sys.query' => $exact, 'query' => $exact], $flags | JSON_THROW_ON_ERROR); $before = $iiExecuted; [$answer] = $call($selector, [['body' => json_encode($value, $flags | JSON_THROW_ON_ERROR)]]); $row = $answer['runs'][0]; $expect($answer['ok'] && $iiExecuted === $before + 1 && $row['query_candidate_count'] === 2, 'two JSON transport layers recover identical exact aliases ' . $number); $expect($row['observed_query_sha256'] === hash('sha256', $exact) && $row['observed_query_bytes'] === strlen($exact), 'transport escapes preserve original hash and bytes ' . $number); $expect($row['inputs_encoding'] === 'json_string' && $row['inputs_availability'] === 'available' && $row['returned_run_id_matches'] && $row['run_status'] === 'running', 'encoding/status metadata does not become terminal ' . $number); $privacy($answer); $expect(!str_contains($json($answer), $exact), 'new escaped query text remains private ' . $number); } foreach (['escaped_key', 'double_inputs', 'nested_inputs', 'literal_json_query', 'decoded_query_different', 'different_alias', 'bad_bytes', 'bad_hash', 'foreign_id', 'foreign_alias', 'metadata_in_inputs'] as $kind) { $fixture = $queryFixture($make(), [$exact]); $value = $response(); $value['status'] = 'running'; $value['inputs'] = $json(['query' => $exact]); $wanted = 'query_match'; if ($kind === 'escaped_key') $value['inputs'] = '{"sys\\u002equery":' . $json($exact) . '}'; if ($kind === 'double_inputs') { $value['inputs'] = $json($value['inputs']); $wanted = 'query_input_invalid'; } if ($kind === 'nested_inputs') { $value['inputs'] = $json(['inputs' => $value['inputs']]); $wanted = 'query_input_unavailable'; } if ($kind === 'literal_json_query' || $kind === 'decoded_query_different') { $literal = $json(['query' => $exact]); $fixture = $queryFixture($make(), [$literal]); $value['inputs'] = $json(['query' => $kind === 'literal_json_query' ? $literal : $exact]); if ($kind === 'decoded_query_different') $wanted = 'query_mismatch'; } if ($kind === 'different_alias') { $value['inputs'] = $json(['sys.query' => $exact, 'query' => $json($exact)]); $wanted = 'query_input_ambiguous'; } if ($kind === 'bad_bytes') { ++$fixture['records'][1]['query_bytes']; $wanted = 'query_mismatch'; } if ($kind === 'bad_hash') { $fixture['records'][1]['query_sha256'] = hash('sha256', $exact . 'x'); $wanted = 'query_mismatch'; } if ($kind === 'foreign_id') { $value['id'] = 'private-independent-foreign-run'; $wanted = 'returned_run_mismatch'; } if ($kind === 'foreign_alias') { $value['task_id'] = 'private-independent-foreign-task'; $wanted = 'returned_run_mismatch'; } if ($kind === 'metadata_in_inputs') $value['inputs'] = $json(['query' => $exact, 'run_status' => 'succeeded', 'returned_run_id_matches' => false, 'inputs_availability' => 'missing', 'status' => 'private-independent-status']); [$selector] = $save($fixture); [$answer] = $call($selector, [['body' => $json($value)]]); $row = $answer['runs'][0]; $expect($row['status'] === $wanted && $answer['ok'] === ($wanted === 'query_match'), 'one decode and per-field exact comparison ' . $kind); if (in_array($kind, ['foreign_id', 'foreign_alias'], true)) { $expect($row['inputs_encoding'] === 'unobserved' && $row['inputs_availability'] === 'unobserved' && $row['returned_run_id_matches'] === ($kind === 'foreign_alias'), 'identity gate precedes any decoded input observation ' . $kind); $expect(!array_key_exists('run_status', $row) && !array_key_exists('observed_query_sha256', $row), 'foreign identity cannot export query/status observations ' . $kind); } else $expect($row['run_status'] === 'running', 'valid original running status independent of query decision ' . $kind); if ($kind === 'metadata_in_inputs') $expect($row['returned_run_id_matches'] && $row['inputs_availability'] === 'available', 'input object cannot override safe metadata'); if (in_array($kind, ['double_inputs', 'nested_inputs', 'different_alias'], true)) $expect(!array_key_exists('observed_query_sha256', $row), 'unavailable or ambiguous query never invents a hash ' . $kind); $privacy($answer); } $secondQuery = $exact . 'sole-continuation'; foreach (['own', 'swapped', 'one_wrong'] as $kind) { [$selector] = $save($queryFixture($make(2), [$exact, $secondQuery])); $first = $response(); $second = $response(2); $first['status'] = $second['status'] = 'running'; $first['inputs'] = $json(['sys.query' => $kind === 'swapped' ? $secondQuery : $exact]); $second['inputs'] = $json(['query' => $kind === 'own' ? $secondQuery : $exact]); $before = $iiExecuted; [$answer] = $call($selector, [['body' => $json($first)], ['body' => $json($second)]]); $expect($iiExecuted === $before + 2 && $answer['inspected_run_count'] === 2, 'exactly two original generation GETs without recovery/fallback ' . $kind); $expect($answer['matched_run_count'] === match ($kind) { 'own' => 2, 'swapped' => 0, 'one_wrong' => 1 } && $answer['ok'] === ($kind === 'own'), 'each serialized query bound to its own generation ' . $kind); $expect(array_column($answer['runs'], 'run_status') === ['running', 'running'], 'matching or mismatching input never rewrites terminal state ' . $kind); $privacy($answer); } [$selector] = $save($queryFixture($make(), [$exact])); $value = $response(); $value['status'] = 'running'; $value['inputs'] = $json(['query' => $exact]); [$answer] = $call($selector, [['body' => $json($value), 'close_ns' => 2000000000]]); $row = $answer['runs'][0]; $expect(!$answer['ok'] && $row['status'] === 'run_timeout' && !$row['query_matches_wire'], 'outer total per-run budget invalidates a comparison that finished before slow close'); $expect($row['run_status'] === 'running' && $row['returned_run_id_matches'] && $row['inputs_encoding'] === 'json_string' && $row['inputs_availability'] === 'available', 'outer timeout retains obtained safe observations without terminal override'); $privacy($answer); // Exact source equivalence is stronger than middleware-name presence: // the original saved-row/audit/config code remains mechanically equal. $artifact = dirname(__DIR__, 2) . '/app/artifacts/ai_concurrency/'; require $artifact . 'private_tcm_r25_run_input_inspector.php'; $methodSource = static function (string $class, string $method): string { $reflection = new ReflectionMethod($class, $method); $lines = file($reflection->getFileName()); return str_replace("\r\n", "\n", implode('', array_slice($lines, $reflection->getStartLine() - 1, $reflection->getEndLine() - $reflection->getStartLine() + 1))); }; foreach (['inspectResultRow', 'readAudit', 'connection', 'keys', 'digest', 'id', 'samePath', 'error'] as $method) { $expect($methodSource(Inspector::class, $method) === $methodSource('PrivateTcmR25\\RunInputInspector', $method), 'canonical old audit/result/connection method exact source equality ' . $method); } $oldProbe = str_replace("\r\n", "\n", file_get_contents($artifact . 'private_tcm_r25_run_input_probe.php')); $newProbe = str_replace("\r\n", "\n", file_get_contents($artifact . 'private_tcm_r25b_run_input_probe.php')); $expectedProbe = str_replace(['runInputFinish', 'private_tcm_r25_run_input_', '\\PrivateTcmR25\\'], ['runInputR25bFinish', 'private_tcm_r25b_run_input_', '\\PrivateTcmR25b\\'], $oldProbe); $expectedProbe = str_replace('// POST: token,', "// New r25b derivative; the original r25 probe/helper remain immutable.\n// POST: token,", $expectedProbe); $expect($newProbe === $expectedProbe, 'entire canonical private probe auth bridge unchanged except exact derivative naming/comment'); foreach (['private_tcm_r25_run_input_inspector.php' => '9f5f163e529ecdbb5e9b4d2b1ab1d04d8c4292b371c72c66034554b3b4860381', 'private_tcm_r25_run_input_probe.php' => '18ffca2a320c683c7e797ec6ac2e1fe606d0103fc59c701c95c818f49c8a4a0e', 'private_tcm_r25b_run_input_inspector.php' => 'f0f6ef018e391ea5f1f219b0d5fc931f59f8fa84fe7431d8d5ca29efab410a61', 'private_tcm_r25b_run_input_probe.php' => '6c19b575ae7fd88554dd68f12d8f258e15851e5e16246a52ae705e6840ad782a'] as $name => $sha) { $expect(hash_file('sha256', $artifact . $name) === $sha, 'exact original/derivative source pin ' . $name); } [$selector, $auditPath] = $save($make()); $lock = fopen($auditPath, 'rb'); $expect(flock($lock, LOCK_EX | LOCK_NB), 'synthetic exclusive lock acquired'); $before = $iiExecuted; [$answer, $configured] = $call($selector, []); $expect(!$answer['ok'] && $configured === 0 && $iiExecuted === $before, 'locked exact private audit never reaches config/GET'); flock($lock, LOCK_UN); fclose($lock); $expect($iiCreated === $iiClosed, 'every fake GET handle closed'); $expect($iiScenarios === [], 'all and only declared fake scenarios consumed'); $expect(!class_exists('think\\App', false), 'application bootstrap never loaded'); echo "Independent r25b serialized exact-run input inspector: {$checks} checks passed (handcrafted private fixtures, in-memory GET/config/time; no auth/network/bootstrap).\n"; } finally { $real = realpath($base); $temp = realpath(sys_get_temp_dir()); if ($real === false || $temp === false || !str_starts_with(str_replace('\\', '/', $real), rtrim(str_replace('\\', '/', $temp), '/') . '/tcm-r25b-inspector-independent-')) throw new RuntimeException('Independent synthetic cleanup boundary'); $entries = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($real, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST); foreach ($entries as $entry) { if ($entry->isLink()) throw new RuntimeException('Independent synthetic cleanup symlink'); if ($entry->isDir()) rmdir($entry->getPathname()); else unlink($entry->getPathname()); } rmdir($real); } }