#!/usr/bin/env node
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import net from 'node:net';
import { randomUUID } from 'node:crypto';
import { fileURLToPath } from 'node:url';
import { spawnSync, spawn } from 'node:child_process';
import { findLocalChromeBinary } from './chrome-binary.mjs';
import { flushAndExit } from './flush-exit.mjs';
import {
  buildProviderCoverageSummary,
  shoppingProvidersForMode,
  socialPlatformsForMode
} from './provider-live-scenarios.mjs';
import { hasDirtyRelayClients } from './live-regression-matrix.mjs';
import {
  DIRECT_SHOPPING_PROVIDER_QUERY,
  HIGH_FRICTION_SHOPPING_PROVIDERS,
  MATRIX_ENV_LIMITED_CODES,
  MATRIX_SHOPPING_PROVIDER_TIMEOUT_MS,
  PRODUCT_VIDEO_ENV_LIMITED_DETAIL_MATCHERS,
  SOCIAL_POST_CASES
} from './shared/workflow-lane-constants.mjs';
import {
  classifyLaneRecords,
  normalizedCodesFromFailures,
  summarizeFailures
} from './shared/workflow-lane-verdicts.mjs';
import {
  DEFAULT_YOUTUBE_TRANSCRIPT_MODE,
  YOUTUBE_TRANSCRIPT_PROBE_STEP_ID
} from './youtube-transcript-live-probe.mjs';

const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const CLI = path.join(ROOT, 'dist', 'cli', 'index.js');
const MAX_BUFFER = 64 * 1024 * 1024;
const HEADLESS_PROCESS_MATCH = '--headless';
const EXTENSION_OPS_NAV_TIMEOUT_MS = Math.max(
  5000,
  Number.parseInt(process.env.PROVIDER_LIVE_EXTENSION_NAV_TIMEOUT_MS ?? '120000', 10) || 120000
);
const EXTENSION_OPS_CLI_TIMEOUT_MS = Math.max(
  EXTENSION_OPS_NAV_TIMEOUT_MS,
  Number.parseInt(process.env.PROVIDER_LIVE_EXTENSION_CLI_TIMEOUT_MS ?? '240000', 10) || 240000
);
const EXTENSION_OPS_NAV_RETRIES = Math.max(
  1,
  Number.parseInt(process.env.PROVIDER_LIVE_EXTENSION_NAV_RETRIES ?? '4', 10) || 4
);
const EXTENSION_LAUNCH_WAIT_TIMEOUT_MS = Math.max(
  30000,
  Number.parseInt(process.env.PROVIDER_LIVE_EXTENSION_WAIT_TIMEOUT_MS ?? '60000', 10) || 60000
);
const EXTENSION_LAUNCH_RECOVERY_RETRIES = Math.max(
  1,
  Number.parseInt(process.env.PROVIDER_LIVE_EXTENSION_LAUNCH_RETRIES ?? '1', 10) || 1
);
export const NESTED_LIVE_REGRESSION_TIMEOUT_MS = Math.max(
  900_000,
  Number.parseInt(process.env.PROVIDER_LIVE_NESTED_LIVE_REGRESSION_TIMEOUT_MS ?? '1500000', 10) || 1_500_000
);
const EXTENSION_HEAVY_NAV_TARGETS = new Set([
  'youtube.search',
  'instagram.explore',
  'facebook.search',
  'linkedin.search',
  'x.search'
]);
const BROWSER_REALWORLD_TARGETS = [
  { id: 'x.search', url: 'https://x.com/home' },
  { id: 'youtube.search', url: 'https://www.youtube.com/results?search_query=browser+automation+anti+bot' },
  { id: 'instagram.explore', url: 'https://www.instagram.com/explore/' },
  { id: 'facebook.search', url: 'https://www.facebook.com/watch/search/?q=browser%20automation' },
  { id: 'linkedin.search', url: 'https://www.linkedin.com/search/results/content/?keywords=browser%20automation' }
];
export const WORKFLOW_RESEARCH_PROBE_ARGS = [
  'research',
  'run',
  '--topic',
  'browser automation production blockers',
  '--sources',
  'web,community',
  '--mode',
  'json',
  '--limit-per-source',
  '4',
  '--timeout-ms',
  '120000'
];
export const WORKFLOW_YOUTUBE_TRANSCRIPT_PROBE_ARGS = [
  'scripts/youtube-transcript-live-probe.mjs',
  '--quiet',
  '--youtube-mode',
  DEFAULT_YOUTUBE_TRANSCRIPT_MODE
];
const SIGNED_IN_BROWSER_ARGS = ['--browser-mode', 'extension', '--use-cookies', '--cookie-policy', 'required'];
export function buildLiveShoppingRunArgs(provider, timeoutMs) {
  return [
    'shopping',
    'run',
    '--query',
    DIRECT_SHOPPING_PROVIDER_QUERY.get(provider) ?? 'ergonomic wireless mouse',
    '--providers',
    provider,
    '--sort',
    'best_deal',
    '--mode',
    'json',
    '--timeout-ms',
    timeoutMs,
    ...SIGNED_IN_BROWSER_ARGS,
    '--challenge-automation-mode',
    'browser_with_helper'
  ];
}

const ownedHeadlessMarkers = new Set();
const ownedHeadlessProfileDirs = new Set();
let headlessCleanupHooksInstalled = false;
let headlessCleanupCompleted = false;

const HELP_TEXT = [
  'Usage: node scripts/provider-live-matrix.mjs [options]',
  '',
  'Options:',
  '  --out <path>                 Output JSON path (default: /tmp/odb-provider-live-matrix-<mode>-<ts>.json)',
  '  --smoke                      CI-safe smoke mode (reduced provider matrix)',
  '  --use-global-env             Use existing OPENCODE_* env/config instead of isolated temp runtime',
  '  --skip-live-regression       Skip scripts/live-regression-matrix.mjs',
  '  --skip-browser-probes        Skip direct browser social probes',
  '  --skip-workflows             Skip research/product-video workflow probes',
  '  --include-live-regression    Force nested live-regression run (disabled by default in --release-gate and --smoke)',
  '  --include-browser-probes     Force browser probes even in --smoke',
  '  --include-workflows          Force workflow probes even in --smoke',
  '  --include-auth-gated         Compatibility flag; auth-gated diagnostics run by default',
  '  --include-high-friction      Compatibility flag; high-friction diagnostics run by default',
  '  --include-social-posts       Include social post probes (default: skipped)',
  '  --release-gate               Strict release mode (forces auth/high-friction/social-post scenarios and fails on non-pass statuses)',
  '  --help                       Show help'
].join('\n');

export function parseArgs(argv) {
  const options = {
    out: null,
    smoke: false,
    useGlobalEnv: false,
    skipLiveRegression: false,
    skipBrowserProbes: false,
    skipWorkflows: false,
    includeLiveRegression: false,
    includeBrowserProbes: false,
    includeWorkflows: false,
    includeAuthGated: false,
    includeHighFriction: false,
    includeSocialPosts: false,
    releaseGate: false
  };

  for (let index = 0; index < argv.length; index += 1) {
    const arg = argv[index];
    if (arg === '--help') {
      console.log(HELP_TEXT);
      process.exit(0);
    }
    if (arg === '--smoke') {
      options.smoke = true;
      continue;
    }
    if (arg === '--use-global-env') {
      options.useGlobalEnv = true;
      continue;
    }
    if (arg === '--skip-live-regression') {
      options.skipLiveRegression = true;
      continue;
    }
    if (arg === '--skip-browser-probes') {
      options.skipBrowserProbes = true;
      continue;
    }
    if (arg === '--skip-workflows') {
      options.skipWorkflows = true;
      continue;
    }
    if (arg === '--include-live-regression') {
      options.includeLiveRegression = true;
      continue;
    }
    if (arg === '--include-browser-probes') {
      options.includeBrowserProbes = true;
      continue;
    }
    if (arg === '--include-workflows') {
      options.includeWorkflows = true;
      continue;
    }
    if (arg === '--include-auth-gated') {
      options.includeAuthGated = true;
      continue;
    }
    if (arg === '--include-high-friction') {
      options.includeHighFriction = true;
      continue;
    }
    if (arg === '--include-social-posts') {
      options.includeSocialPosts = true;
      continue;
    }
    if (arg === '--release-gate') {
      options.releaseGate = true;
      continue;
    }
    if (arg === '--out') {
      const next = argv[index + 1];
      if (!next || next.startsWith('--')) {
        throw new Error('--out requires a file path.');
      }
      options.out = next;
      index += 1;
      continue;
    }
    if (arg.startsWith('--out=')) {
      options.out = arg.slice('--out='.length);
      continue;
    }
    throw new Error(`Unknown option: ${arg}`);
  }

  if (options.releaseGate && options.smoke) {
    throw new Error('--release-gate cannot be combined with --smoke.');
  }

  const runLiveRegression = options.releaseGate
    ? options.includeLiveRegression
    : (options.smoke ? options.includeLiveRegression : !options.skipLiveRegression);
  const runBrowserProbes = options.smoke
    ? options.includeBrowserProbes
    : !options.skipBrowserProbes;
  const runWorkflows = options.smoke
    ? options.includeWorkflows
    : !options.skipWorkflows;

  const mode = options.smoke ? 'smoke' : 'full';
  return {
    ...options,
    mode,
    runLiveRegression,
    runBrowserProbes,
    runWorkflows,
    runAuthGated: true,
    runHighFriction: true,
    runSocialPostCases: options.releaseGate || options.includeSocialPosts,
    strictGate: options.releaseGate,
    out: options.out || `/tmp/odb-provider-live-matrix-${mode}-${Date.now()}.json`
  };
}

