false, 'db_target' => $dbTarget, 'preflight' => null, 'applied' => false, 'postflight' => null, 'wash_id_uniqueness_ready' => false, 'wash_id_uniqueness_activated' => false, 'wash_id_uniqueness_blocked' => false, 'error' => null, ]; try { $preflight = migration_20260804_xlvask_ai_auto_policy_v2::preflight(); $result['preflight'] = $preflight; if (!(bool)($preflight['ready'] ?? false)) { $result['postflight'] = migration_20260804_xlvask_ai_auto_policy_v2::apply(); $result['applied'] = true; } else { $result['postflight'] = $preflight; } $postflight = (array)$result['postflight']; if (!(bool)($postflight['ready'] ?? false)) { throw new RuntimeException('XL Vask automation schema is still not ready after apply.'); } if (xlvask_usage_logs_schema_bootstrap::washIdUniquenessReady()) { $result['wash_id_uniqueness_ready'] = true; } else { $activated = xlvask_usage_logs_schema_bootstrap::applyWashIdUniquenessMigration(); $result['wash_id_uniqueness_ready'] = $activated && xlvask_usage_logs_schema_bootstrap::washIdUniquenessReady(); $result['wash_id_uniqueness_activated'] = $result['wash_id_uniqueness_ready']; $result['wash_id_uniqueness_blocked'] = !$result['wash_id_uniqueness_ready']; } $result['success'] = (bool)$result['wash_id_uniqueness_ready']; if (!$result['success']) { $result['error'] = 'Wash-id uniqueness is blocked, likely due duplicate normalized wash_id values.'; } } catch (Throwable $throwable) { // The wrapper cron entry may swallow the runtime exception that is // re-thrown below, so emit a container-log breadcrumb here too. error_log('[cron-ensure-xlvask-automation-schema] apply failed: ' . $throwable->getMessage()); $result['error'] = $throwable->getMessage(); } echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL; if (!$result['success']) { throw new RuntimeException((string)($result['error'] ?: 'XL Vask schema readiness failed.')); }