import { projectRoot, dirSize, exists, formatBytes } from '../core/fsx.js';
import { flag } from '../cli/args.js';
import { printJson } from '../cli/output.js';
import { getCodexInfo } from '../core/codex-adapter.js';
import { rustInfo } from '../core/rust-accelerator.js';
import { codexAppIntegrationStatus } from '../core/codex-app.js';
import { codexLbMetrics, readCodexLbCircuit } from '../core/codex-lb-circuit.js';
import { ensureGlobalCodexSkillsDuringInstall, ensureGlobalCodexFastModeDuringInstall } from '../cli/install-helpers.js';
import { normalizeInstallScope } from '../core/init.js';
import { inspectCodexConfigReadability } from '../core/codex/codex-config-readability.js';
import { repairCodexConfigEperm } from '../core/codex/codex-config-eperm-repair.js';
import { writeDoctorReadinessMatrix } from '../core/doctor/doctor-readiness-matrix.js';
import { runCodexDoctorBridge, compareCodexDoctorBridge } from '../core/doctor/codex-doctor-bridge.js';
import { cleanDuplicateGlobalSksInstalls } from '../core/doctor/global-sks-install-cleanup.js';
import { checkZellijCapability } from '../core/zellij/zellij-capability.js';
import { inventoryCodexPermissionProfiles } from '../core/codex/codex-permission-profiles.js';
import { appendMigrationEvents, hashConfigText } from '../core/migration/migration-transaction-journal.js';
import { repairCodexAppFastUi } from '../core/codex-app/codex-app-fast-ui-repair.js';
import { resolveProviderContext } from '../core/provider/provider-context.js';
import { readLocalModelConfig } from '../core/agents/ollama-worker-config.js';
import { repairAgentRoleConfigs } from '../core/agents/agent-role-config.js';
import { writeCodex0138CapabilityArtifacts } from '../core/codex-control/codex-0138-capability.js';
import { runCodex0138Doctor } from '../core/doctor/codex-0138-doctor.js';
import { writeCodexPluginInventoryArtifacts, pluginAppTemplatePolicy } from '../core/codex-plugins/codex-plugin-json.js';
import { writeMcpPluginInventoryArtifacts } from '../core/mcp/mcp-plugin-inventory.js';
import { runDoctorZellijRepair, doctorZellijRepairConsoleLine } from '../core/doctor/doctor-zellij-repair.js';
import { buildCodexAppHarnessMatrix } from '../core/codex-app/codex-app-harness-matrix.js';
import { buildCodexNativeFeatureMatrix } from '../core/codex-native/codex-native-feature-broker.js';
export async function run(_command, args = []) {
    const doctorFix = flag(args, '--fix');
    let setupRepair = null;
    const sksUpdate = doctorFix
        ? {
            schema: 'sks.update-now.v1',
            ok: true,
            status: 'skipped',
            reason: 'manual_update_commands_only'
        }
        : null;
    let migrationPreFix = null;
    if (doctorFix) {
        // Snapshot config content before ANY mutation so the migration journal can
        // record real before/after hashes for the whole --fix transaction.
        migrationPreFix = await captureCodexConfigSnapshot();
        const { setupCommand } = await import('../core/commands/basic-cli.js');
        const installScope = installScopeFromArgs(args);
        // Back up the existing managed project config before --force regeneration so a
        // hand-edited .codex/config.toml is always recoverable (mirrors the splitter/structure
        // repair backup contract).
        const preFixBackup = await backupProjectConfigBeforeFix();
        const setupArgs = ['--force', '--install-scope', installScope];
        if (flag(args, '--local-only'))
            setupArgs.push('--local-only');
        await setupCommand(setupArgs);
        setupRepair = {
            install_scope: installScope,
            config_backup_path: preFixBackup,
            global_skills: installScope === 'global' && !flag(args, '--local-only')
                ? await ensureGlobalCodexSkillsDuringInstall({ force: true })
                : { status: 'skipped', reason: 'project or local-only repair' },
            // Re-seed the Codex App Fast-mode UI table ([user.fast_mode] visible/enabled/
            // default_profile) in the global ~/.codex/config.toml so existing installs whose
            // config predates the Fast-mode UI keys get the App speed selector back. Safe:
            // backs up + parse-validates before writing, no-op when already present.
            codex_app_fast_mode: flag(args, '--local-only')
                ? { status: 'skipped', reason: 'local-only repair' }
                : await ensureGlobalCodexFastModeDuringInstall().catch((err) => ({ status: 'failed', error: err?.message || String(err) }))
        };
    }
    const root = await projectRoot();
    const codexBin = readOption(args, '--codex-bin', process.env.SKS_DOCTOR_CODEX_BIN || '');
    const configProbeOpts = {
        codexProbe: flag(args, '--fix') || flag(args, '--actual-codex') || Boolean(codexBin),
        actualCodex: flag(args, '--fix') || flag(args, '--actual-codex') || Boolean(codexBin),
        requireActualCodex: flag(args, '--fix') || flag(args, '--require-actual-codex'),
        codexBin: codexBin || undefined
    };
    const codexDoctorBefore = flag(args, '--fix') ? await runCodexDoctorBridge({ codexBin: codexBin || null, cwd: root, required: flag(args, '--require-actual-codex') }).catch(() => null) : null;
    const configRepair = flag(args, '--fix') ? await repairCodexConfigEperm(root, { fix: true, ...configProbeOpts }) : null;
    const migrationJournal = flag(args, '--fix')
        ? await writeFixMigrationJournal(root, migrationPreFix, configRepair, setupRepair).catch(() => null)
        : null;
    const codexConfig = configRepair?.after || await inspectCodexConfigReadability(root, configProbeOpts);
    const codexDoctor = await runCodexDoctorBridge({ codexBin: codexBin || null, cwd: root, required: flag(args, '--require-actual-codex') });
    const codexDoctorDiff = compareCodexDoctorBridge(codexDoctorBefore, codexDoctor);
    const codex = codexBin
        ? { bin: codexBin, version: 'fixture-or-explicit', available: true }
        : await getCodexInfo().catch(() => ({ bin: null, version: null, available: false }));
    const rust = await rustInfo().catch((err) => ({
        available: false,
        mode: 'js_fallback',
        status: 'error',
        version: null,
        error: err.message
    }));
    const codexApp = await codexAppIntegrationStatus({ codex }).catch((err) => ({ ok: false, error: err.message }));
    const codexLb = codexLbMetrics(await readCodexLbCircuit(root).catch(() => ({})));
    const providerContext = await resolveProviderContext({ root, route: '$Doctor', serviceTier: process.env.SKS_SERVICE_TIER || 'fast' }).catch((err) => ({
        schema: 'sks.provider-context.v1',
        generated_at: new Date().toISOString(),
        provider: 'unknown',
        auth_mode: 'unknown',
        route: '$Doctor',
        service_tier: 'unknown',
        source: 'unknown',
        confidence: 'low',
        conflict: false,
        warnings: [err?.message || String(err)],
        signals: {
            openai_api_key_present: false,
            codex_lb_key_present: false,
            codex_lb_explicit: false,
            codex_app_auth_present: false,
            model_provider: null
        }
    }));
    const explicitCodexAppUiRepair = flag(args, '--repair-codex-app-ui') || flag(args, '--yes');
    const codexAppUiPlan = await repairCodexAppFastUi(root, {
        apply: false,
        reportPath: `${root}/.sneakoscope/reports/codex-app-fast-ui-repair-plan.json`
    }).catch((err) => ({
        schema: 'sks.codex-app-fast-ui-repair.v1',
        ok: false,
        apply: false,
        safe_auto_apply: false,
        requires_confirmation: true,
        fast_selector: 'manual_action_required',
        provider_selector: 'ok',
        host_owned_config: 'diagnostic_failed',
        next_action: 'Review Codex App UI config manually.',
        actions: [],
        blockers: [err?.message || String(err)]
    }));
    const shouldApplyCodexAppUiRepair = doctorFix && (explicitCodexAppUiRepair ||
        codexAppUiPlan.safe_auto_apply === true);
    const codexAppUi = shouldApplyCodexAppUiRepair
        ? await repairCodexAppFastUi(root, {
            apply: true,
            force: explicitCodexAppUiRepair,
            reportPath: `${root}/.sneakoscope/reports/codex-app-fast-ui-repair.json`
        }).catch((err) => ({
            schema: 'sks.codex-app-fast-ui-repair.v1',
            ok: false,
            apply: true,
            safe_auto_apply: false,
            requires_confirmation: true,
            fast_selector: 'manual_action_required',
            provider_selector: 'ok',
            host_owned_config: 'diagnostic_failed',
            next_action: 'Review Codex App UI config manually.',
            actions: [],
            blockers: [err?.message || String(err)]
        }))
        : codexAppUiPlan;
    const zellijRepair = await runDoctorZellijRepair({ root, args, doctorFix }).catch((err) => ({
        schema: 'sks.zellij-self-heal.v1',
        ok: false,
        requested_by: 'doctor --fix',
        fix_requested: doctorFix,
        auto_approved: flag(args, '--yes') || flag(args, '-y'),
        install_homebrew_allowed: false,
        before: { status: 'unknown', version: null, bin: null },
        latest_version: null,
        strategy: 'failed',
        command: 'sks doctor --fix --yes',
        after: { status: 'unknown', version: null, bin: null },
        mutation_guard_artifact: null,
        homebrew: { present: false, bin: null, install_attempted: false, install_allowed: false },
        blockers: [err?.message || String(err)],
        warnings: []
    }));
    const zellij = await checkZellijCapability({ root, require: process.env.SKS_REQUIRE_ZELLIJ === '1' });
    const localModel = await readLocalModelConfig().catch(() => null);
    const permissionProfiles = await inventoryCodexPermissionProfiles(root, { writeReport: true });
    const agentRoleConfigRepair = await repairAgentRoleConfigs({
        root,
        apply: doctorFix,
        reportPath: `${root}/.sneakoscope/reports/agent-role-config-repair.json`
    }).catch((err) => ({
        schema: 'sks.agent-role-config-repair.v1',
        ok: false,
        apply: doctorFix,
        missing: [],
        existing: [],
        created: [],
        warnings_suppressed: false,
        blockers: [err?.message || String(err)]
    }));
    const globalSksInstallCleanup = flag(args, '--fix') && !flag(args, '--local-only')
        ? await cleanDuplicateGlobalSksInstalls({ root, fix: true }).catch((err) => ({ schema: 'sks.global-sks-install-cleanup.v1', ok: false, fix: true, error: err?.message || String(err), blockers: ['global_sks_install_cleanup_exception'] }))
        : null;
    const { detectImagegenCapability } = await import('../core/imagegen/imagegen-capability.js');
    const imagegen = await detectImagegenCapability({ codexBin: codexBin || undefined }).catch((err) => ({ ok: false, error: err.message, auth_readiness: null }));
    const codex0138Capability = await writeCodex0138CapabilityArtifacts(root, { codexBin: codexBin || null }).catch((err) => ({ error: err?.message || String(err), report: null }));
    const codex0138Doctor = await runCodex0138Doctor(root, { fix: doctorFix }).catch((err) => ({ schema: 'sks.codex-0138-doctor.v1', ok: false, error: err?.message || String(err), blockers: ['codex_0138_doctor_exception'], warnings: [] }));
    const pluginInventory = await writeCodexPluginInventoryArtifacts(root).catch((err) => ({ error: err?.message || String(err), report: null, artifact: null }));
    const pluginPolicy = pluginInventory?.report ? pluginAppTemplatePolicy(pluginInventory.report) : null;
    const mcpPluginInventory = pluginInventory?.report
        ? await writeMcpPluginInventoryArtifacts(root, { inventory: pluginInventory.report }).catch((err) => ({ error: err?.message || String(err), candidates: null }))
        : null;
    const codexAppHarnessMatrix = await buildCodexAppHarnessMatrix({ root, applyRepairs: doctorFix }).catch((err) => ({
        schema: 'sks.codex-app-harness-matrix.v1',
        ok: false,
        codex_cli: { available: false, version: null },
        app_features: {},
        sks_integrations: {},
        blockers: [err?.message || String(err)],
        warnings: []
    }));
    const codexNativeFeatureMatrix = await buildCodexNativeFeatureMatrix({ root, applyRepairs: doctorFix }).catch((err) => ({
        schema: 'sks.codex-native-feature-matrix.v1',
        ok: false,
        codex_cli: { available: Boolean(codex.bin), version: codex.version || null, bin: codex.bin || null },
        features: {},
        invocation_defaults: {
            loop_worker_role_strategy: 'message-role',
            qa_visual_review_strategy: 'blocked',
            research_source_strategy: 'local-files',
            image_followup_strategy: 'blocked',
            hook_evidence_policy: 'unknown-do-not-count',
            skill_bridge_strategy: 'cli-only'
        },
        blockers: [err?.message || String(err)],
        warnings: []
    }));
    const pkgBytes = await dirSize(root).catch(() => 0);
    const ready = await writeDoctorReadinessMatrix(root, {
        codex,
        codex_config: codexConfig,
        codex_app: codexApp,
        codex_lb: codexLb,
        codex_doctor: codexDoctor,
        require_codex_doctor: flag(args, '--fix') || flag(args, '--require-actual-codex'),
        zellij,
        local_model: localModel,
        agent_role_config: agentRoleConfigRepair,
        repair: configRepair,
        codex_app_ui: codexAppUi,
        codex_0138_doctor: codex0138Doctor,
        codex_plugin_inventory: pluginInventory?.report || null,
        codex_plugin_app_template_policy: pluginPolicy,
        codex_app_harness_matrix: codexAppHarnessMatrix,
        require_codex_cli_config_load: flag(args, '--fix') || flag(args, '--require-actual-codex'),
        operator_actions: [
            ...(codexConfig.operator_actions || []),
            ...(configRepair?.operator_actions || []),
            ...(zellijRepair && !zellijRepair.ok && zellijRepair.command ? [`Run: ${zellijRepair.command}`] : []),
            ...(pluginPolicy?.doctor_warnings || [])
        ]
    });
    const zellijReadiness = buildZellijReadiness(root, zellij, ready);
    const runtimeReadiness = buildRuntimeReadiness(zellijReadiness, codexNativeFeatureMatrix);
    const result = {
        schema: 'sks.doctor-status.v1',
        ok: ready.ready && (!sksUpdate || sksUpdate.ok !== false),
        root,
        node: { ok: Number(process.versions.node.split('.')[0]) >= 20, version: process.version },
        codex,
        codex_config: codexConfig,
        rust,
        codex_app: codexApp,
        codex_app_ui: codexAppUi,
        provider_context: providerContext,
        codex_lb: codexLb,
        codex_doctor: codexDoctor,
        codex_doctor_diff: codexDoctorDiff,
        zellij,
        zellij_repair: zellijRepair,
        local_model: localModel,
        agent_role_config: agentRoleConfigRepair,
        zellij_readiness: zellijReadiness,
        codex_permission_profiles: permissionProfiles,
        imagegen: {
            ok: imagegen.auth_readiness?.available_paths?.length > 0,
            auth_readiness: imagegen.auth_readiness || null,
            codex_app_builtin_available: imagegen.codex_app?.available === true
        },
        codex_0138: {
            capability: codex0138Capability.report || null,
            doctor: codex0138Doctor,
            plugins: pluginInventory?.report || null,
            plugin_app_template_policy: pluginPolicy,
            mcp_plugin_inventory: mcpPluginInventory?.candidates || null
        },
        codex_app_harness_matrix: codexAppHarnessMatrix,
        codex_native_feature_matrix: codexNativeFeatureMatrix,
        runtime_readiness: runtimeReadiness,
        ready,
        sneakoscope: { ok: await exists(`${root}/.sneakoscope`) },
        package: { bytes: pkgBytes, human: formatBytes(pkgBytes) },
        repair: { sks_update: sksUpdate, setup: setupRepair, codex_config: configRepair, migration_journal: migrationJournal, global_sks_installs: globalSksInstallCleanup, agent_role_config: agentRoleConfigRepair, zellij: zellijRepair }
    };
    if (flag(args, '--json')) {
        printJson(result);
        if (!result.ok)
            process.exitCode = 1;
        return;
    }
    console.log('SKS Doctor');
    console.log(`Root:      ${root}`);
    console.log(`Node:      ${result.node.ok ? 'ok' : 'fail'} ${result.node.version}`);
    console.log(`Codex:     ${codex.bin ? 'ok' : 'missing'} ${codex.version || ''}`);
    const actual = (codexConfig.checks || []).find((check) => check.name === 'actual_codex_cli_config_load');
    console.log('Project config:');
    console.log(`  node read:       ${ready.codex_config_readable_by_node ? 'ok' : 'failed'}`);
    console.log(`  codex cli read:  ${ready.codex_config_readable_by_codex_cli ? 'ok' : (actual?.status || 'failed')}`);
    console.log(`  removed runtime: tmux`);
    console.log('Zellij:');
    console.log(`  binary:      ${zellijReadiness.binary} ${zellijReadiness.version || ''} ${zellijReadiness.status === 'ok' ? 'ok' : zellijReadiness.status}`);
    console.log(`  required_for: ${zellijReadiness.required_for.join(', ')}`);
    console.log(`  layout:      ${zellijReadiness.layout_proof}`);
    console.log(`  pane proof:  ${zellijReadiness.pane_proof}`);
    console.log(`  screen proof:${zellijReadiness.screen_proof}`);
    console.log(`  tmux:        ${zellijReadiness.tmux_removed_runtime ? 'removed_runtime' : 'present'}`);
    const zellijRepairLine = doctorZellijRepairConsoleLine(zellijRepair);
    if (zellijRepairLine)
        console.log(zellijRepairLine);
    console.log(`  codex doctor:    ${codexDoctor.available ? (codexDoctor.exit_code === 0 ? 'ok' : 'warning') : 'unavailable'}`);
    console.log(`Rust acc.: ${rust.mode || (rust.available ? 'rust_accelerated' : 'js_fallback')} ${rust.version || rust.status || ''}`);
    console.log(`Codex App: ${ready.codex_app_ready ? 'ok' : 'optional_missing'}`);
    console.log('SKS Runtime Readiness:');
    console.log(`  Zellij: ${runtimeReadiness.zellij}`);
    console.log(`  Codex Native: ${runtimeReadiness.codex_native}`);
    console.log(`  Loop Mesh: ${runtimeReadiness.loop_mesh}`);
    console.log(`  QA Visual: ${runtimeReadiness.qa_visual}`);
    console.log(`  Research Sources: ${runtimeReadiness.research_sources}`);
    for (const action of runtimeReadiness.repair_actions)
        console.log(`  Repair: ${action}`);
    console.log('Codex App Harness:');
    console.log(`  plugins: ${codexAppHarnessMatrix.app_features?.plugin_json ? 'ok' : 'degraded'}`);
    console.log(`  hook approval: ${codexAppHarnessMatrix.app_features?.hook_approval_state_detectable ? 'ok' : 'unknown'}`);
    console.log(`  skills: ${codexAppHarnessMatrix.sks_integrations?.dollar_skills_synced ? 'ok' : 'degraded'}`);
    console.log(`  agent roles: ${codexAppHarnessMatrix.sks_integrations?.agent_roles_synced ? 'ok' : 'degraded'}`);
    console.log(`  native agent_type: ${codexAppHarnessMatrix.app_features?.agent_type_supported ? 'ok' : 'fallback message-role'}`);
    console.log(`  init-deep memory: ${codexAppHarnessMatrix.sks_integrations?.init_deep_available ? 'available' : 'missing'}`);
    console.log(`  loop mesh app profile: ${codexAppHarnessMatrix.sks_integrations?.loop_mesh_app_profile_available ? 'available' : 'missing'}`);
    console.log('Codex App UI:');
    console.log(`  fast selector: ${codexAppUi.fast_selector || 'unknown'}`);
    console.log(`  provider selector: ${codexAppUi.provider_selector || 'unknown'}`);
    console.log(`  host-owned config: ${codexAppUi.host_owned_config || 'unknown'}`);
    if (Array.isArray(codexAppUi.actions) && codexAppUi.actions.some((action) => action.changed)) {
        console.log('  repaired files:');
        for (const action of codexAppUi.actions.filter((entry) => entry.changed))
            console.log(`    - ${action.file}${action.backup_path ? ` (backup ${action.backup_path})` : ''}`);
    }
    if (codexAppUi.next_action)
        console.log(`  next action: ${codexAppUi.next_action}`);
    console.log(`Provider: ${providerContext.provider || 'unknown'} ${providerContext.service_tier || ''} (${providerContext.source || 'unknown'}, ${providerContext.confidence || 'low'})`);
    const imagegenReady = imagegen.auth_readiness;
    if (imagegenReady) {
        const paths = imagegenReady.available_paths?.length ? imagegenReady.available_paths.join(', ') : 'none';
        console.log(`Image Gen: auth=${imagegenReady.auth_mode} | headless_auto=${imagegenReady.headless_auto_available ? 'available' : 'unavailable'} | paths: ${paths}`);
        if (!imagegenReady.headless_auto_available) {
            for (const action of imagegenReady.next_actions || [])
                console.log(`  - ${action}`);
        }
    }
    const codex0138 = codex0138Capability.report || {};
    console.log('Codex 0.138 features:');
    console.log(`  /app handoff: ${codex0138.supports_app_handoff ? 'ok' : 'unavailable'}`);
    console.log(`  plugin JSON: ${codex0138.supports_plugin_json ? 'ok' : 'unavailable'}`);
    console.log(`  image path exposure: ${codex0138.supports_image_path_exposure ? 'ok' : 'unavailable'}`);
    console.log(`  OAuth MCP pre-refresh: ${codex0138.supports_oauth_mcp_prerefresh ? 'ok' : 'unavailable'}`);
    const plugins = pluginInventory?.report?.plugins || [];
    const remoteMcpCount = plugins.flatMap((plugin) => plugin.remote_mcp_servers || []).length;
    const unavailableTemplates = pluginPolicy?.unavailable_app_templates?.length || 0;
    console.log(`Codex plugins: ${pluginInventory?.report ? 'ok' : 'warning'}`);
    console.log(`  Remote MCP servers: ${remoteMcpCount} candidates`);
    console.log(`  Unavailable app templates: ${unavailableTemplates}`);
    for (const warning of pluginPolicy?.doctor_warnings || [])
        console.log(`  warning: ${warning}`);
    if (codex0138Doctor?.fixed?.length)
        console.log(`  doctor --fix repaired: ${codex0138Doctor.fixed.join(', ')}`);
    console.log(`codex-lb:  ${codexLb.ok ? 'ok' : `warning ${codexLb.circuit?.state || 'unknown'}`}`);
    if (localModel) {
        console.log('Local LLM:');
        console.log(`  enabled: ${localModel.enabled ? 'yes' : 'no'}`);
        console.log(`  status: ${localModel.status}`);
        console.log(`  provider: ${localModel.provider}`);
        console.log(`  model: ${localModel.model}`);
        console.log(`  endpoint: ${localModel.base_url}`);
        console.log(`  last smoke: ${localModel.last_smoke?.ok ? `ok ${localModel.last_smoke.latency_ms || 0}ms ${localModel.last_smoke.tokens_per_second || 0} tok/s` : 'missing'}`);
        console.log('  final arbiter: GPT required');
    }
    console.log(`Permissions: config profile and permission profile are tracked separately (${permissionProfiles.codex_config_profile_field}, ${permissionProfiles.codex_permission_profile_field})`);
    console.log('Ready:');
    console.log(`  cli_ready: ${ready.cli_ready ? 'yes' : 'no'}`);
    console.log(`  mad_ready: ${ready.mad_ready ? 'yes' : 'no'}`);
    console.log(`  ready:     ${ready.ready ? 'yes' : 'no'}`);
    if (!ready.ready) {
        console.log('Primary blocker:');
        console.log(`  ${ready.primary_blocker || 'unknown'}`);
    }
    if (configRepair?.repair_actions?.length) {
        console.log('What I fixed:');
        for (const action of configRepair.repair_actions)
            console.log(`  - ${action.name}: ${action.ok ? 'ok' : 'failed'}`);
    }
    if (migrationJournal?.journal_path) {
        console.log(`Migration journal: ${migrationJournal.journal_path} (${migrationJournal.event_count} events, ${migrationJournal.mutations_without_rollback} without rollback)`);
    }
    if (sksUpdate) {
        console.log(`SKS update: ${sksUpdate.status}${sksUpdate.latest ? ` latest ${sksUpdate.latest}` : ''}${sksUpdate.error ? ` (${sksUpdate.error})` : ''}`);
    }
    if (globalSksInstallCleanup) {
        console.log(`Global SKS installs: kept ${globalSksInstallCleanup.kept?.length ?? 0}, removed ${globalSksInstallCleanup.removed?.filter((entry) => entry.ok).length ?? 0}, source repo exempt ${globalSksInstallCleanup.candidates?.filter((entry) => entry.source_repo_exempt).length ?? 0}`);
    }
    if (!ready.ready && ready.next_actions?.length) {
        console.log('What still needs you:');
        for (const action of ready.next_actions)
            console.log(`  - ${action}`);
    }
    if (!result.ok)
        process.exitCode = 1;
}
function buildRuntimeReadiness(zellijReadiness, matrix) {
    const defaults = matrix?.invocation_defaults || {};
    const hookPolicy = defaults.hook_evidence_policy || 'unknown-do-not-count';
    const agentStrategy = defaults.loop_worker_role_strategy || 'message-role';
    const zellijStatus = zellijReadiness?.status === 'ok'
        ? 'ok'
        : zellijReadiness?.cli_ready ? 'headless_available' : 'repair_required';
    const codexNative = matrix?.ok === true
        ? 'ok'
        : matrix?.codex_cli?.available ? 'degraded' : 'blocked';
    const repairActions = [];
    if (zellijStatus === 'repair_required')
        repairActions.push('sks doctor --fix --yes');
    if (codexNative !== 'ok')
        repairActions.push('sks doctor --fix --repair-codex-native --yes');
    if (matrix?.features?.project_memory?.ok !== true)
        repairActions.push('sks codex-native init-deep --apply --directory-local');
    if (hookPolicy !== 'approved-only')
        repairActions.push('hook-derived evidence will not count until Codex hook approval is approved');
    return {
        schema: 'sks.runtime-readiness-story.v1',
        zellij: zellijStatus,
        codex_native: codexNative,
        loop_mesh: agentStrategy === 'agent_type' ? 'ok' : 'fallback',
        qa_visual: defaults.qa_visual_review_strategy || 'blocked',
        research_sources: defaults.research_source_strategy || 'local-files',
        hook_evidence_policy: hookPolicy,
        agent_role_strategy: agentStrategy,
        notes: [
            ...(zellijStatus === 'headless_available' ? ['MAD can run with --headless; live panes require repair'] : []),
            ...(hookPolicy !== 'approved-only' ? ['hook-derived evidence will not count'] : []),
            ...(agentStrategy !== 'agent_type' ? ['message-role fallback active'] : [])
        ],
        repair_actions: repairActions
    };
}
// Assemble the explicit Zellij readiness block for `doctor --json` from the
// capability probe + readiness matrix. Proof statuses are availability-derived:
// `verified` is reserved for a real environment run (SKS_REQUIRE_ZELLIJ=1 gates);
// here they report `optional` when the binary is usable and `unavailable` when
// Zellij is missing/too old. Zellij missing keeps mad_ready=false while cli_ready
// can remain true (the matrix already enforces this).
function buildZellijReadiness(root, zellij, ready) {
    const status = String(zellij?.status || 'missing');
    const usable = status === 'ok';
    const proofStatus = usable ? 'optional' : 'unavailable';
    const readiness = {
        schema: 'sks.zellij-readiness.v1',
        binary: zellij?.bin || 'zellij',
        status,
        min_version: zellij?.min_version || '0.41.0',
        version: zellij?.version || null,
        required_for: zellij?.required_for || ['sks --mad', 'interactive lane UI'],
        layout_proof: proofStatus,
        pane_proof: proofStatus,
        screen_proof: proofStatus,
        tmux_removed_runtime: true,
        mad_ready: ready?.mad_ready === true,
        cli_ready: ready?.cli_ready === true,
        ready_for_interactive_runtime: ready?.codex_config_readable_in_zellij_context === true
    };
    return readiness;
}
async function codexHomeConfigPath() {
    const path = await import('node:path');
    const os = await import('node:os');
    const home = process.env.CODEX_HOME || path.join(process.env.HOME || os.homedir(), '.codex');
    return path.join(home, 'config.toml');
}
async function captureCodexConfigSnapshot() {
    const fsp = await import('node:fs/promises');
    const path = await import('node:path');
    const read = async (p) => {
        if (!p)
            return null;
        try {
            return await fsp.readFile(p, 'utf8');
        }
        catch {
            return null;
        }
    };
    const root = await projectRoot();
    const projectPath = root ? path.join(root, '.codex', 'config.toml') : null;
    const homePath = await codexHomeConfigPath();
    return {
        project_path: projectPath,
        project_text: await read(projectPath),
        home_path: homePath,
        home_text: await read(homePath)
    };
}
// Build a migration journal for the --fix transaction with real before/after
// content hashes and the backup paths produced by setup/structure/split repair.
async function writeFixMigrationJournal(root, preFix, configRepair, setupRepair) {
    if (!preFix)
        return null;
    const fsp = await import('node:fs/promises');
    const read = async (p) => {
        if (!p)
            return null;
        try {
            return await fsp.readFile(p, 'utf8');
        }
        catch {
            return null;
        }
    };
    const projectAfter = await read(preFix.project_path);
    const homeAfter = await read(preFix.home_path);
    const structureRepairs = Array.isArray(configRepair?.structure_repairs) ? configRepair.structure_repairs : [];
    const projectStructure = structureRepairs.find((repair) => repair.scope === 'project');
    const homeStructure = structureRepairs.find((repair) => repair.scope === 'codex_home');
    const events = [
        {
            step: 'doctor_fix_project_config',
            target: preFix.project_path || '.codex/config.toml',
            beforeHash: preFix.project_text != null ? hashConfigText(preFix.project_text) : null,
            afterHash: projectAfter != null ? hashConfigText(projectAfter) : null,
            backupPath: setupRepair?.config_backup_path || projectStructure?.backup_path || configRepair?.policy?.backup_path || null
        },
        {
            step: 'doctor_fix_codex_home_config',
            target: preFix.home_path || '~/.codex/config.toml',
            beforeHash: preFix.home_text != null ? hashConfigText(preFix.home_text) : null,
            afterHash: homeAfter != null ? hashConfigText(homeAfter) : null,
            backupPath: homeStructure?.backup_path || null
        }
    ].filter((event) => event.beforeHash != null || event.afterHash != null);
    if (!events.length)
        return null;
    return appendMigrationEvents(root, events);
}
async function backupProjectConfigBeforeFix() {
    try {
        const fsp = await import('node:fs/promises');
        const path = await import('node:path');
        const root = await projectRoot();
        if (!root)
            return null;
        const configPath = path.join(root, '.codex', 'config.toml');
        if (!(await exists(configPath)))
            return null;
        const text = await fsp.readFile(configPath, 'utf8');
        const backupPath = `${configPath}.doctor-pre-fix-${Date.now().toString(36)}.bak`;
        await fsp.writeFile(backupPath, text);
        return backupPath;
    }
    catch {
        return null;
    }
}
function installScopeFromArgs(args = []) {
    if (flag(args, '--project'))
        return 'project';
    if (flag(args, '--global'))
        return 'global';
    const index = args.indexOf('--install-scope');
    return normalizeInstallScope(index >= 0 && args[index + 1] ? args[index + 1] : 'global');
}
function readOption(args = [], name, fallback = null) {
    const index = args.indexOf(name);
    return index >= 0 && args[index + 1] ? args[index + 1] : fallback;
}
//# sourceMappingURL=doctor.js.map