/**
 * Build environment for nested live-regression execution.
 * Provider matrix keeps using the same daemon after live-regression, so
 * LIVE_MATRIX_STOP_DAEMON must stay disabled by default.
 */
export function buildLiveRegressionEnv(env, { useGlobalEnv = false, stopDaemon = false } = {}) {
  return {
    ...env,
    LIVE_MATRIX_USE_GLOBAL: useGlobalEnv ? '1' : '0',
    LIVE_MATRIX_STOP_DAEMON: stopDaemon ? '1' : '0'
  };
}

function getFreePort() {
  return new Promise((resolve, reject) => {
    const server = net.createServer();
    server.on('error', reject);
    server.listen(0, '127.0.0.1', () => {
      const addr = server.address();
      if (!addr || typeof addr === 'string') {
        server.close(() => reject(new Error('Unable to allocate free port')));
        return;
      }
      const port = addr.port;
      server.close(() => resolve(port));
    });
  });
}

function registerHeadlessMarker(marker) {
  if (typeof marker === 'string' && marker.length > 0) {
    ownedHeadlessMarkers.add(marker);
  }
}

function registerHeadlessProfileDir(profileDir) {
  if (typeof profileDir === 'string' && profileDir.length > 0) {
    ownedHeadlessProfileDirs.add(profileDir);
    registerHeadlessMarker(profileDir);
  }
}

function unregisterHeadlessProfileDir(profileDir) {
  if (typeof profileDir === 'string' && profileDir.length > 0) {
    ownedHeadlessProfileDirs.delete(profileDir);
  }
}

