"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.controlPlaneConfigSchema = exports.DEFAULT_CONFIG = exports.foreignIssueApprovalScopeSchema = exports.FOLLOWUP_CHILD_ISSUE_POLICIES = exports.AI_WORKFLOW_OPTION_AUTOFILL_VALUES = exports.PARALLELISM_MODE_VALUES = exports.WORKSPACE_SETUP_FREQUENCY_VALUES = exports.GIT_HOOKS_MODE_VALUES = exports.DEPENDENCIES_STRATEGY_VALUES = exports.REQUIREMENTS_SETUP_APPROVAL_VALUES = exports.WORKFLOW_START_APPROVAL_MODE_VALUES = exports.WORKFLOW_START_APPROVAL_SCOPE_VALUES = exports.PULL_REQUEST_REVIEW_POLICY_VALUES = exports.PULL_REQUEST_MERGE_POLICY_VALUES = exports.ISSUE_COMPLETION_TARGET_VALUES = exports.workflowTemplateIdSchema = exports.customWorkerIdSchema = exports.workerNameSchema = exports.BUILT_IN_WORKER_NAMES = void 0;
exports.createCustomWorkerIdSchema = createCustomWorkerIdSchema;
exports.resolveFollowupDefaultWorkflowSelector = resolveFollowupDefaultWorkflowSelector;
exports.resolveWorkflowTemplateDefaultsWithFollowup = resolveWorkflowTemplateDefaultsWithFollowup;
exports.loadConfig = loadConfig;
exports.writeConfig = writeConfig;
exports.getConfigPath = getConfigPath;
exports.formatConfigFile = formatConfigFile;
exports.cloneWorkersConfig = cloneWorkersConfig;
exports.cloneCustomWorkersConfig = cloneCustomWorkersConfig;
exports.isBuiltInWorkerName = isBuiltInWorkerName;
exports.isCustomWorkerName = isCustomWorkerName;
exports.resolveConfiguredWorkerNames = resolveConfiguredWorkerNames;
exports.resolveCustomWorkerConfig = resolveCustomWorkerConfig;
exports.hasCustomWorkerConfig = hasCustomWorkerConfig;
exports.collectCustomWorkerEnvTemplateNames = collectCustomWorkerEnvTemplateNames;
exports.getConfiguredBuiltInWorkers = getConfiguredBuiltInWorkers;
exports.getDefaultWorkers = getDefaultWorkers;
exports.getThinkingWorkers = getThinkingWorkers;
exports.getConfiguredWorkerProviders = getConfiguredWorkerProviders;
exports.resolveWorkersForPurpose = resolveWorkersForPurpose;
exports.resolveIssueCompletion = resolveIssueCompletion;
exports.isIssueCompletionAutoMergeEnabled = isIssueCompletionAutoMergeEnabled;
exports.resolveWorkflowStartApprovalMode = resolveWorkflowStartApprovalMode;
exports.resolveWorkflowStartApprovalModeForPlanningIntent = resolveWorkflowStartApprovalModeForPlanningIntent;
exports.resolveIssueEffectiveConfig = resolveIssueEffectiveConfig;
exports.resolveIssueEffectiveConfigForWorkflowState = resolveIssueEffectiveConfigForWorkflowState;
exports.resolveIssueEffectiveConfigFromComments = resolveIssueEffectiveConfigFromComments;
// biome-ignore-all lint/nursery/noExcessiveLinesPerFile: control-plane config intentionally keeps the schema, defaults, and serializers together.
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const zod_1 = require("zod");
const definitions_1 = require("../auth-profiles/definitions");
const canonical_workflow_state_1 = require("../comments/canonical-workflow-state");
const branding_1 = require("../core/branding");
const paths_1 = require("../core/paths");
const structured_clone_1 = require("../core/structured-clone");
const tracked_project_1 = require("../core/tracked-project");
const config_1 = require("../event-hooks/config");
const remote_name_1 = require("../git/remote-name");
const catalog_1 = require("../i18n/catalog");
const config_2 = require("../i18n/config");
const display_time_1 = require("../i18n/display-time");
const comment_reactions_1 = require("../platform/ticket-tracker/comment-reactions");
const workflow_labels_1 = require("../platform/ticket-tracker/workflow-labels");
const paths_2 = require("../system-prompts/paths");
const types_1 = require("../system-prompts/types");
const command_apply_1 = require("../workflows/command-apply");
const config_override_validation_1 = require("../workflows/config-override-validation");
const types_2 = require("../workflows/types");
const workflow_command_state_1 = require("../workflows/workflow-command-state");
const env_template_1 = require("./env-template");
const issue_completion_1 = require("./issue-completion");
exports.BUILT_IN_WORKER_NAMES = definitions_1.AUTH_PROFILE_PROVIDER_VALUES;
const CUSTOM_WORKER_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
exports.workerNameSchema = createConfiguredEntityIdSchema();
function createCustomWorkerIdSchema(locale = catalog_1.DEFAULT_APP_LOCALE) {
    return zod_1.z
        .string()
        .regex(CUSTOM_WORKER_ID_PATTERN, {
        message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
    })
        .refine((value) => value !== "all" && value !== "default" && !isBuiltInWorkerName(value), {
        message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
    });
}
exports.customWorkerIdSchema = createCustomWorkerIdSchema();
exports.workflowTemplateIdSchema = createConfiguredEntityIdSchema().refine((value) => value !== "default", {
    message: (0, catalog_1.translate)(catalog_1.DEFAULT_APP_LOCALE, "config.error.workflowTemplateDefaultReserved"),
});
var issue_completion_2 = require("./issue-completion");
Object.defineProperty(exports, "ISSUE_COMPLETION_TARGET_VALUES", { enumerable: true, get: function () { return issue_completion_2.ISSUE_COMPLETION_TARGET_VALUES; } });
Object.defineProperty(exports, "PULL_REQUEST_MERGE_POLICY_VALUES", { enumerable: true, get: function () { return issue_completion_2.PULL_REQUEST_MERGE_POLICY_VALUES; } });
Object.defineProperty(exports, "PULL_REQUEST_REVIEW_POLICY_VALUES", { enumerable: true, get: function () { return issue_completion_2.PULL_REQUEST_REVIEW_POLICY_VALUES; } });
exports.WORKFLOW_START_APPROVAL_SCOPE_VALUES = [
    "issue_only",
    "issue_and_pr",
];
exports.WORKFLOW_START_APPROVAL_MODE_VALUES = [
    "auto",
    "confirm",
    "conservative",
    "aggressive",
];
exports.REQUIREMENTS_SETUP_APPROVAL_VALUES = ["auto", "confirm"];
exports.DEPENDENCIES_STRATEGY_VALUES = [
    "none",
    "auto",
    "block",
    "parallel_comment",
];
exports.GIT_HOOKS_MODE_VALUES = [
    "publish",
    "publish_and_worker",
    "off",
];
exports.WORKSPACE_SETUP_FREQUENCY_VALUES = [
    "when_changed",
    "once",
    "always",
];
exports.PARALLELISM_MODE_VALUES = ["balance", "greedy"];
exports.AI_WORKFLOW_OPTION_AUTOFILL_VALUES = ["off", "on"];
exports.FOLLOWUP_CHILD_ISSUE_POLICIES = ["inherit", "off"];
const PUBLIC_WORKFLOW_TEMPLATE_DEFAULT_SURFACES = types_2.WORKFLOW_TEMPLATE_TARGETS.filter((surface) => surface !== "followup");
exports.foreignIssueApprovalScopeSchema = zod_1.z.enum([
    "external_only",
    "all_foreign",
]);
function createDefaultWorkflowTemplateDefaults() {
    return Object.fromEntries(types_2.WORKFLOW_TEMPLATE_TARGETS.map((surface) => [
        surface,
        (0, types_2.createAutoSelectWorkflowTemplateSelector)(),
    ]));
}
function resolveFollowupDefaultWorkflowSelector(followup) {
    return followup.autoMaintainTemplates
        ? { mode: "auto" }
        : (0, types_2.createAutoSelectWorkflowTemplateSelector)();
}
function resolveWorkflowTemplateDefaultsWithFollowup(config) {
    return {
        ...config.workflowTemplateDefaults,
        followup: resolveFollowupDefaultWorkflowSelector(config.followup),
    };
}
exports.DEFAULT_CONFIG = {
    branchPrefix: branding_1.CLI_COMMAND_NAME,
    approvals: {
        workflowStart: {
            newPlan: "auto",
            replan: "auto",
            scope: "issue_and_pr",
        },
        requirementsSetup: {
            skills: "auto",
            mcp: "auto",
        },
    },
    dependencies: {
        strategy: "auto",
    },
    workflowTemplateDefaults: createDefaultWorkflowTemplateDefaults(),
    followup: {
        proposalPolicy: "if_needed",
        proposalApproval: "auto",
        maxIssuesPerSource: types_2.DEFAULT_WORKFLOW_FOLLOWUP_MAX_ISSUES_PER_SOURCE,
        preferredWorkflowTemplates: [],
        autoMaintainTemplates: false,
        childIssuePolicy: "inherit",
    },
    aiWorkflowOptionAutofill: "on",
    foreignIssueApprovalScope: "all_foreign",
    paths: {
        issueNotes: ".alpaca/issue-notes",
        systemPrompts: {},
    },
    i18n: config_2.defaultI18nConfig,
    issueCompletion: {
        target: "pull_request",
        pullRequest: {
            reviewPolicy: "if_needed",
            mergePolicy: "auto",
        },
    },
    git: {
        hooks: "publish",
    },
    workspaces: {
        setupCommand: null,
        setupFrequency: "when_changed",
        setupWatchPaths: "auto",
        setupTimeoutSec: 600,
    },
    repositoryHost: {
        kind: "github",
        projectRef: "owner/name",
        remoteName: "origin",
        baseBranch: "main",
        pullRequest: {
            defaultReviewers: [],
        },
    },
    ticketTracker: {
        kind: "github",
        projectRef: "owner/name",
        commentReactions: comment_reactions_1.DEFAULT_TRACKER_COMMENT_REACTIONS,
        workflowLabels: workflow_labels_1.DEFAULT_WORKFLOW_LABELS,
        showStepProgressInTitles: true,
    },
    customWorkers: {},
    workers: {
        default: ["codex"],
    },
    pollIntervalSec: 60,
    workerTimeoutSec: 3600,
    workerNoOutputTimeoutSec: 600,
    parallelism: {
        maxWorkers: 4,
        maxIssues: 4,
        mode: "balance",
    },
    aiRunLimits: {
        maxRuns: 30,
        maxHours: 5,
    },
    autoReviews: {
        plan: {
            maxRevisions: 1,
        },
    },
    recurring: {
        maxActiveChildren: 1,
        updateChildTitleAfterPlan: false,
    },
    cooldownDefaultSecs: {
        capacity: 900,
        quotaExhausted: 3600,
    },
    eventHooks: [],
    maxNestedWorkflowDepth: 5,
};
const aiRunMaxRunsSchema = zod_1.z.number().int().min(0);
const aiRunMaxHoursSchema = zod_1.z.number().min(0).nullable();
const FOLLOWUP_PREFERRED_WORKFLOW_TEMPLATES_CONFIG_OVERRIDE_PATH = "followup.preferredWorkflowTemplates";
exports.controlPlaneConfigSchema = createControlPlaneConfigSchema();
async function loadConfig(cwd) {
    const filePath = getConfigPath(cwd);
    const text = await (0, promises_1.readFile)(filePath, "utf8");
    const parsed = JSON.parse(text);
    return createControlPlaneConfigSchema(resolveConfigLocale(parsed)).parse(parsed);
}
async function writeConfig(cwd, config) {
    const filePath = getConfigPath(cwd);
    await (0, promises_1.writeFile)(filePath, formatConfigFile(config), "utf8");
    return filePath;
}
function getConfigPath(cwd) {
    return node_path_1.default.join(cwd, paths_1.CONFIG_FILENAME);
}
function formatConfigFile(config) {
    return `${JSON.stringify(normalizeConfigForWrite(config), null, 2)}\n`;
}
function normalizeConfigForWrite(config) {
    return {
        i18n: {
            defaultLanguage: config.i18n.defaultLanguage,
            displayTimeZone: config.i18n.displayTimeZone,
        },
        repositoryHost: {
            kind: config.repositoryHost.kind,
            projectRef: config.repositoryHost.projectRef,
            remoteName: config.repositoryHost.remoteName,
            baseBranch: config.repositoryHost.baseBranch,
            pullRequest: serializePullRequestConfig(config.repositoryHost.pullRequest ??
                normalizePullRequestConfig(undefined)),
        },
        issueCompletion: {
            target: config.issueCompletion.target,
            pullRequest: {
                reviewPolicy: config.issueCompletion.pullRequest.reviewPolicy,
                mergePolicy: config.issueCompletion.pullRequest.mergePolicy,
            },
        },
        git: {
            hooks: config.git.hooks,
        },
        workspaces: {
            setupCommand: config.workspaces.setupCommand,
            setupFrequency: config.workspaces.setupFrequency,
            setupWatchPaths: config.workspaces.setupWatchPaths === "auto"
                ? "auto"
                : [...config.workspaces.setupWatchPaths],
            setupTimeoutSec: config.workspaces.setupTimeoutSec,
        },
        ticketTracker: {
            kind: config.ticketTracker.kind,
            projectRef: config.ticketTracker.projectRef,
            workflowLabels: (0, workflow_labels_1.resolveWorkflowLabels)(config.ticketTracker.workflowLabels),
            showStepProgressInTitles: config.ticketTracker.showStepProgressInTitles,
            commentReactions: [...config.ticketTracker.commentReactions],
        },
        customWorkers: cloneCustomWorkersConfig(config.customWorkers),
        workers: cloneWorkersConfig(config.workers),
        pollIntervalSec: config.pollIntervalSec,
        workerTimeoutSec: config.workerTimeoutSec,
        workerNoOutputTimeoutSec: config.workerNoOutputTimeoutSec,
        parallelism: {
            maxWorkers: config.parallelism.maxWorkers,
            maxIssues: config.parallelism.maxIssues,
            mode: config.parallelism.mode,
        },
        aiRunLimits: {
            maxRuns: config.aiRunLimits.maxRuns,
            maxHours: config.aiRunLimits.maxHours ?? null,
        },
        autoReviews: {
            plan: {
                maxRevisions: config.autoReviews.plan.maxRevisions,
            },
        },
        recurring: {
            maxActiveChildren: config.recurring.maxActiveChildren,
            updateChildTitleAfterPlan: config.recurring.updateChildTitleAfterPlan,
        },
        cooldownDefaultSecs: {
            capacity: config.cooldownDefaultSecs.capacity,
            quotaExhausted: config.cooldownDefaultSecs.quotaExhausted,
        },
        branchPrefix: config.branchPrefix,
        approvals: {
            workflowStart: {
                newPlan: config.approvals.workflowStart.newPlan,
                replan: config.approvals.workflowStart.replan,
                scope: config.approvals.workflowStart.scope,
            },
            requirementsSetup: {
                skills: config.approvals.requirementsSetup.skills,
                mcp: config.approvals.requirementsSetup.mcp,
            },
        },
        dependencies: {
            strategy: config.dependencies.strategy,
        },
        workflowTemplateDefaults: formatWorkflowTemplateDefaultsConfig(config.workflowTemplateDefaults),
        maxNestedWorkflowDepth: config.maxNestedWorkflowDepth,
        followup: {
            proposalPolicy: config.followup.proposalPolicy,
            proposalApproval: config.followup.proposalApproval,
            maxIssuesPerSource: config.followup.maxIssuesPerSource,
            preferredWorkflowTemplates: [
                ...config.followup.preferredWorkflowTemplates,
            ],
            autoMaintainTemplates: config.followup.autoMaintainTemplates,
            childIssuePolicy: config.followup.childIssuePolicy,
        },
        aiWorkflowOptionAutofill: config.aiWorkflowOptionAutofill,
        foreignIssueApprovalScope: config.foreignIssueApprovalScope,
        eventHooks: config.eventHooks.map((hook) => ({
            path: hook.path,
            ...(hook.runner !== undefined ? { runner: hook.runner } : {}),
            on: [...hook.on],
        })),
        paths: {
            issueNotes: config.paths.issueNotes,
            systemPrompts: { ...config.paths.systemPrompts },
        },
    };
}
function serializePullRequestConfig(config) {
    return {
        defaultReviewers: [...config.defaultReviewers],
    };
}
function formatWorkflowTemplateDefaultsConfig(config) {
    return Object.fromEntries(PUBLIC_WORKFLOW_TEMPLATE_DEFAULT_SURFACES.map((surface) => [
        surface,
        formatWorkflowTemplateSelectorConfigValue(config[surface]),
    ]));
}
function formatWorkflowTemplateSelectorConfigValue(selector) {
    switch (selector.mode) {
        case "auto":
            return types_2.WORKFLOW_TEMPLATE_AUTO_SENTINEL;
        case "auto_select":
            return types_2.WORKFLOW_TEMPLATE_AUTO_SELECT_SENTINEL;
        case "no_template":
            return types_2.WORKFLOW_TEMPLATE_NO_TEMPLATE_SENTINEL;
        case "template":
            return selector.templatePath;
    }
}
function cloneWorkersConfig(workers) {
    return {
        default: [...workers.default],
        ...(workers.thinking !== undefined
            ? { thinking: [...workers.thinking] }
            : {}),
    };
}
function cloneCustomWorkersConfig(customWorkers) {
    return Object.fromEntries(Object.entries(customWorkers).map(([worker, config]) => [
        worker,
        {
            baseUrl: config.baseUrl,
            model: config.model,
            ...(config.apiKey !== undefined ? { apiKey: config.apiKey } : {}),
            ...(config.headers !== undefined
                ? { headers: { ...config.headers } }
                : {}),
            ...(config.requestParams !== undefined
                ? { requestParams: (0, structured_clone_1.cloneStructured)(config.requestParams) }
                : {}),
        },
    ]));
}
function isBuiltInWorkerName(worker) {
    return exports.BUILT_IN_WORKER_NAMES.includes(worker);
}
function isCustomWorkerName(config, worker) {
    return !isBuiltInWorkerName(worker) && hasCustomWorkerConfig(config, worker);
}
function resolveConfiguredWorkerNames(config) {
    return getConfiguredWorkerProviders(config);
}
function resolveCustomWorkerConfig(config, worker) {
    return hasCustomWorkerConfig(config, worker)
        ? (config.customWorkers[worker] ?? null)
        : null;
}
function hasCustomWorkerConfig(config, worker) {
    return Object.hasOwn(config.customWorkers, worker);
}
function collectCustomWorkerEnvTemplateNames(config) {
    const names = new Set();
    for (const customWorker of Object.values(config.customWorkers)) {
        for (const name of (0, env_template_1.collectConfigEnvTemplateNames)(customWorker.baseUrl)) {
            names.add(name);
        }
        for (const name of (0, env_template_1.collectConfigEnvTemplateNames)(customWorker.model)) {
            names.add(name);
        }
        if (customWorker.apiKey !== undefined) {
            for (const name of (0, env_template_1.collectConfigEnvTemplateNames)(customWorker.apiKey)) {
                names.add(name);
            }
        }
        for (const value of Object.values(customWorker.headers ?? {})) {
            for (const name of (0, env_template_1.collectConfigEnvTemplateNames)(value)) {
                names.add(name);
            }
        }
        if (customWorker.requestParams !== undefined) {
            for (const name of collectJsonEnvTemplateNames(customWorker.requestParams)) {
                names.add(name);
            }
        }
    }
    return [...names];
}
function collectJsonEnvTemplateNames(value) {
    if (typeof value === "string") {
        return (0, env_template_1.collectConfigEnvTemplateNames)(value);
    }
    if (Array.isArray(value)) {
        return value.flatMap((item) => collectJsonEnvTemplateNames(item));
    }
    if (value !== null && typeof value === "object") {
        return Object.values(value).flatMap((item) => collectJsonEnvTemplateNames(item));
    }
    return [];
}
function getConfiguredBuiltInWorkers(config) {
    return getConfiguredWorkerProviders(config).filter(isBuiltInWorkerName);
}
function getDefaultWorkers(config) {
    return [...config.workers.default];
}
function getThinkingWorkers(config) {
    return [...(config.workers.thinking ?? config.workers.default)];
}
function getConfiguredWorkerProviders(config) {
    return dedupeWorkers([
        ...config.workers.default,
        ...(config.workers.thinking ?? []),
    ]);
}
function resolveWorkersForPurpose(config, purpose) {
    if (purpose === "default") {
        return getDefaultWorkers(config);
    }
    return dedupeWorkers([
        ...(config.workers.thinking ?? config.workers.default),
        ...config.workers.default,
    ]);
}
function dedupeWorkers(workers) {
    return [...new Set(workers)];
}
function normalizePullRequestConfig(config) {
    return {
        defaultReviewers: [
            ...(config?.defaultReviewers ??
                exports.DEFAULT_CONFIG.repositoryHost.pullRequest.defaultReviewers),
        ],
    };
}
function resolveIssueCompletion(config) {
    return config.issueCompletion;
}
function isIssueCompletionAutoMergeEnabled(config) {
    return (0, issue_completion_1.isPullRequestAutoMergePolicyEnabled)(resolveIssueCompletion(config));
}
function resolveWorkflowStartApprovalMode(input) {
    const workflowStart = input.config.approvals.workflowStart;
    if (workflowStart.scope === "issue_only" && input.target === "pull_request") {
        return "auto";
    }
    if (input.planningIntent === "new_plan") {
        return workflowStart.newPlan;
    }
    if (input.planningIntent === "replan") {
        return workflowStart.replan;
    }
    if (input.planningIntent === "revise_plan") {
        if (input.startApprovalIntent !== "new_plan" &&
            input.startApprovalIntent !== "replan") {
            throw new Error("Workflow revise_plan start approval mode requires a start approval intent.");
        }
        return input.startApprovalIntent === "new_plan"
            ? workflowStart.newPlan
            : workflowStart.replan;
    }
    const exhaustiveCheck = input;
    return exhaustiveCheck;
}
function resolveWorkflowStartApprovalModeForPlanningIntent(input) {
    if (input.planningIntent === "revise_plan") {
        if (input.startApprovalIntent === undefined ||
            input.startApprovalIntent === null) {
            throw new Error("Workflow revise_plan start approval mode requires a start approval intent.");
        }
        return resolveWorkflowStartApprovalMode({
            target: input.target,
            planningIntent: input.planningIntent,
            startApprovalIntent: input.startApprovalIntent,
            config: input.config,
        });
    }
    return resolveWorkflowStartApprovalMode({
        target: input.target,
        planningIntent: input.planningIntent,
        config: input.config,
    });
}
function resolveIssueEffectiveConfig(baseConfig, patch) {
    const effectiveConfig = (0, structured_clone_1.cloneStructured)(baseConfig);
    if (!patch || patch.entries.length === 0) {
        return effectiveConfig;
    }
    (0, config_override_validation_1.assertNoUnavailableWorkerConfigOverride)({
        configWorkers: getConfiguredWorkerProviders(baseConfig),
        patch,
    });
    const sortedEntries = [...patch.entries].sort((left, right) => countConfigPathSegments(left.path) - countConfigPathSegments(right.path));
    for (const entry of sortedEntries) {
        applyConfigOverrideEntry(effectiveConfig, baseConfig, entry);
    }
    return effectiveConfig;
}
function resolveIssueEffectiveConfigForWorkflowState(baseConfig, workflowState) {
    const effectiveConfig = resolveIssueEffectiveConfig(baseConfig, workflowState?.configOverrides);
    if (workflowState !== null) {
        effectiveConfig.repositoryHost.baseBranch = workflowState.baseBranch;
    }
    return effectiveConfig;
}
function resolveIssueEffectiveConfigFromComments(baseConfig, comments, locale = catalog_1.DEFAULT_APP_LOCALE, options = {}) {
    const canonicalResolution = (0, canonical_workflow_state_1.resolveCanonicalWorkflowStateComment)(comments, locale);
    const stickyState = canonicalResolution.kind === "found"
        ? canonicalResolution.workflowState
        : null;
    const pendingWorkflowCommand = (0, workflow_command_state_1.resolvePendingWorkflowCommand)(comments, {
        issueBody: options.issueBody ?? null,
        workflowState: stickyState,
    });
    const appliedCommandState = (0, command_apply_1.applyWorkflowCommandToStickyState)({
        stickyState,
        command: pendingWorkflowCommand?.command.kind === "update"
            ? pendingWorkflowCommand.command
            : null,
        baseBranchDefault: baseConfig.repositoryHost.baseBranch,
        workflowSurface: stickyState?.workflowSurface ?? "issue",
        workflowTemplateDefaults: baseConfig.workflowTemplateDefaults,
    });
    const effectiveConfig = resolveIssueEffectiveConfig(baseConfig, appliedCommandState.configOverrides);
    effectiveConfig.repositoryHost.baseBranch = appliedCommandState.baseBranch;
    return effectiveConfig;
}
function countConfigPathSegments(path) {
    return path.split(".").length;
}
function applyConfigOverrideEntry(effectiveConfig, baseConfig, entry) {
    (0, config_override_validation_1.assertConfigOverrideEntryValid)(entry);
    switch (entry.op) {
        case "disable":
            setConfigPathValue(effectiveConfig, entry.path, null);
            return;
        case "inherit":
            setConfigPathValue(effectiveConfig, entry.path, (0, structured_clone_1.cloneStructured)(getConfigPathValue(baseConfig, entry.path)));
            return;
        case "set":
            setConfigPathValue(effectiveConfig, entry.path, resolveConfigOverrideSetValue(entry));
            return;
    }
}
function resolveConfigOverrideSetValue(entry) {
    if (entry.path === config_override_validation_1.DEFAULT_WORKERS_CONFIG_OVERRIDE_PATH &&
        Array.isArray(entry.value)) {
        return dedupeWorkers(entry.value);
    }
    if (entry.path === config_override_validation_1.THINKING_WORKERS_CONFIG_OVERRIDE_PATH &&
        Array.isArray(entry.value)) {
        return dedupeWorkers(entry.value);
    }
    if (entry.path === FOLLOWUP_PREFERRED_WORKFLOW_TEMPLATES_CONFIG_OVERRIDE_PATH &&
        Array.isArray(entry.value)) {
        return [
            ...new Set(entry.value.flatMap((value) => {
                if (typeof value !== "string") {
                    return [];
                }
                const normalized = (0, types_2.normalizeFollowupWorkflowTemplateCandidate)(value);
                return normalized === null ? [] : [normalized];
            })),
        ];
    }
    return (0, structured_clone_1.cloneStructured)(entry.value);
}
function getConfigPathValue(target, path) {
    let current = target;
    for (const segment of path.split(".")) {
        if (current === null ||
            current === undefined ||
            typeof current !== "object") {
            return undefined;
        }
        current = Reflect.get(current, segment);
    }
    return current;
}
function setConfigPathValue(target, path, value) {
    if (target === null || typeof target !== "object") {
        return;
    }
    const segments = path.split(".");
    let current = target;
    for (const segment of segments.slice(0, -1)) {
        const next = Reflect.get(current, segment);
        if (next === null || next === undefined || typeof next !== "object") {
            Reflect.set(current, segment, {});
        }
        const resolvedNext = Reflect.get(current, segment);
        if (resolvedNext === null || typeof resolvedNext !== "object") {
            return;
        }
        current = resolvedNext;
    }
    const finalSegment = segments.at(-1);
    if (finalSegment) {
        Reflect.set(current, finalSegment, value);
    }
}
function createConfiguredEntityIdSchema(locale = catalog_1.DEFAULT_APP_LOCALE) {
    return zod_1.z
        .string()
        .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"));
}
function createRemoteNameSchema(locale = catalog_1.DEFAULT_APP_LOCALE) {
    return zod_1.z.string().refine(remote_name_1.isValidRemoteName, {
        message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
    });
}
function createBranchPrefixSchema(locale = catalog_1.DEFAULT_APP_LOCALE) {
    return zod_1.z
        .string()
        .min(1)
        .refine((value) => value.trim() === value, {
        message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
    })
        .refine((value) => !value.startsWith("/") && !value.endsWith("/"), {
        message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
    })
        .refine((value) => value.split("/").every((segment) => segment.length > 0), {
        message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
    });
}
function createWorkflowLabelValueSchema(locale = catalog_1.DEFAULT_APP_LOCALE) {
    return zod_1.z
        .string()
        .min(1)
        .refine((value) => value.trim().length > 0, {
        message: (0, catalog_1.translate)(locale, "config.error.workflowLabelBlankAfterTrim"),
    });
}
// biome-ignore lint/complexity/noExcessiveLinesPerFunction: config schema stays centralized to keep parse/write rules aligned.
function createControlPlaneConfigSchema(locale = catalog_1.DEFAULT_APP_LOCALE) {
    const workflowStartApprovalInputSchema = zod_1.z
        .object({
        newPlan: zod_1.z
            .enum(exports.WORKFLOW_START_APPROVAL_MODE_VALUES)
            .optional()
            .default(exports.DEFAULT_CONFIG.approvals.workflowStart.newPlan),
        replan: zod_1.z
            .enum(exports.WORKFLOW_START_APPROVAL_MODE_VALUES)
            .optional()
            .default(exports.DEFAULT_CONFIG.approvals.workflowStart.replan),
        scope: zod_1.z
            .enum(exports.WORKFLOW_START_APPROVAL_SCOPE_VALUES)
            .optional()
            .default(exports.DEFAULT_CONFIG.approvals.workflowStart.scope),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.approvals.workflowStart);
    const requirementsSetupApprovalInputSchema = zod_1.z
        .object({
        skills: zod_1.z
            .enum(exports.REQUIREMENTS_SETUP_APPROVAL_VALUES)
            .optional()
            .default(exports.DEFAULT_CONFIG.approvals.requirementsSetup.skills),
        mcp: zod_1.z
            .enum(exports.REQUIREMENTS_SETUP_APPROVAL_VALUES)
            .optional()
            .default(exports.DEFAULT_CONFIG.approvals.requirementsSetup.mcp),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.approvals.requirementsSetup);
    const issueCompletionInputSchema = zod_1.z
        .object({
        target: zod_1.z
            .enum(issue_completion_1.ISSUE_COMPLETION_TARGET_VALUES)
            .default(exports.DEFAULT_CONFIG.issueCompletion.target),
        pullRequest: zod_1.z
            .object({
            reviewPolicy: zod_1.z
                .enum(issue_completion_1.PULL_REQUEST_REVIEW_POLICY_VALUES)
                .default(exports.DEFAULT_CONFIG.issueCompletion.pullRequest.reviewPolicy),
            mergePolicy: zod_1.z
                .enum(issue_completion_1.PULL_REQUEST_MERGE_POLICY_VALUES)
                .default(exports.DEFAULT_CONFIG.issueCompletion.pullRequest.mergePolicy),
        })
            .strict()
            .default(exports.DEFAULT_CONFIG.issueCompletion.pullRequest),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.issueCompletion);
    const workflowLabelsInputSchema = zod_1.z
        .object({
        aiReady: createWorkflowLabelValueSchema(locale),
        aiRunning: createWorkflowLabelValueSchema(locale),
        aiNeedsHuman: createWorkflowLabelValueSchema(locale),
        aiWorkingInPr: createWorkflowLabelValueSchema(locale)
            .optional()
            .default(workflow_labels_1.DEFAULT_WORKFLOW_LABELS.aiWorkingInPr),
        aiDisabled: createWorkflowLabelValueSchema(locale),
        aiRecurring: createWorkflowLabelValueSchema(locale)
            .optional()
            .default(workflow_labels_1.DEFAULT_WORKFLOW_LABELS.aiRecurring),
        aiScheduled: createWorkflowLabelValueSchema(locale)
            .optional()
            .default(workflow_labels_1.DEFAULT_WORKFLOW_LABELS.aiScheduled),
        aiQuestion: createWorkflowLabelValueSchema(locale)
            .optional()
            .default(workflow_labels_1.DEFAULT_WORKFLOW_LABELS.aiQuestion),
        aiRunLimit: createWorkflowLabelValueSchema(locale)
            .optional()
            .default(workflow_labels_1.DEFAULT_WORKFLOW_LABELS.aiRunLimit),
        aiCoolingDown: createWorkflowLabelValueSchema(locale)
            .optional()
            .default(workflow_labels_1.DEFAULT_WORKFLOW_LABELS.aiCoolingDown),
        aiFollowUp: createWorkflowLabelValueSchema(locale)
            .optional()
            .default(workflow_labels_1.DEFAULT_WORKFLOW_LABELS.aiFollowUp),
    })
        .strict();
    const dependenciesInputSchema = zod_1.z
        .object({
        strategy: zod_1.z
            .enum(exports.DEPENDENCIES_STRATEGY_VALUES)
            .default(exports.DEFAULT_CONFIG.dependencies.strategy),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.dependencies);
    const gitInputSchema = zod_1.z
        .object({
        hooks: zod_1.z.enum(exports.GIT_HOOKS_MODE_VALUES).default(exports.DEFAULT_CONFIG.git.hooks),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.git);
    const workspaceSetupWatchPathSchema = zod_1.z
        .string()
        .trim()
        .min(1)
        .refine(isWorkspaceSetupWatchPathRepoRelative, {
        message: "Workspace setup watch paths must be repo-relative and must not contain dot or parent traversal segments.",
    });
    const workspaceSetupWatchPathsInputSchema = zod_1.z.union([
        zod_1.z.literal("auto"),
        zod_1.z
            .array(workspaceSetupWatchPathSchema)
            .transform((paths) => [...new Set(paths)]),
    ]);
    const workspacesInputSchema = zod_1.z
        .object({
        setupCommand: zod_1.z
            .string()
            .trim()
            .min(1)
            .nullable()
            .default(exports.DEFAULT_CONFIG.workspaces.setupCommand),
        setupFrequency: zod_1.z
            .enum(exports.WORKSPACE_SETUP_FREQUENCY_VALUES)
            .default(exports.DEFAULT_CONFIG.workspaces.setupFrequency),
        setupWatchPaths: workspaceSetupWatchPathsInputSchema.default(exports.DEFAULT_CONFIG.workspaces.setupWatchPaths),
        setupTimeoutSec: zod_1.z
            .number()
            .int()
            .positive()
            .default(exports.DEFAULT_CONFIG.workspaces.setupTimeoutSec),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.workspaces);
    const workflowTemplateDefaultSelectorObjectSchema = zod_1.z
        .union([
        zod_1.z.object({ mode: zod_1.z.literal("auto") }).strict(),
        zod_1.z.object({ mode: zod_1.z.literal("auto_select") }).strict(),
        zod_1.z.object({ mode: zod_1.z.literal("no_template") }).strict(),
        zod_1.z
            .object({
            mode: zod_1.z.literal("template"),
            templatePath: zod_1.z.string().min(1),
        })
            .strict(),
    ])
        .transform((selector, context) => {
        if (selector.mode !== "template") {
            return selector;
        }
        const normalizedPath = (0, types_2.normalizeWorkflowTemplatePath)(selector.templatePath);
        if (normalizedPath === null) {
            context.addIssue({
                code: "custom",
                message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
            });
            return zod_1.z.NEVER;
        }
        return { mode: "template", templatePath: normalizedPath };
    });
    const workflowTemplateDefaultSelectorInputSchema = zod_1.z.union([
        zod_1.z.string().transform((value, context) => {
            if (value === types_2.WORKFLOW_TEMPLATE_AUTO_SENTINEL) {
                return { mode: "auto" };
            }
            if (value === types_2.WORKFLOW_TEMPLATE_AUTO_SELECT_SENTINEL) {
                return { mode: "auto_select" };
            }
            if (value === types_2.WORKFLOW_TEMPLATE_NO_TEMPLATE_SENTINEL) {
                return { mode: "no_template" };
            }
            const normalizedPath = (0, types_2.normalizeWorkflowTemplatePath)(value);
            if (normalizedPath === null) {
                context.addIssue({
                    code: "custom",
                    message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
                });
                return zod_1.z.NEVER;
            }
            return { mode: "template", templatePath: normalizedPath };
        }),
        workflowTemplateDefaultSelectorObjectSchema,
    ]);
    const workflowTemplateDefaultsShape = Object.fromEntries(PUBLIC_WORKFLOW_TEMPLATE_DEFAULT_SURFACES.map((surface) => [
        surface,
        workflowTemplateDefaultSelectorInputSchema
            .optional()
            .default(exports.DEFAULT_CONFIG.workflowTemplateDefaults[surface]),
    ]));
    const workflowTemplateDefaultsInputSchema = zod_1.z
        .object(workflowTemplateDefaultsShape)
        .strict()
        .default(Object.fromEntries(PUBLIC_WORKFLOW_TEMPLATE_DEFAULT_SURFACES.map((surface) => [
        surface,
        exports.DEFAULT_CONFIG.workflowTemplateDefaults[surface],
    ])))
        .transform((defaults) => ({
        ...exports.DEFAULT_CONFIG.workflowTemplateDefaults,
        ...defaults,
    }));
    const followupPreferredWorkflowTemplateInputSchema = zod_1.z
        .string()
        .transform((value, context) => {
        const normalized = (0, types_2.normalizeFollowupWorkflowTemplateCandidate)(value);
        if (normalized === null) {
            context.addIssue({
                code: "custom",
                message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
            });
            return zod_1.z.NEVER;
        }
        return normalized;
    });
    const followupMaxIssuesPerSourceInputSchema = zod_1.z
        .object({
        mainWork: zod_1.z
            .number()
            .int()
            .min(0)
            .max(5)
            .default(exports.DEFAULT_CONFIG.followup.maxIssuesPerSource.mainWork),
        maintenance: zod_1.z
            .number()
            .int()
            .min(0)
            .max(5)
            .default(exports.DEFAULT_CONFIG.followup.maxIssuesPerSource.maintenance),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.followup.maxIssuesPerSource);
    const followupInputSchema = zod_1.z
        .object({
        proposalPolicy: zod_1.z
            .enum(types_2.FOLLOWUP_PROPOSAL_POLICIES)
            .default(exports.DEFAULT_CONFIG.followup.proposalPolicy),
        proposalApproval: zod_1.z
            .enum(types_2.FOLLOWUP_PROPOSAL_APPROVALS)
            .default(exports.DEFAULT_CONFIG.followup.proposalApproval),
        maxIssuesPerSource: followupMaxIssuesPerSourceInputSchema,
        preferredWorkflowTemplates: zod_1.z
            .array(followupPreferredWorkflowTemplateInputSchema)
            .default(() => [...exports.DEFAULT_CONFIG.followup.preferredWorkflowTemplates])
            .transform((templates) => [...new Set(templates)]),
        autoMaintainTemplates: zod_1.z
            .boolean()
            .default(exports.DEFAULT_CONFIG.followup.autoMaintainTemplates),
        childIssuePolicy: zod_1.z
            .enum(exports.FOLLOWUP_CHILD_ISSUE_POLICIES)
            .default(exports.DEFAULT_CONFIG.followup.childIssuePolicy),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.followup);
    const cooldownDefaultSecsInputSchema = zod_1.z
        .object({
        capacity: zod_1.z
            .number()
            .int()
            .positive()
            .default(exports.DEFAULT_CONFIG.cooldownDefaultSecs.capacity),
        quotaExhausted: zod_1.z
            .number()
            .int()
            .positive()
            .default(exports.DEFAULT_CONFIG.cooldownDefaultSecs.quotaExhausted),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.cooldownDefaultSecs);
    const autoReviewsInputSchema = zod_1.z
        .object({
        plan: zod_1.z
            .object({
            maxRevisions: zod_1.z
                .number()
                .int()
                .min(1)
                .default(exports.DEFAULT_CONFIG.autoReviews.plan.maxRevisions),
        })
            .strict()
            .default(exports.DEFAULT_CONFIG.autoReviews.plan),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.autoReviews);
    const systemPromptPathInputSchema = zod_1.z
        .string()
        .refine((value) => (0, paths_2.normalizeSystemPromptPath)(value) !== null, (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"));
    const issueNotesPathInputSchema = zod_1.z
        .string()
        .refine((value) => isRepoRelativeConfigDirectoryPath(value), (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"));
    const systemPromptPathsShape = Object.fromEntries(types_1.SYSTEM_PROMPT_PATH_NAMES.map((name) => [
        name,
        systemPromptPathInputSchema.optional(),
    ]));
    const pathsInputSchema = zod_1.z
        .object({
        issueNotes: issueNotesPathInputSchema.default(exports.DEFAULT_CONFIG.paths.issueNotes),
        systemPrompts: zod_1.z
            .object(systemPromptPathsShape)
            .strict()
            .default(exports.DEFAULT_CONFIG.paths.systemPrompts),
    })
        .strict()
        .default(exports.DEFAULT_CONFIG.paths);
    const jsonValueInputSchema = zod_1.z.lazy(() => zod_1.z.union([
        zod_1.z.string(),
        zod_1.z.number(),
        zod_1.z.boolean(),
        zod_1.z.null(),
        zod_1.z.array(jsonValueInputSchema),
        zod_1.z.record(zod_1.z.string(), jsonValueInputSchema),
    ]));
    const requestParamsInputSchema = zod_1.z.record(zod_1.z.string(), jsonValueInputSchema);
    const customWorkerConfigInputSchema = zod_1.z
        .object({
        baseUrl: zod_1.z.string().trim().min(1),
        model: zod_1.z.string().trim().min(1).default("default"),
        apiKey: zod_1.z.string().trim().min(1).optional(),
        headers: zod_1.z.record(zod_1.z.string().trim().min(1), zod_1.z.string().min(1)).optional(),
        requestParams: requestParamsInputSchema.optional(),
    })
        .strict()
        .superRefine((config, context) => {
        if (config.apiKey !== undefined &&
            hasHeaderName(config.headers, "authorization")) {
            context.addIssue({
                code: "custom",
                message: (0, catalog_1.translate)(locale, "config.error.customWorkerDuplicateAuth"),
                path: ["headers", "Authorization"],
            });
        }
    })
        .transform((config) => ({
        baseUrl: config.baseUrl,
        model: config.model,
        ...(config.apiKey !== undefined ? { apiKey: config.apiKey } : {}),
        ...(config.headers !== undefined
            ? { headers: { ...config.headers } }
            : {}),
        ...(config.requestParams !== undefined
            ? { requestParams: (0, structured_clone_1.cloneStructured)(config.requestParams) }
            : {}),
    }));
    const customWorkersInputSchema = zod_1.z
        .record(createCustomWorkerIdSchema(locale), customWorkerConfigInputSchema)
        .default(exports.DEFAULT_CONFIG.customWorkers);
    const workerListSchema = zod_1.z.array(exports.workerNameSchema).min(1);
    const workersInputSchema = zod_1.z
        .object({
        default: workerListSchema,
        thinking: workerListSchema.optional(),
    })
        .strict()
        .transform((workers) => ({
        default: [...workers.default],
        ...(workers.thinking !== undefined
            ? { thinking: [...workers.thinking] }
            : {}),
    }));
    return zod_1.z
        .object({
        branchPrefix: createBranchPrefixSchema(locale).default(exports.DEFAULT_CONFIG.branchPrefix),
        approvals: zod_1.z
            .object({
            workflowStart: workflowStartApprovalInputSchema,
            requirementsSetup: requirementsSetupApprovalInputSchema,
        })
            .strict()
            .default(exports.DEFAULT_CONFIG.approvals),
        dependencies: dependenciesInputSchema,
        workflowTemplateDefaults: workflowTemplateDefaultsInputSchema,
        followup: followupInputSchema,
        aiWorkflowOptionAutofill: zod_1.z
            .enum(exports.AI_WORKFLOW_OPTION_AUTOFILL_VALUES)
            .default(exports.DEFAULT_CONFIG.aiWorkflowOptionAutofill),
        foreignIssueApprovalScope: exports.foreignIssueApprovalScopeSchema.default(exports.DEFAULT_CONFIG.foreignIssueApprovalScope),
        issueCompletion: issueCompletionInputSchema,
        git: gitInputSchema,
        workspaces: workspacesInputSchema,
        paths: pathsInputSchema,
        i18n: zod_1.z
            .object({
            defaultLanguage: config_2.appLocaleSchema,
            displayTimeZone: zod_1.z
                .string()
                .min(1)
                .refine(display_time_1.isSupportedTimeZone, {
                message: (0, catalog_1.translate)(locale, "config.error.displayTimeZoneInvalid"),
            })
                .default(config_2.defaultI18nConfig.displayTimeZone),
        })
            .strict()
            .default(config_2.defaultI18nConfig),
        repositoryHost: zod_1.z
            .object({
            kind: tracked_project_1.repositoryHostKindSchema,
            projectRef: zod_1.z.string().min(1),
            remoteName: createRemoteNameSchema(locale),
            baseBranch: zod_1.z.string().min(1),
            pullRequest: zod_1.z
                .object({
                defaultReviewers: zod_1.z
                    .array(zod_1.z.string().min(1))
                    .default(() => [
                    ...exports.DEFAULT_CONFIG.repositoryHost.pullRequest.defaultReviewers,
                ]),
            })
                .strict()
                .default(() => ({
                defaultReviewers: [
                    ...exports.DEFAULT_CONFIG.repositoryHost.pullRequest.defaultReviewers,
                ],
            }))
                .transform((config) => ({
                defaultReviewers: [...config.defaultReviewers],
            })),
        })
            .strict(),
        ticketTracker: zod_1.z
            .object({
            kind: tracked_project_1.ticketTrackerKindSchema,
            projectRef: zod_1.z.string().min(1),
            commentReactions: zod_1.z
                .array(zod_1.z.enum(comment_reactions_1.TRACKER_COMMENT_REACTION_VALUES))
                .default(() => [...comment_reactions_1.DEFAULT_TRACKER_COMMENT_REACTIONS]),
            showStepProgressInTitles: zod_1.z.boolean(),
            workflowLabels: workflowLabelsInputSchema,
        })
            .strict(),
        customWorkers: customWorkersInputSchema,
        workers: workersInputSchema,
        pollIntervalSec: zod_1.z.number().int().positive(),
        workerTimeoutSec: zod_1.z.number().int().positive(),
        workerNoOutputTimeoutSec: zod_1.z
            .number()
            .int()
            .positive()
            .nullable()
            .default(exports.DEFAULT_CONFIG.workerNoOutputTimeoutSec),
        parallelism: zod_1.z
            .object({
            maxWorkers: zod_1.z.number().int().positive(),
            maxIssues: zod_1.z.number().int().positive(),
            mode: zod_1.z.enum(exports.PARALLELISM_MODE_VALUES),
        })
            .strict(),
        aiRunLimits: zod_1.z
            .object({
            maxRuns: aiRunMaxRunsSchema,
            maxHours: aiRunMaxHoursSchema,
        })
            .strict(),
        autoReviews: autoReviewsInputSchema,
        recurring: zod_1.z
            .object({
            maxActiveChildren: zod_1.z.number().int().min(1),
            updateChildTitleAfterPlan: zod_1.z.boolean(),
        })
            .strict()
            .default(exports.DEFAULT_CONFIG.recurring),
        cooldownDefaultSecs: cooldownDefaultSecsInputSchema,
        eventHooks: (0, config_1.createRepoEventHookConfigSchema)(locale).default([]),
        maxNestedWorkflowDepth: zod_1.z
            .number()
            .int()
            .min(0)
            .default(exports.DEFAULT_CONFIG.maxNestedWorkflowDepth),
    })
        .strict()
        .superRefine((config, context) => {
        addDuplicateWorkerIssues(config.workers.default, ["workers", "default"], context, locale);
        if (config.workers.thinking !== undefined) {
            addDuplicateWorkerIssues(config.workers.thinking, ["workers", "thinking"], context, locale);
        }
        addUnknownWorkerIssues(config.workers.default, config.customWorkers, ["workers", "default"], context, locale);
        if (config.workers.thinking !== undefined) {
            addUnknownWorkerIssues(config.workers.thinking, config.customWorkers, ["workers", "thinking"], context, locale);
        }
        if (config.parallelism.maxIssues > config.parallelism.maxWorkers) {
            context.addIssue({
                code: "custom",
                message: (0, catalog_1.translate)(locale, "config.error.parallelismMaxIssues"),
                path: ["parallelism", "maxIssues"],
            });
        }
        const workflowLabels = config.ticketTracker.workflowLabels;
        const seenWorkflowLabelValues = new Map();
        for (const key of workflow_labels_1.WORKFLOW_LABEL_KEYS) {
            const value = workflowLabels[key];
            const trimmedValue = value.trim();
            const previousKey = seenWorkflowLabelValues.get(trimmedValue);
            if (previousKey) {
                context.addIssue({
                    code: "custom",
                    message: (0, catalog_1.translate)(locale, "config.error.duplicateWorkflowLabelAfterTrim", { value: trimmedValue }),
                    path: ["ticketTracker", "workflowLabels", key],
                });
                continue;
            }
            seenWorkflowLabelValues.set(trimmedValue, key);
        }
    })
        .transform((config) => ({
        ...config,
        repositoryHost: {
            ...config.repositoryHost,
            pullRequest: normalizePullRequestConfig(config.repositoryHost.pullRequest),
        },
        ticketTracker: {
            ...config.ticketTracker,
            workflowLabels: (0, workflow_labels_1.resolveWorkflowLabels)(config.ticketTracker.workflowLabels),
        },
    }));
}
function isWorkspaceSetupWatchPathRepoRelative(value) {
    if (node_path_1.default.isAbsolute(value) || node_path_1.default.win32.isAbsolute(value)) {
        return false;
    }
    return !value
        .split(/[\\/]+/u)
        .some((segment) => segment === "." || segment === "..");
}
function isRepoRelativeConfigDirectoryPath(value) {
    if (value.length === 0 ||
        value.trim() !== value ||
        value.includes("\\") ||
        node_path_1.default.isAbsolute(value) ||
        node_path_1.default.win32.isAbsolute(value)) {
        return false;
    }
    if (node_path_1.default.posix.normalize(value) !== value) {
        return false;
    }
    return !value
        .split("/")
        .some((segment) => segment === "" || segment === "." || segment === "..");
}
function addDuplicateWorkerIssues(workers, path, context, locale) {
    const workerProviders = new Set();
    for (const worker of workers) {
        if (workerProviders.has(worker)) {
            context.addIssue({
                code: "custom",
                message: (0, catalog_1.translate)(locale, "config.error.duplicateWorkerProvider", {
                    worker,
                }),
                path,
            });
        }
        workerProviders.add(worker);
    }
}
function addUnknownWorkerIssues(workers, customWorkers, path, context, locale) {
    for (const worker of workers) {
        if (isBuiltInWorkerName(worker) || Object.hasOwn(customWorkers, worker)) {
            continue;
        }
        context.addIssue({
            code: "custom",
            message: (0, catalog_1.translate)(locale, "config.error.invalidIdentifier"),
            path,
        });
    }
}
function hasHeaderName(headers, headerName) {
    if (headers === undefined) {
        return false;
    }
    return Object.keys(headers).some((key) => key.toLowerCase() === headerName.toLowerCase());
}
function resolveConfigLocale(parsed) {
    if (!parsed || typeof parsed !== "object") {
        return catalog_1.DEFAULT_APP_LOCALE;
    }
    const defaultLanguage = parsed
        .i18n?.defaultLanguage;
    return (0, catalog_1.isAppLocale)(defaultLanguage) ? defaultLanguage : catalog_1.DEFAULT_APP_LOCALE;
}