function removeDirSafe(targetDir) {
  if (typeof targetDir !== 'string' || targetDir.length === 0) return;
  if (!fs.existsSync(targetDir)) return;
  try {
    fs.rmSync(targetDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
  } catch {
    // ignore cleanup races
  }
}

function killProcessHard(pid) {
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return;
  try {
    process.kill(pid, 'SIGTERM');
  } catch {
    return;
  }
  try {
    process.kill(pid, 0);
    process.kill(pid, 'SIGKILL');
  } catch {
    // process exited after SIGTERM
  }
}

function killOwnedHeadlessChromeWorkers() {
  const markers = [...ownedHeadlessMarkers].filter((entry) => typeof entry === 'string' && entry.length > 0);
  const isTempProfileWorker = (command) => command.includes('/opendevbrowser/projects/') && command.includes('/temp-profiles/');
  const processList = spawnSync('ps', ['-ax', '-o', 'pid=,command='], {
    encoding: 'utf-8',
    maxBuffer: MAX_BUFFER
  });
  if ((processList.status ?? 1) !== 0) return;
  const lines = String(processList.stdout ?? '').split(/\r?\n/);
  for (const line of lines) {
    const trimmed = line.trim();
    if (trimmed.length === 0) continue;
    const match = trimmed.match(/^(\d+)\s+(.*)$/);
    if (!match) continue;
    const pid = Number.parseInt(match[1], 10);
    const command = match[2] ?? '';
    const tempProfileWorker = isTempProfileWorker(command);
    const headlessOwnedWorker = command.includes(HEADLESS_PROCESS_MATCH) && markers.some((marker) => command.includes(marker));
    if (!tempProfileWorker && !headlessOwnedWorker) continue;
    killProcessHard(pid);
  }
}

function listTempProfileWorkers() {
  const processList = spawnSync('ps', ['-ax', '-o', 'pid=,command='], {
    encoding: 'utf-8',
    maxBuffer: MAX_BUFFER
  });
  if ((processList.status ?? 1) !== 0) return [];
  const rows = [];
  const lines = String(processList.stdout ?? '').split(/\r?\n/);
  for (const line of lines) {
    const trimmed = line.trim();
    if (trimmed.length === 0) continue;
    const match = trimmed.match(/^(\d+)\s+(.*)$/);
    if (!match) continue;
    const pid = Number.parseInt(match[1], 10);
    const command = match[2] ?? '';
    if (!command.includes('/opendevbrowser/projects/') || !command.includes('/temp-profiles/')) continue;
    rows.push({ pid, command });
  }
  return rows;
}

function cleanupOwnedHeadlessResources(force = false) {
  if (headlessCleanupCompleted && !force) return;
  headlessCleanupCompleted = true;
  killOwnedHeadlessChromeWorkers();
  for (const profileDir of [...ownedHeadlessProfileDirs]) {
    removeDirSafe(profileDir);
    unregisterHeadlessProfileDir(profileDir);
  }
}

function installHeadlessCleanupHooks() {
  if (headlessCleanupHooksInstalled) return;
  headlessCleanupHooksInstalled = true;
  process.on('exit', cleanupOwnedHeadlessResources);
  for (const signal of ['SIGINT', 'SIGTERM']) {
    process.on(signal, () => {
      cleanupOwnedHeadlessResources();
      process.exit(signal === 'SIGINT' ? 130 : 143);
    });
  }
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function parseJsonLoose(text) {
  const value = String(text ?? '').trim();
  if (!value) return null;

  try {
    return JSON.parse(value);
  } catch {
    // continue
  }

  const lines = value.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
  let parsed = null;
  for (const line of lines) {
    try {
      parsed = JSON.parse(line);
    } catch {
      continue;
    }
  }
  if (parsed) return parsed;

  const objectStart = value.indexOf('{');
  if (objectStart >= 0) {
    try {
      return JSON.parse(value.slice(objectStart));
    } catch {
      // ignore
    }
  }

  return null;
}

function isTimeoutDetail(detail) {
  return /timed out|timeout/i.test(String(detail || ''));
}

export function isEnvLimitedDetail(detail) {
  return /auth|challenge|captcha|token required|environment|extension not connected|ops client not connected|rate limit|timed out|profile is locked|processsingleton|singletonlock|already in use by another instance/i.test(
    String(detail || '')
  );
}

function classifyNonZeroProviderStatus() {
  return 'fail';
}

export function buildDefaultSkippedStep(id, detail, data = {}) {
  return {
    id,
    status: 'skipped',
    detail,
    data: { skipped: true, ...data }
  };
}

export function isApprovedProductVideoEnvLimitedDetail(detail) {
  const normalized = String(detail || '').toLowerCase();
  return PRODUCT_VIDEO_ENV_LIMITED_DETAIL_MATCHERS.some((matcher) => normalized.includes(matcher));
}

function readPositiveCountKeys(value) {
  if (!value || typeof value !== 'object') return [];
  return Object.entries(value)
    .filter(([, count]) => typeof count === 'number' && Number.isFinite(count) && count > 0)
    .map(([key]) => key);
}

function readProductVideoAmazonMeta(data) {
  if (!data || typeof data !== 'object') return {};
  if (data.meta && typeof data.meta === 'object') {
    return data.meta;
  }
  if (data.error?.details && typeof data.error.details === 'object') {
    return data.error.details;
  }
  return {};
}

function classifyStructuredProductVideoAmazonFailure(data) {
  const meta = readProductVideoAmazonMeta(data);
  const summary = typeof meta.primaryConstraintSummary === 'string'
    ? meta.primaryConstraintSummary
    : '';
  if (!isApprovedProductVideoEnvLimitedDetail(summary)) {
    return null;
  }
  const reasonCodes = readPositiveCountKeys(meta.reasonCodeDistribution);
  if (reasonCodes.length > 0 && !reasonCodes.every((code) => MATRIX_ENV_LIMITED_CODES.has(code))) {
    return 'fail';
  }
  return 'env_limited';
}

function readStructuredCount(value) {
  return typeof value === 'number' && Number.isFinite(value) ? value : null;
}

export function classifyProductVideoAmazonStatus(status, detail, data = {}) {
  if (status === 0) {
    return 'pass';
  }
  const structuredStatus = classifyStructuredProductVideoAmazonFailure(data);
  if (structuredStatus) {
    return structuredStatus;
  }
  return isApprovedProductVideoEnvLimitedDetail(detail) ? 'env_limited' : 'fail';
}

function readArtifactPath(data) {
  return typeof data?.artifact_path === 'string' && data.artifact_path.trim()
    ? data.artifact_path
    : null;
}

export function validateSuccessfulWorkflowArtifact(data, workflow) {
  const artifactPath = readArtifactPath(data);
  if (!artifactPath) {
    return {
      artifactPath: null,
      detail: `successful_${workflow}_workflow_missing_artifact_path`
    };
  }
  if (!fs.existsSync(artifactPath) || !fs.statSync(artifactPath).isDirectory()) {
    return {
      artifactPath,
      detail: `successful_${workflow}_workflow_artifact_path_missing_on_disk`
    };
  }
  if (path.basename(path.dirname(artifactPath)) !== workflow) {
    return {
      artifactPath,
      detail: `successful_${workflow}_workflow_artifact_namespace_mismatch`
    };
  }
  const manifestPath = path.join(artifactPath, 'bundle-manifest.json');
  if (!fs.existsSync(manifestPath) || !fs.statSync(manifestPath).isFile()) {
    return {
      artifactPath,
      detail: `successful_${workflow}_workflow_bundle_manifest_missing`
    };
  }
  const reportPath = path.join(artifactPath, 'report.md');
  if (workflow === 'research' && (!fs.existsSync(reportPath) || !fs.statSync(reportPath).isFile())) {
    return {
      artifactPath,
      detail: 'successful_research_workflow_report_missing'
    };
  }
  return { artifactPath, detail: null };
}

export function classifySuccessfulResearchWorkflow(records, artifactValidation) {
  if (records <= 0) {
    return {
      status: 'fail',
      detail: 'successful_research_workflow_returned_no_records'
    };
  }
  if (artifactValidation.detail) {
    return { status: 'fail', detail: artifactValidation.detail };
  }
  return { status: 'pass', detail: null };
}

export function classifyNestedLiveRegressionStatus(status, parsed, { strictGate = false } = {}) {
  const failCount = readStructuredCount(parsed?.counts?.fail);
  const envLimitedCount = readStructuredCount(parsed?.counts?.env_limited);
  const hasStructuredCounts = failCount !== null || envLimitedCount !== null;
  const resolvedFailCount = failCount ?? 0;
  const resolvedEnvLimitedCount = envLimitedCount ?? 0;
  const nestedStatus = status === 0
    ? (resolvedFailCount > 0 ? 'fail' : (resolvedEnvLimitedCount > 0 ? 'env_limited' : 'pass'))
    : (hasStructuredCounts && resolvedFailCount === 0 && resolvedEnvLimitedCount > 0 ? 'env_limited' : 'fail');
  return strictGate && nestedStatus !== 'pass' ? 'fail' : nestedStatus;
}

function createNestedLiveRegressionStep(mode, { strictGate = false } = {}) {
  return {
    id: 'matrix.live_regression_modes',
    status: classifyNestedLiveRegressionStatus(mode.status, mode.json, { strictGate }),
    data: mode.json ?? null,
    detail: mode.status === 0 ? null : (mode.stderr || mode.stdout || null)
  };
}

export async function runNestedLiveRegressionMode(
  env,
  { strictGate = false, useGlobalEnv = false } = {},
  {
    nodeRunner = runNode,
    daemonRestorer = restoreDaemonAfterNestedLiveRegression
  } = {}
) {
  const matrixArgs = ['scripts/live-regression-matrix.mjs'];
  if (strictGate) {
    matrixArgs.push('--release-gate');
  }
  const mode = nodeRunner(matrixArgs, buildLiveRegressionEnv(env, {
    useGlobalEnv,
    stopDaemon: false
  }), {
    allowFailure: true,
    timeoutMs: NESTED_LIVE_REGRESSION_TIMEOUT_MS
  });
  const step = createNestedLiveRegressionStep(mode, { strictGate });
  try {
    const daemonRestore = await daemonRestorer(env);
    return { restarted: daemonRestore.restarted, step };
  } catch (error) {
    return { restarted: false, step: { ...step, status: 'fail', detail: String(error) } };
  }
}

function relayNeedsRestartAfterNestedRun(status) {
  const relay = status?.json?.data?.relay;
  if (!relay || relay.running !== true) {
    return true;
  }
  return hasDirtyRelayClients(relay)
    || (relay.extensionConnected === true && relay.extensionHandshakeComplete !== true);
}

function summarizeCliDetail(result) {
  if (result.errorCode === 'ETIMEDOUT') {
    return 'timed out';
  }
  if (result.signal === 'SIGTERM' && result.status !== 0) {
    return 'terminated by signal';
  }
  const fromJson = result.json?.error || result.json?.message;
  if (typeof fromJson === 'string' && fromJson.trim().length > 0) {
    return fromJson;
  }
  if (result.stderr && result.stderr.trim().length > 0) {
    return result.stderr.trim();
  }
  if (result.stdout && result.stdout.trim().length > 0) {
    return result.stdout.trim();
  }
  return 'unknown failure';
}

export const REQUIRED_PLAYWRIGHT_CORE_FILES = [
  'lib/inprocess.js',
  'lib/inProcessFactory.js',
  'lib/androidServerImpl.js',
  'lib/browserServerImpl.js',
  'lib/client/connection.js',
  'lib/utilsBundle.js',
  'lib/server/index.js',
  'lib/server/registry/index.js'
];

let playwrightCoreIntegrityChecked = false;
let playwrightCoreIntegrityRepairAttempted = false;

function hasPlaywrightCoreIntegrity() {
  return REQUIRED_PLAYWRIGHT_CORE_FILES.every((relativePath) => (
    fs.existsSync(path.join(ROOT, 'node_modules', 'playwright-core', relativePath))
  ));
}

function restorePlaywrightCoreFromTarball() {
  const packageJsonPath = path.join(ROOT, 'node_modules', 'playwright-core', 'package.json');
  let version = '1.58.2';
  if (fs.existsSync(packageJsonPath)) {
    try {
      const parsed = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
      if (typeof parsed.version === 'string' && parsed.version.length > 0) {
        version = parsed.version;
      }
    } catch {
      // use default fallback version
    }
  }

  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'odb-playwright-core-'));
  try {
    const pack = spawnSync('npm', ['pack', `playwright-core@${version}`, '--silent'], {
      cwd: tmpDir,
      encoding: 'utf-8',
      maxBuffer: MAX_BUFFER
    });
    if ((pack.status ?? 1) !== 0) {
      throw new Error(`npm pack playwright-core@${version} failed: ${pack.stderr || pack.stdout || 'unknown error'}`);
    }

    const tarball = fs.readdirSync(tmpDir).find((entry) => entry.startsWith('playwright-core-') && entry.endsWith('.tgz'));
    if (!tarball) {
      throw new Error('playwright-core tarball not found after npm pack');
    }

    const extract = spawnSync('tar', ['-xzf', tarball], {
      cwd: tmpDir,
      encoding: 'utf-8',
      maxBuffer: MAX_BUFFER
    });
    if ((extract.status ?? 1) !== 0) {
      throw new Error(`tar extract failed for ${tarball}: ${extract.stderr || extract.stdout || 'unknown error'}`);
    }

    const sync = spawnSync('rsync', ['-a', '--delete', `${tmpDir}/package/`, `${ROOT}/node_modules/playwright-core/`], {
      encoding: 'utf-8',
      maxBuffer: MAX_BUFFER
    });
    if ((sync.status ?? 1) !== 0) {
      throw new Error(`rsync repair failed: ${sync.stderr || sync.stdout || 'unknown error'}`);
    }
  } finally {
    fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
  }
}

function ensurePlaywrightCoreIntegrity() {
  if (playwrightCoreIntegrityChecked) return;
  if (!hasPlaywrightCoreIntegrity()) {
    restorePlaywrightCoreFromTarball();
  }
  playwrightCoreIntegrityChecked = true;
}

function runCli(env, args, { allowFailure = false, timeoutMs = 180000 } = {}) {
  ensurePlaywrightCoreIntegrity();

  const res = spawnSync(process.execPath, [CLI, ...args, '--output-format', 'json'], {
    cwd: ROOT,
    env,
    encoding: 'utf-8',
    timeout: timeoutMs,
    maxBuffer: MAX_BUFFER
  });
  const json = parseJsonLoose(res.stdout ?? '');
  const status = res.status ?? 1;
  const payload = {
    status,
    stdout: res.stdout ?? '',
    stderr: res.stderr ?? '',
    json,
    signal: typeof res.signal === 'string' ? res.signal : null,
    errorCode: typeof res.error?.code === 'string' ? res.error.code : null
  };
  const detail = summarizeCliDetail(payload);

  if (status !== 0 && !playwrightCoreIntegrityRepairAttempted && /Cannot find module '\\.\/lib\//i.test(detail)) {
    playwrightCoreIntegrityRepairAttempted = true;
    playwrightCoreIntegrityChecked = false;
    ensurePlaywrightCoreIntegrity();
    return runCli(env, args, { allowFailure, timeoutMs });
  }

  if (!allowFailure && status !== 0) {
    throw new Error(`CLI failed (${args.join(' ')}): ${detail}`);
  }

  return {
    ...payload,
    detail
  };
}

function runNode(commandArgs, env, { allowFailure = false, timeoutMs = 600000 } = {}) {
  const res = spawnSync(process.execPath, commandArgs, {
    cwd: ROOT,
    env,
    encoding: 'utf-8',
    timeout: timeoutMs,
    maxBuffer: MAX_BUFFER
  });
  const status = res.status ?? 1;
  const stdout = res.stdout ?? '';
  const stderr = res.stderr ?? '';
  if (!allowFailure && status !== 0) {
    throw new Error(`Node command failed (${commandArgs.join(' ')}): ${stderr || stdout || 'unknown failure'}`);
  }
  return {
    status,
    stdout,
    stderr,
    json: parseJsonLoose(stdout)
  };
}

function startDaemon(env) {
  const child = spawn(process.execPath, [CLI, 'serve', '--output-format', 'json'], {
    cwd: ROOT,
    env,
    detached: true,
    stdio: 'ignore'
  });
  child.unref();
}

function stopDaemon(env) {
  runCli(env, ['serve', '--stop'], { allowFailure: true, timeoutMs: 15000 });
}

async function waitForDaemonReady(env, timeoutMs = 30000) {
  const start = Date.now();
  while (Date.now() - start < timeoutMs) {
    const status = runCli(env, ['status', '--daemon'], { allowFailure: true, timeoutMs: 15000 });
    if (status.status === 0 && !relayNeedsRestartAfterNestedRun(status)) {
      return status;
    }
    await sleep(500);
  }
  return null;
}

export async function restoreDaemonAfterNestedLiveRegression(
  env,
  {
    statusReader = (daemonEnv) => runCli(daemonEnv, ['status', '--daemon'], { allowFailure: true, timeoutMs: 15000 }),
    stopper = stopDaemon,
    starter = startDaemon,
    waiter = waitForDaemonReady
  } = {}
) {
  const status = statusReader(env);
  if (status.status === 0 && !relayNeedsRestartAfterNestedRun(status)) {
    return { restarted: false, status };
  }
  if (status.status === 0) {
    stopper(env);
  }
  starter(env);
  const ready = await waiter(env, 30000);
  if (!ready || relayNeedsRestartAfterNestedRun(ready)) {
    throw new Error('daemon not ready after nested live regression');
  }
  return { restarted: true, status: ready };
}

async function waitForExtensionReady(env, timeoutMs = EXTENSION_LAUNCH_WAIT_TIMEOUT_MS) {
  const start = Date.now();
  while (Date.now() - start < timeoutMs) {
    const status = runCli(env, ['status', '--daemon'], { allowFailure: true, timeoutMs: 15000 });
    const relay = status.json?.data?.relay ?? null;
    if (
      status.status === 0
      && relay?.extensionConnected === true
      && relay?.extensionHandshakeComplete === true
    ) {
      return true;
    }
    await sleep(1000);
  }
  return false;
}

async function launchExtensionWithRecovery(env) {
  const launchArgs = [
    'launch',
    '--extension-only',
    '--wait-for-extension',
    '--wait-timeout-ms',
    String(EXTENSION_LAUNCH_WAIT_TIMEOUT_MS)
  ];
  const launchTimeoutMs = Math.max(120000, EXTENSION_LAUNCH_WAIT_TIMEOUT_MS + 30000);

  let last = runCli(env, launchArgs, {
    allowFailure: true,
    timeoutMs: launchTimeoutMs
  });
  if (last.status === 0) {
    return last;
  }

  for (let attempt = 1; attempt < EXTENSION_LAUNCH_RECOVERY_RETRIES; attempt += 1) {
    if (!isEnvLimitedDetail(last.detail)) {
      break;
    }
    await waitForExtensionReady(env);
    await sleep(1000 * attempt);
    last = runCli(env, launchArgs, {
      allowFailure: true,
      timeoutMs: launchTimeoutMs
    });
    if (last.status === 0) {
      return last;
    }
  }
  return last;
}

export function classifyMatrixRecords(recordsCount, failures, extra = {}) {
  const verdict = classifyLaneRecords(recordsCount, failures, {
    envLimitedCodes: MATRIX_ENV_LIMITED_CODES,
    allowExpectedUnavailable: extra.allowExpectedUnavailable === true,
    allowNoRecordsNoFailures: extra.allowNoRecordsNoFailures === true,
    expectedUnavailableMessageDetails: [
      {
        includes: 'posting transport is not configured',
        detail: 'expected_gating_post_transport_not_configured'
      }
    ]
  });
  return {
    status: verdict.status,
    reason: verdict.detail
  };
}

export function resolveMatrixSocialSearchStatus(input) {
  const execution = input.execution ?? {};
  const records = Array.isArray(execution.records) ? execution.records : [];
  const failures = Array.isArray(execution.failures) ? execution.failures : [];
  const reasonCodes = normalizedCodesFromFailures(failures);
  const hasExecutionPayload = execution.hasExecutionPayload === true;
  const linkedinAuthWall = input.platform === 'linkedin' && hasLinkedInAuthWall(records);
  const parityProbeCandidates = [
    `browser.extension.${input.platform}.search`,
    `browser.managed.${input.platform}.search`,
    `browser.cdp_connect.${input.platform}.search`
  ];
  const probeParitySource = parityProbeCandidates.find((probeId) => (
    input.reportSteps?.some((step) => step.id === probeId && step.status === 'pass')
  )) ?? null;

  if (input.resultStatus === 0 && !hasExecutionPayload) {
    return {
      status: 'fail',
      detail: 'missing_execution_payload',
      reasonCodes,
      linkedinAuthWall,
      extensionProbeParity: probeParitySource !== null,
      probeParitySource,
      expectedTiktokTimeoutGate: false
    };
  }

  const verdict = classifyMatrixRecords(records.length, failures);
  const status = input.resultStatus === 0
    ? verdict.status
    : classifyNonZeroProviderStatus(input.resultDetail);
  const detail = input.resultStatus === 0
    ? (linkedinAuthWall ? 'pass_with_auth_wall_markers' : verdict.reason)
    : input.resultDetail;
  const expectedTiktokTimeoutGate = input.strictGate === true
    && input.platform === 'tiktok'
    && status === 'env_limited'
    && reasonCodes.includes('timeout');

  return {
    status,
    detail,
    reasonCodes,
    linkedinAuthWall,
    extensionProbeParity: probeParitySource !== null,
    probeParitySource,
    expectedTiktokTimeoutGate
  };
}

export function resolveMatrixSocialPostStatus(input) {
  const reasonCodes = Array.isArray(input.reasonCodes) ? input.reasonCodes : [];
  const expectedTransportGateVerified = input.strictGate === true
    && input.verdict?.status === 'env_limited'
    && input.verdict?.reason === 'expected_gating_post_transport_not_configured';
  const expectedPolicyGateVerified = input.strictGate === true
    && input.verdict?.status === 'env_limited'
    && reasonCodes.length > 0
    && reasonCodes.every((code) => (
      code === 'policy_blocked'
      || code === 'challenge_detected'
      || code === 'cooldown_active'
    ));
  return {
    status: input.resultStatus === 0
      ? input.verdict.status
      : classifyNonZeroProviderStatus(input.resultDetail),
    detail: input.resultStatus === 0 ? input.verdict.reason : input.resultDetail,
    expectedGateVerified: expectedTransportGateVerified || expectedPolicyGateVerified,
    expectedTransportGateVerified,
    expectedPolicyGateVerified
  };
}

function collectMacroExecution(result) {
  const execution = result.json?.data?.execution;
  const records = Array.isArray(execution?.records) ? execution.records : [];
  const failures = Array.isArray(execution?.failures) ? execution.failures : [];
  const providerOrder = Array.isArray(execution?.meta?.providerOrder) ? execution.meta.providerOrder : [];
  return {
    records,
    failures,
    providerOrder,
    meta: execution?.meta ?? null,
    raw: execution ?? null,
    hasExecutionPayload: Boolean(execution)
  };
}

export function resolveSocialFallbackRetry(currentResult, currentExecution, retryResult) {
  const retryExecution = collectMacroExecution(retryResult);
  const hasRetrySignal = retryExecution.records.length > 0 || retryExecution.failures.length > 0;
  if (!hasRetrySignal) {
    return {
      result: currentResult,
      execution: currentExecution,
      usedFallbackQuery: false,
      fallbackQueryStatus: retryResult.status
    };
  }
  return {
    result: retryResult,
    execution: retryExecution,
    usedFallbackQuery: true,
    fallbackQueryStatus: retryResult.status
  };
}

function collectShoppingExecution(result) {
  const data = result.json?.data ?? {};
  const offers = Array.isArray(data?.offers) ? data.offers : [];
  const failures = Array.isArray(data?.meta?.failures) ? data.meta.failures : [];
  return {
    offers,
    failures,
    meta: data?.meta ?? null
  };
}

function findChromePath() {
  return findLocalChromeBinary();
}

async function waitForHttp(port, pathSuffix, timeoutMs = 30000) {
  const attemptFetch = async (url, requestTimeoutMs = 2500) => {
    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), requestTimeoutMs);
    try {
      return await fetch(url, { signal: controller.signal });
    } finally {
      clearTimeout(timer);
    }
  };

  const startedAt = Date.now();
  while (Date.now() - startedAt < timeoutMs) {
    try {
      const response = await attemptFetch(`http://127.0.0.1:${port}${pathSuffix}`);
      if (response.ok) return true;
    } catch {
      // retry
    }
    await sleep(250);
  }
  return false;
}

async function launchRemoteChrome(chromePath, options = {}) {
  const port = options.port ?? await getFreePort();
  const profileDir = options.profileDir ?? fs.mkdtempSync(path.join(os.tmpdir(), 'odb-provider-cdp-'));
  registerHeadlessProfileDir(profileDir);
  const args = [
    `--remote-debugging-port=${port}`,
    `--user-data-dir=${profileDir}`,
    '--disable-gpu',
    '--no-first-run',
    '--no-default-browser-check',
    'about:blank'
  ];
  if (options.headless !== false) {
    args.splice(2, 0, '--headless=new');
  }
  const processHandle = spawn(chromePath, args, { stdio: ['ignore', 'ignore', 'ignore'] });
  const ready = await waitForHttp(port, '/json/version', 30000);
  if (!ready) {
    if (!processHandle.killed) {
      processHandle.kill('SIGTERM');
    }
    throw new Error(`cdp chrome not ready on port ${port}`);
  }
  return { processHandle, port, profileDir };
}

function cleanupRemoteChrome(instance) {
  if (!instance) return;
  if (instance.processHandle && !instance.processHandle.killed) {
    try {
      instance.processHandle.kill('SIGTERM');
    } catch {
      // ignore kill failures
    }
    killProcessHard(instance.processHandle.pid);
  }
  if (instance.profileDir) {
    removeDirSafe(instance.profileDir);
    unregisterHeadlessProfileDir(instance.profileDir);
  }
}

function hasLinkedInAuthWall(records) {
  if (!Array.isArray(records) || records.length === 0) return false;
  const gated = records.filter((record) => {
    const url = typeof record?.url === 'string' ? record.url : '';
    if (/linkedin\.com\/(?:uas\/login|login)/i.test(url)) return true;
    try {
      return /(^|\.)static\.licdn\.com$/i.test(new URL(url).hostname);
    } catch {
      return false;
    }
  });
  return gated.length > 0 && gated.length === records.length;
}

async function buildRuntimeEnv(options) {
  if (options.useGlobalEnv) {
    return {
      env: process.env,
      runtimeMode: 'global',
      tempRoot: null,
      configDir: process.env.OPENCODE_CONFIG_DIR || null,
      cacheDir: process.env.OPENCODE_CACHE_DIR || null,
      daemonPort: null,
      relayPort: null
    };
  }

  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'odb-provider-live-'));
  const configDir = path.join(tempRoot, 'config');
  const cacheDir = path.join(tempRoot, 'cache');
  fs.mkdirSync(configDir, { recursive: true });
  fs.mkdirSync(cacheDir, { recursive: true });

  const daemonPort = await getFreePort();
  const relayPort = await getFreePort();
  const config = {
    daemonPort,
    daemonToken: randomUUID().replaceAll('-', ''),
    relayPort,
    relayToken: randomUUID().replaceAll('-', '')
  };
  fs.writeFileSync(path.join(configDir, 'opendevbrowser.jsonc'), `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });

  return {
    env: {
      ...process.env,
      OPENCODE_CONFIG_DIR: configDir,
      OPENCODE_CACHE_DIR: cacheDir
    },
    runtimeMode: 'isolated',
    tempRoot,
    configDir,
    cacheDir,
    daemonPort,
    relayPort
  };
}

function finalizeReport(report) {
  report.finishedAt = new Date().toISOString();
  report.durationMs = new Date(report.finishedAt).getTime() - new Date(report.startedAt).getTime();
  const counts = {
    pass: report.steps.filter((step) => step.status === 'pass').length,
    env_limited: report.steps.filter((step) => step.status === 'env_limited').length,
    fail: report.steps.filter((step) => step.status === 'fail').length
  };
  report.counts = counts;
  report.ok = Boolean(report.ok) && counts.fail === 0 && (!report.strictGate || counts.env_limited === 0);
}

async function runSocialBrowserProbes(pushStep, env) {
  const probeModes = ['managed', 'extension', 'cdpConnect'];

  for (const mode of probeModes) {
    const modeId = mode === 'cdpConnect' ? 'cdp_connect' : mode;
    let sessionId = null;
    let closeBrowser = false;
    let cdpInstance = null;

    try {
      if (mode === 'managed') {
        const browserProfile = `provider-browser-${Date.now().toString(36)}`;
        registerHeadlessMarker(browserProfile);
        const launchAttempts = [
          ['launch', '--no-extension', '--headless', '--profile', browserProfile],
          ['launch', '--no-extension', '--headless', '--persist-profile', 'false']
        ];

        let launchResult = null;
        let launchFailureDetail = null;
        for (const attemptArgs of launchAttempts) {
          const attempt = runCli(env, attemptArgs, { allowFailure: true, timeoutMs: 120000 });
          if (attempt.status === 0) {
            launchResult = attempt;
            break;
          }
          launchFailureDetail = attempt.detail;
        }
        if (!launchResult && isTimeoutDetail(launchFailureDetail)) {
          const recoveryAttempt = runCli(
            env,
            ['launch', '--no-extension', '--headless', '--persist-profile', 'false'],
            { allowFailure: true, timeoutMs: 180000 }
          );
          if (recoveryAttempt.status === 0) {
            launchResult = recoveryAttempt;
          } else {
            launchFailureDetail = recoveryAttempt.detail;
          }
        }
        if (!launchResult) {
          const detail = launchFailureDetail ?? 'managed launch failed for all launch attempts';
          pushStep({
            id: `browser.${modeId}.launch`,
            status: isEnvLimitedDetail(detail) ? 'env_limited' : 'fail',
            detail
          });
          continue;
        }

        sessionId = launchResult.json?.data?.sessionId ?? null;
        closeBrowser = true;
      } else if (mode === 'extension') {
        const launch = await launchExtensionWithRecovery(env);
        if (launch.status !== 0) {
          pushStep({
            id: `browser.${modeId}.launch`,
            status: isEnvLimitedDetail(launch.detail) ? 'env_limited' : 'fail',
            detail: launch.detail
          });
          continue;
        }
        sessionId = launch.json?.data?.sessionId ?? null;
      } else {
        const chromePath = findChromePath();
        if (!chromePath) {
          pushStep({
            id: `browser.${modeId}.launch`,
            status: 'env_limited',
            detail: 'chrome binary unavailable for cdpConnect probes'
          });
          continue;
        }
        cdpInstance = await launchRemoteChrome(chromePath, { headless: true });
        let connect = runCli(env, ['connect', '--host', '127.0.0.1', '--cdp-port', String(cdpInstance.port)], {
          allowFailure: true,
          timeoutMs: 120000
        });
        if (connect.status !== 0 && isTimeoutDetail(connect.detail)) {
          connect = runCli(env, ['connect', '--host', '127.0.0.1', '--cdp-port', String(cdpInstance.port)], {
            allowFailure: true,
            timeoutMs: 180000
          });
        }
        if (connect.status !== 0) {
          pushStep({
            id: `browser.${modeId}.launch`,
            status: isEnvLimitedDetail(connect.detail) ? 'env_limited' : 'fail',
            detail: connect.detail
          });
          continue;
        }
        sessionId = connect.json?.data?.sessionId ?? null;
      }

      if (!sessionId) {
        pushStep({
          id: `browser.${modeId}.launch`,
          status: 'fail',
          detail: `${mode} launch returned no sessionId`
        });
        continue;
      }

      pushStep({
        id: `browser.${modeId}.launch`,
        status: 'pass',
        detail: null
      });

      for (const target of BROWSER_REALWORLD_TARGETS) {
        const isExtensionHeavyProbe = mode === 'extension' && EXTENSION_HEAVY_NAV_TARGETS.has(target.id);
        const maxAttempts = isExtensionHeavyProbe ? EXTENSION_OPS_NAV_RETRIES : 1;
        const navTimeoutMs = mode === 'extension' ? EXTENSION_OPS_NAV_TIMEOUT_MS : 60000;
        const cliTimeoutMs = mode === 'extension' ? EXTENSION_OPS_CLI_TIMEOUT_MS : 120000;
        const waitUntil = mode === 'extension' ? 'domcontentloaded' : 'load';
        let goto = null;
        let debug = null;
        let attemptCount = 0;

        for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
          attemptCount = attempt;
          goto = runCli(
            env,
            ['goto', '--session-id', sessionId, '--url', target.url, '--wait-until', waitUntil, '--timeout-ms', String(navTimeoutMs)],
            { allowFailure: true, timeoutMs: cliTimeoutMs }
          );
          debug = runCli(env, ['debug-trace-snapshot', '--session-id', sessionId, '--max', '120'], {
            allowFailure: true,
            timeoutMs: cliTimeoutMs
          });
          const gotoTimedOut = goto.status !== 0 && isTimeoutDetail(goto.detail);
          if (!gotoTimedOut || attempt === maxAttempts) {
            break;
          }
          await sleep(750 * attempt);
        }

        const gotoResult = goto ?? { status: 1, detail: 'goto probe did not execute' };
        const debugResult = debug ?? { status: 1, json: null, detail: 'debug probe did not execute' };
        const blockerState = debugResult.json?.data?.meta?.blockerState;
        const blockerType = debugResult.json?.data?.meta?.blocker?.type ?? null;
        const gotoDetail = gotoResult.status === 0 ? null : gotoResult.detail;
        const debugDetail = debugResult.status === 0 ? null : debugResult.detail;
        const detail = gotoDetail ?? debugDetail;
        const extensionTimeoutRecovered = mode === 'extension'
          && gotoResult.status !== 0
          && isTimeoutDetail(gotoDetail)
          && debugResult.status === 0;
        const probeStatus = gotoResult.status === 0 && debugResult.status === 0
          ? 'pass'
          : (extensionTimeoutRecovered
            ? 'pass'
            : (isEnvLimitedDetail(detail) ? 'env_limited' : 'fail'));
        const probeDetail = extensionTimeoutRecovered ? 'timeout_recovered_via_debug_probe' : detail;

        pushStep({
          id: `browser.${modeId}.${target.id}`,
          status: probeStatus,
          data: {
            blockerState: typeof blockerState === 'string' ? blockerState : null,
            blockerType,
            gotoStatus: gotoResult.status,
            debugStatus: debugResult.status,
            attemptCount,
            timeoutRecoveredViaDebug: extensionTimeoutRecovered
          },
          detail: probeDetail
        });
      }
    } catch (error) {
      pushStep({ id: `browser.${modeId}.social_realworld`, status: 'fail', detail: String(error) });
    } finally {
      if (sessionId) {
        const disconnectArgs = ['disconnect', '--session-id', sessionId, ...(closeBrowser ? ['--close-browser'] : [])];
        runCli(env, disconnectArgs, { allowFailure: true, timeoutMs: 30000 });
      }
      cleanupRemoteChrome(cdpInstance);
    }
  }
}

function webCommunityCases(smoke) {
  const all = [
    {
      id: 'provider.web.search.keyword',
      args: ['macro-resolve', '--execute', '--expression', '@web.search("site:developer.mozilla.org playwright locator", 4)', '--timeout-ms', '120000']
    },
    {
      id: 'provider.web.search.url',
      args: ['macro-resolve', '--execute', '--expression', '@web.search("https://example.com", 2)', '--timeout-ms', '120000']
    },
    {
      id: 'provider.web.fetch.url',
      args: ['macro-resolve', '--execute', '--expression', '@web.fetch("https://example.com")', '--timeout-ms', '120000']
    },
    {
      id: 'provider.community.search.keyword',
      args: ['macro-resolve', '--execute', '--expression', '@community.search("browser automation failures", 4)', '--timeout-ms', '120000', ...SIGNED_IN_BROWSER_ARGS, '--challenge-automation-mode', 'browser_with_helper']
    },
    {
      id: 'provider.community.search.url',
      args: ['macro-resolve', '--execute', '--expression', '@community.search("https://www.reddit.com/r/programming", 2)', '--timeout-ms', '120000', ...SIGNED_IN_BROWSER_ARGS, '--challenge-automation-mode', 'browser_with_helper']
    }
  ];
  return smoke ? all.slice(0, 4) : all;
}

async function main() {
  const options = parseArgs(process.argv.slice(2));
  installHeadlessCleanupHooks();
  const runtime = await buildRuntimeEnv(options);
  registerHeadlessMarker(runtime.cacheDir ?? '');
  registerHeadlessMarker(runtime.tempRoot ?? '');
  const env = runtime.env;
  let daemonStartedByScript = false;

  const report = {
    startedAt: new Date().toISOString(),
    root: ROOT,
    out: options.out,
    mode: options.mode,
    strictGate: options.strictGate,
    smoke: options.smoke,
    runLiveRegression: options.runLiveRegression,
    runBrowserProbes: options.runBrowserProbes,
    runWorkflows: options.runWorkflows,
    runAuthGated: options.runAuthGated,
    runHighFriction: options.runHighFriction,
    runSocialPostCases: options.runSocialPostCases,
    env: {
      runtimeMode: runtime.runtimeMode,
      configDir: runtime.configDir,
      cacheDir: runtime.cacheDir,
      daemonPort: runtime.daemonPort,
      relayPort: runtime.relayPort
    },
    steps: [],
    ok: true
  };

  const progressLoggingEnabled = process.env.PROVIDER_LIVE_PROGRESS === '1';
  const pushStep = (step) => {
    report.steps.push(step);
    if (progressLoggingEnabled) {
      const detailSuffix = typeof step.detail === 'string' && step.detail.length > 0
        ? ` (${step.detail})`
        : '';
      console.error(`[provider-live] ${step.id} -> ${step.status}${detailSuffix}`);
    }
  };
  const providerCoverage = buildProviderCoverageSummary({
    smoke: options.smoke,
    runAuthGated: options.runAuthGated,
    runHighFriction: options.runHighFriction,
    releaseGate: options.strictGate
  });
  report.providerCoverage = providerCoverage;
  pushStep({
    id: 'infra.provider_scenario_coverage',
    status: options.strictGate ? (providerCoverage.ok ? 'pass' : 'fail') : 'pass',
    detail: providerCoverage.ok
      ? null
      : `Missing provider coverage: ${providerCoverage.missingProviderIds.join(', ')}`,
    data: {
      strictGate: options.strictGate,
      missingProviderIds: providerCoverage.missingProviderIds,
      extraScenarioProviderIds: providerCoverage.extraScenarioProviderIds,
      expectedCount: providerCoverage.expected.all.length,
      scenarioCount: providerCoverage.scenarios.all.length
    }
  });
  if (options.strictGate && !providerCoverage.ok) {
    report.ok = false;
  }

  try {
    const daemonStatusAttempts = [];
    let existing = null;
    for (let attempt = 0; attempt < 3; attempt += 1) {
      existing = runCli(env, ['status', '--daemon'], { allowFailure: true, timeoutMs: 15000 });
      daemonStatusAttempts.push({
        attempt: attempt + 1,
        status: existing.status,
        detail: existing.detail
      });
      if (existing.status === 0) break;
      if (attempt < 2) {
        await sleep(750);
      }
    }

    if (progressLoggingEnabled) {
      const statusDetail = existing.status === 0
        ? 'ok'
        : (existing.detail || existing.stderr || existing.stdout || 'status_probe_failed');
      console.error(`[provider-live] infra.daemon_status_probe -> exit=${existing.status} ${statusDetail}`);
    }
    let ready = null;

    if (existing.status === 0) {
      ready = existing;
      pushStep({
        id: 'infra.daemon_ready',
        status: 'pass',
        data: { reusedExistingDaemon: true, daemonStatusAttempts }
      });
    } else {
      startDaemon(env);
      daemonStartedByScript = true;
      ready = await waitForDaemonReady(env, 30000);
      if (!ready) {
        throw new Error('daemon not ready');
      }
      pushStep({
        id: 'infra.daemon_ready',
        status: 'pass',
        data: { reusedExistingDaemon: false, daemonStatusAttempts }
      });
    }

    if (options.runLiveRegression) {
      const nestedLiveRegression = await runNestedLiveRegressionMode(env, {
        strictGate: options.strictGate,
        useGlobalEnv: options.useGlobalEnv
      });
      if (nestedLiveRegression.restarted) {
        daemonStartedByScript = true;
      }
      pushStep(nestedLiveRegression.step);
    } else {
      pushStep({
        id: 'matrix.live_regression_modes',
        status: 'pass',
        detail: 'skipped_by_mode',
        data: { skipped: true }
      });
    }

    if (options.runBrowserProbes) {
      await runSocialBrowserProbes(pushStep, env);
    } else {
      pushStep({ id: 'browser.social_realworld', status: 'pass', detail: 'skipped_by_mode', data: { skipped: true } });
    }

    for (const testCase of webCommunityCases(options.smoke)) {
      try {
        const res = runCli(env, testCase.args, { allowFailure: true, timeoutMs: 180000 });
        const execution = collectMacroExecution(res);
        const verdict = classifyMatrixRecords(execution.records.length, execution.failures);

        pushStep({
          id: testCase.id,
          status: res.status === 0
            ? verdict.status
            : classifyNonZeroProviderStatus(res.detail),
          data: {
            records: execution.records.length,
            failures: execution.failures.length,
            providerOrder: execution.providerOrder,
            reasonCodes: normalizedCodesFromFailures(execution.failures),
            blockerType: execution.meta?.blocker?.type ?? null
          },
          detail: res.status === 0 ? verdict.reason : res.detail
        });
      } catch (error) {
        pushStep({ id: testCase.id, status: 'fail', detail: String(error) });
      }
    }

    for (const platform of socialPlatformsForMode(options.smoke)) {
      const id = `provider.social.${platform}.search`;
      try {
        const socialCliTimeoutMs = options.strictGate
          ? 300000
          : (options.smoke ? 60000 : 180000);
        const socialMacroTimeoutMs = options.strictGate
          ? '180000'
          : (options.smoke ? '45000' : '120000');
        const primaryExpression = `@media.search("hard mode browser automation anti bot for ${platform}", "${platform}", 5)`;
        const fallbackExpression = `@media.search("browser automation ${platform}", "${platform}", 5)`;
        const primaryMacroArgs = ['macro-resolve', '--execute', '--expression', primaryExpression, '--timeout-ms', socialMacroTimeoutMs, ...SIGNED_IN_BROWSER_ARGS, '--challenge-automation-mode', 'browser_with_helper'];
        const fallbackMacroArgs = ['macro-resolve', '--execute', '--expression', fallbackExpression, '--timeout-ms', socialMacroTimeoutMs, ...SIGNED_IN_BROWSER_ARGS, '--challenge-automation-mode', 'browser_with_helper'];

        let res = runCli(env, primaryMacroArgs, {
          allowFailure: true,
          timeoutMs: socialCliTimeoutMs
        });
        let execution = collectMacroExecution(res);

        if (res.status === 0 && !execution.hasExecutionPayload) {
          const retry = runCli(env, primaryMacroArgs, {
            allowFailure: true,
            timeoutMs: socialCliTimeoutMs
          });
          const retryExecution = collectMacroExecution(retry);
          if (retry.status === 0 && retryExecution.hasExecutionPayload) {
            res = retry;
            execution = retryExecution;
          }
        }

        if (res.status === 0 && !execution.hasExecutionPayload) {
          pushStep({
            id,
            status: 'fail',
            detail: 'missing_execution_payload',
            data: {
              records: 0,
              failures: 0,
              providerOrder: [],
              reasonCodes: [],
              blockerType: null,
              usedFallbackQuery: false,
              fallbackQueryStatus: null,
              hasExecutionPayload: false,
              failureSamples: [],
              linkedinAuthWall: false,
              extensionProbeParity: false
            }
          });
          continue;
        }

        let usedFallbackQuery = false;
        let fallbackQueryStatus = null;
        let timeoutRecoveryAttempted = false;
        let timeoutRecoveryStatus = null;

        if (
          options.strictGate
          && res.status === 0
          && execution.records.length === 0
          && normalizedCodesFromFailures(execution.failures).includes('timeout')
        ) {
          const retry = runCli(
            env,
            ['macro-resolve', '--execute', '--expression', fallbackExpression, '--timeout-ms', '240000', ...SIGNED_IN_BROWSER_ARGS, '--challenge-automation-mode', 'browser_with_helper'],
            {
              allowFailure: true,
              timeoutMs: 360000
            }
          );
          timeoutRecoveryAttempted = true;
          timeoutRecoveryStatus = retry.status;
          const retryState = resolveSocialFallbackRetry(res, execution, retry);
          if (retryState.usedFallbackQuery) {
            res = retryState.result;
            execution = retryState.execution;
            usedFallbackQuery = true;
            fallbackQueryStatus = retryState.fallbackQueryStatus;
          }
        }

        if (res.status === 0 && execution.records.length === 0 && execution.failures.length === 0) {
          const retry = runCli(env, fallbackMacroArgs, {
            allowFailure: true,
            timeoutMs: socialCliTimeoutMs
          });
          const retryState = resolveSocialFallbackRetry(res, execution, retry);
          fallbackQueryStatus = retryState.fallbackQueryStatus;
          if (retryState.usedFallbackQuery) {
            res = retryState.result;
            execution = retryState.execution;
            usedFallbackQuery = true;
          }
        }

        const resolved = resolveMatrixSocialSearchStatus({
          platform,
          strictGate: options.strictGate,
          resultStatus: res.status,
          resultDetail: res.detail,
          execution,
          reportSteps: report.steps
        });

        pushStep({
          id,
          status: resolved.status,
          data: {
            records: execution.records.length,
            failures: execution.failures.length,
            providerOrder: execution.providerOrder,
            reasonCodes: resolved.reasonCodes,
            blockerType: execution.meta?.blocker?.type ?? null,
            usedFallbackQuery,
            fallbackQueryStatus,
            timeoutRecoveryAttempted,
            timeoutRecoveryStatus,
            hasExecutionPayload: execution.hasExecutionPayload,
            failureSamples: summarizeFailures(execution.failures),
            linkedinAuthWall: resolved.linkedinAuthWall,
            extensionProbeParity: resolved.extensionProbeParity,
            probeParitySource: resolved.probeParitySource,
            expectedTiktokTimeoutGate: resolved.expectedTiktokTimeoutGate
          },
          detail: resolved.detail
        });
      } catch (error) {
        pushStep({ id, status: 'fail', detail: String(error) });
      }
    }

    if (options.runSocialPostCases) {
      for (const testCase of SOCIAL_POST_CASES) {
        try {
          const res = runCli(env, ['macro-resolve', '--execute', '--expression', testCase.expression, '--timeout-ms', '120000', ...SIGNED_IN_BROWSER_ARGS, '--challenge-automation-mode', 'browser_with_helper'], {
            allowFailure: true,
            timeoutMs: 180000
          });
          const execution = collectMacroExecution(res);
          const verdict = classifyMatrixRecords(execution.records.length, execution.failures, { allowExpectedUnavailable: true });
          const reasonCodes = normalizedCodesFromFailures(execution.failures);
          const resolved = resolveMatrixSocialPostStatus({
            strictGate: options.strictGate,
            resultStatus: res.status,
            resultDetail: res.detail,
            verdict,
            reasonCodes
          });
          pushStep({
            id: testCase.id,
            status: resolved.status,
            data: {
              records: execution.records.length,
              failures: execution.failures.length,
              reasonCodes,
              failureSamples: summarizeFailures(execution.failures),
              blockerType: execution.meta?.blocker?.type ?? null,
              expectedGateVerified: resolved.expectedGateVerified,
              expectedTransportGateVerified: resolved.expectedTransportGateVerified,
              expectedPolicyGateVerified: resolved.expectedPolicyGateVerified
            },
            detail: resolved.detail
          });
        } catch (error) {
          pushStep({ id: testCase.id, status: 'fail', detail: String(error) });
        }
      }
    } else {
      for (const testCase of SOCIAL_POST_CASES) {
        pushStep(buildDefaultSkippedStep(
          testCase.id,
          'skipped_by_default',
          { includeSocialPosts: false }
        ));
      }
    }

    for (const provider of shoppingProvidersForMode(options.smoke)) {
      const id = `provider.${provider.replace('/', '.')}.search`;
      try {
        const providerTimeoutMs = MATRIX_SHOPPING_PROVIDER_TIMEOUT_MS.get(provider) ?? '45000';
        const cliTimeoutMs = options.strictGate && HIGH_FRICTION_SHOPPING_PROVIDERS.has(provider)
          ? 360000
          : 240000;
        const res = runCli(env, buildLiveShoppingRunArgs(provider, providerTimeoutMs), {
          allowFailure: true,
          timeoutMs: cliTimeoutMs
        });
        const execution = collectShoppingExecution(res);
        const verdict = classifyMatrixRecords(execution.offers.length, execution.failures);
        const reasonCodes = normalizedCodesFromFailures(execution.failures);
        const baseStatus = res.status === 0
          ? verdict.status
          : classifyNonZeroProviderStatus(res.detail);
        let resolvedStatus = baseStatus;
        let resolvedDetail = res.status === 0 ? verdict.reason : res.detail;
        const expectedHighFrictionTimeout = options.strictGate
          && HIGH_FRICTION_SHOPPING_PROVIDERS.has(provider)
          && resolvedStatus === 'env_limited'
          && (reasonCodes.includes('timeout') || isTimeoutDetail(resolvedDetail));

        pushStep({
          id,
          status: resolvedStatus,
          data: {
            offers: execution.offers.length,
            failures: execution.failures.length,
            reasonCodes,
            failureSamples: summarizeFailures(execution.failures),
            tokenRequired: reasonCodes.includes('token_required'),
            expectedHighFrictionTimeout
          },
          detail: resolvedDetail
        });
      } catch (error) {
        pushStep({ id, status: 'fail', detail: String(error) });
      }
    }

    if (options.runWorkflows) {
      try {
        const research = runCli(env, WORKFLOW_RESEARCH_PROBE_ARGS, {
          allowFailure: true,
          timeoutMs: 240000
        });
        const data = research.json?.data ?? {};
        const records = Array.isArray(data.records) ? data.records.length : 0;
        const failures = Array.isArray(data.meta?.failures) ? data.meta.failures.length : 0;
        const artifactValidation = validateSuccessfulWorkflowArtifact(data, 'research');
        const verdict = research.status === 0
          ? classifySuccessfulResearchWorkflow(records, artifactValidation)
          : { status: 'fail', detail: research.detail };
        pushStep({
          id: 'workflow.research.auto_sources',
          status: verdict.status,
          data: { records, failures, artifactPath: artifactValidation.artifactPath },
          detail: verdict.detail
        });
      } catch (error) {
        pushStep({ id: 'workflow.research.auto_sources', status: 'fail', detail: String(error) });
      }

      try {
        const product = runCli(env, ['product-video', 'run', '--product-url', 'https://www.amazon.com/dp/B0CHWRXH8B', '--include-screenshots', '--include-all-images'], {
          allowFailure: true,
          timeoutMs: 300000
        });
        const data = product.json?.data ?? {};
        const artifactValidation = validateSuccessfulWorkflowArtifact(data, 'product-video');
        const status = product.status === 0 && artifactValidation.detail
          ? 'fail'
          : classifyProductVideoAmazonStatus(product.status, product.detail, data);
        pushStep({
          id: 'workflow.product_video.amazon',
          status,
          data: {
            artifactPath: artifactValidation.artifactPath,
            provider: data.provider ?? null,
            imageCount: Array.isArray(data.images) ? data.images.length : null,
            screenshotCount: Array.isArray(data.screenshots) ? data.screenshots.length : null
          },
          detail: product.status === 0 ? artifactValidation.detail : product.detail
        });
      } catch (error) {
        pushStep({ id: 'workflow.product_video.amazon', status: 'fail', detail: String(error) });
      }

      try {
        const transcriptOut = runtime.tempRoot
          ? path.join(runtime.tempRoot, 'youtube-transcript-live-probe.json')
          : `/tmp/odb-youtube-transcript-live-probe-matrix-${Date.now()}.json`;
        const transcript = runNode(
          [...WORKFLOW_YOUTUBE_TRANSCRIPT_PROBE_ARGS, '--out', transcriptOut],
          env,
          { allowFailure: true, timeoutMs: 240000 }
        );
        const summary = transcript.json?.summary ?? null;
        const status = typeof summary?.status === 'string'
          ? summary.status
          : 'fail';
        const detail = typeof summary?.detail === 'string'
          ? summary.detail
          : (transcript.stderr || transcript.stdout || 'youtube_transcript_probe_failed');
        pushStep({
          id: YOUTUBE_TRANSCRIPT_PROBE_STEP_ID,
          status,
          detail,
          data: {
            artifactPath: transcript.json?.out ?? transcriptOut,
            ...(summary?.data ?? {})
          }
        });
      } catch (error) {
        pushStep({ id: YOUTUBE_TRANSCRIPT_PROBE_STEP_ID, status: 'fail', detail: String(error) });
      }
    } else {
      pushStep({ id: 'workflow.research.auto_sources', status: 'pass', detail: 'skipped_by_mode', data: { skipped: true } });
      pushStep({ id: 'workflow.product_video.amazon', status: 'pass', detail: 'skipped_by_mode', data: { skipped: true } });
      pushStep({ id: YOUTUBE_TRANSCRIPT_PROBE_STEP_ID, status: 'pass', detail: 'skipped_by_mode', data: { skipped: true } });
    }

    report.ok = options.strictGate
      ? report.steps.every((step) => step.status === 'pass')
      : report.steps.every((step) => step.status === 'pass' || step.status === 'env_limited');
  } catch (error) {
    report.ok = false;
    report.error = error instanceof Error ? error.message : String(error);
  } finally {
    try {
      if (daemonStartedByScript) {
        runCli(env, ['serve', '--stop'], { allowFailure: true, timeoutMs: 15000 });
      }
    } catch {
      // ignore daemon stop failures
    }

    if (runtime.tempRoot && fs.existsSync(runtime.tempRoot)) {
      try {
        fs.rmSync(runtime.tempRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
      } catch {
        // ignore cleanup races
      }
    }
    cleanupOwnedHeadlessResources();

    let lingeringTempProfiles = listTempProfileWorkers();
    if (lingeringTempProfiles.length > 0) {
      try {
        runCli(env, ['serve', '--stop'], { allowFailure: true, timeoutMs: 15000 });
        startDaemon(env);
        await waitForDaemonReady(env, 30000);
      } catch {
        // ignore daemon recycle failures during cleanup fallback
      }
      cleanupOwnedHeadlessResources(true);
      lingeringTempProfiles = listTempProfileWorkers();
    }
    pushStep({
      id: 'infra.headless_worker_cleanup',
      status: lingeringTempProfiles.length === 0 ? 'pass' : 'fail',
      detail: lingeringTempProfiles.length === 0
        ? null
        : `Lingering temp-profile workers detected: ${lingeringTempProfiles.length}`,
      data: {
        lingeringCount: lingeringTempProfiles.length,
        lingeringPids: lingeringTempProfiles.map((entry) => entry.pid)
      }
    });

    finalizeReport(report);
    fs.writeFileSync(options.out, JSON.stringify(report, null, 2));
    console.log(options.out);
    console.log(JSON.stringify({ ok: report.ok, counts: report.counts, out: options.out, mode: options.mode }, null, 2));
    if (!report.ok) process.exitCode = 1;
  }
}

if (import.meta.url === `file://${process.argv[1]}`) {
  main()
    .then(() => {
      flushAndExit();
    })
    .catch((error) => {
      cleanupOwnedHeadlessResources();
      console.error(error instanceof Error ? error.message : String(error));
      flushAndExit(process, 1);
    });
}
