/**
 * Registry of synced settings: the single map between `.lisa.config.json`
 * keys, their built-in defaults, and the project artifact files that mirror
 * them (test thresholds, lint budgets, mutation gates).
 *
 * The registry drives `lisa sync`: every entry is populated into the config
 * when missing (absorbing an existing artifact value first, falling back to
 * the built-in default), and afterwards the config value is written back into
 * each artifact file — config is the source of truth unless a value is
 * completely missing.
 * @module sync/registry
 */
import { validateHealthSchedule } from "../health/contract.js";
import { BUILD_LABEL_DEFAULTS, LINEAR_WORKFLOW_DEFAULTS, PRD_LABEL_DEFAULTS, } from "./lifecycle-defaults.js";
const WHEN_TRACKER_JIRA = "tracker=jira";
const WHEN_TRACKER_GITHUB = "tracker=github";
const WHEN_SOURCE_GITHUB = "source=github";
const WHEN_TRACKER_LINEAR = "tracker=linear";
const WHEN_SOURCE_LINEAR = "source=linear";
const WHEN_SOURCE_NOTION = "source=notion";
/**
 * Authoritative tracker/PRD-source setup requirements. Config sync and
 * read-only readiness consumers share this map so provider lanes cannot drift.
 */
export const SETUP_PROVIDER_REQUIREMENTS = {
    tracker: {
        github: {
            allOf: ["github.org", "github.repo"],
            setupHint: "/lisa:setup:github",
        },
        jira: {
            allOf: ["jira.project", "atlassian.cloudId"],
            setupHint: "/lisa:setup:jira",
        },
        linear: {
            allOf: ["linear.workspace", "linear.teamKey"],
            setupHint: "/lisa:setup:linear",
        },
    },
    source: {
        github: {
            allOf: ["github.org", "github.repo"],
            setupHint: "/lisa:setup:github",
        },
        notion: {
            allOf: ["notion.workspaceId", "notion.prdDatabaseId"],
            setupHint: "/lisa:setup:notion",
        },
        linear: {
            allOf: ["linear.workspace"],
            setupHint: "/lisa:setup:linear",
        },
        confluence: {
            allOf: ["atlassian.cloudId"],
            anyOf: ["confluence.spaceKey", "confluence.parentPageId"],
            setupHint: "/lisa:setup:confluence",
        },
    },
};
const COVERAGE_DEFAULTS = {
    global: { statements: 70, branches: 70, functions: 70, lines: 70 },
};
/**
 * All settings `lisa sync` manages. Local-only keys (`atlassian.email`,
 * `intake.assignee`, `jira.verified_workflow_hash`, secret paths) are
 * deliberately absent — sync never populates the committed file with values
 * that belong in `.lisa.config.local.json`.
 */
export const SYNC_REGISTRY = [
    {
        key: "harness",
        defaultValue: "claude",
        description: "Target coding-agent harness(es)",
    },
    {
        key: "health.schedule",
        defaultValue: "off",
        validate: validateHealthSchedule,
        description: "Health-check schedule (off, daily, or weekly)",
    },
    {
        key: "quality.testCoverage",
        defaultValue: COVERAGE_DEFAULTS,
        artifacts: [
            { file: "vitest.thresholds.json", pointer: "" },
            { file: "jest.thresholds.json", pointer: "" },
        ],
        description: "Test coverage floors (statements/branches/functions/lines)",
    },
    {
        key: "quality.e2eCoverage",
        defaultValue: { playwright: { routes: 80 }, maestro: { routes: 80 } },
        artifacts: [{ file: "e2e.thresholds.json", pointer: "" }],
        description: "E2E route/screen coverage floors (Playwright web routes, Maestro screens)",
    },
    {
        key: "quality.lintBudgets",
        defaultValue: {
            cognitiveComplexity: 10,
            maxLines: 300,
            maxLinesPerFunction: 75,
        },
        artifacts: [{ file: "eslint.thresholds.json", pointer: "" }],
        description: "Lint complexity and size budgets",
    },
    {
        key: "quality.mutation.gate",
        defaultValue: { enabled: false, since: "main" },
        artifacts: [{ file: "mutation.gate.json", pointer: "" }],
        description: "Diff-only mutation testing gate",
    },
    {
        key: "quality.mutation.strykerThresholds",
        defaultValue: { high: 80, low: 60, break: 60 },
        artifacts: [{ file: "stryker.conf.json", pointer: "thresholds" }],
        description: "Stryker mutation-score thresholds",
    },
    {
        key: "intake.repair",
        defaultValue: { staleAfterHours: 2, maxCandidates: 100 },
        description: "Repair-intake stall window and candidate cap",
    },
    {
        // Semantics documented in one place: the claim-archaeology rule pair
        // (plugins/src/base/rules/{eager,reference}/claim-archaeology.md).
        key: "archaeology",
        defaultValue: { maxSteps: 8 },
        description: "Claim-time archaeology cost budget (max tracker/git queries per claim)",
    },
    {
        key: "monitor",
        defaultValue: {
            maxCandidates: 20,
            gapTiers: "core",
            backoffHours: 24,
            // Provider-neutral threshold names: the audit spans Sentry, CloudWatch,
            // X-Ray, and future providers, so no key is prefixed with a vendor.
            thresholds: {
                minEvents24h: 1,
                errorRateSpikeMultiplier: 2,
                p95LatencyMs: 1000,
                faultRatePct: 5,
            },
        },
        legacyAliases: [
            {
                currentPath: "thresholds.minEvents24h",
                legacyPath: "thresholds.sentryMinEvents24h",
            },
            {
                currentPath: "thresholds.faultRatePct",
                legacyPath: "thresholds.xrayFaultRatePct",
            },
        ],
        description: "Observability audit caps and alert thresholds",
    },
    {
        key: "jira.workflow",
        defaultValue: {
            ready: "Ready",
            claimed: "In Progress",
            review: "Code Review",
            blocked: "Blocked",
            done: { dev: "On Dev", staging: "On Stg", production: "Done" },
        },
        relevantWhen: ["jira", WHEN_TRACKER_JIRA],
        description: "JIRA workflow status names per lifecycle role",
    },
    {
        key: "jira.labels",
        defaultValue: { human_needed: "Human Needed" },
        relevantWhen: ["jira", WHEN_TRACKER_JIRA],
        description: "JIRA marker labels",
    },
    {
        key: "github.labels",
        defaultValue: { build: BUILD_LABEL_DEFAULTS, prd: PRD_LABEL_DEFAULTS },
        relevantWhen: ["github", WHEN_TRACKER_GITHUB, WHEN_SOURCE_GITHUB],
        description: "GitHub build and PRD lifecycle labels",
    },
    {
        key: "linear.workflow",
        defaultValue: LINEAR_WORKFLOW_DEFAULTS,
        relevantWhen: ["linear", WHEN_TRACKER_LINEAR],
        description: "Linear workflow state names per build lifecycle role",
    },
    {
        // Markers and the PRD lane only. The build lane moved to `linear.workflow`
        // — see LINEAR_WORKFLOW_DEFAULTS. `human_needed` stays a LABEL for the same
        // reason it does on JIRA: an Issue holds exactly one state but any number
        // of labels, so an additive marker cannot be a state. The PRD lane stays
        // labels because it rides on Linear PROJECTS, whose status model is a
        // separate object from Issue workflow states.
        key: "linear.labels",
        defaultValue: {
            build: { human_needed: BUILD_LABEL_DEFAULTS.human_needed },
            prd: PRD_LABEL_DEFAULTS,
        },
        relevantWhen: ["linear", WHEN_TRACKER_LINEAR, WHEN_SOURCE_LINEAR],
        description: "Linear marker labels and PRD lifecycle labels",
    },
    {
        key: "notion.statusProperty",
        defaultValue: "Status",
        relevantWhen: ["notion", WHEN_SOURCE_NOTION],
        description: "Notion database property that drives the PRD lifecycle",
    },
    {
        key: "notion.values",
        defaultValue: {
            draft: "Draft",
            ready: "Ready",
            in_review: "In Review",
            blocked: "Blocked",
            ticketed: "Ticketed",
            shipped: "Shipped",
            verified: "Verified",
        },
        relevantWhen: ["notion", WHEN_SOURCE_NOTION],
        description: "Notion status option names per lifecycle role",
    },
    {
        key: "wiki.ttlSeconds",
        defaultValue: 300,
        relevantWhen: ["wiki"],
        description: "Remote wiki mirror refresh TTL",
    },
];
/**
 * Keys sync can never default: they identify external systems and must come
 * from a human (via the matching `/lisa:setup:*` skill). Sync reports them
 * when missing instead of inventing values.
 */
export const REQUIRED_KEYS = [
    { key: "tracker", setupHint: "/lisa:setup:jira | github | linear" },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.tracker.jira.allOf[0],
        relevantWhen: [WHEN_TRACKER_JIRA],
        setupHint: SETUP_PROVIDER_REQUIREMENTS.tracker.jira.setupHint,
    },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.tracker.jira.allOf[1],
        relevantWhen: [WHEN_TRACKER_JIRA, "source=confluence"],
        setupHint: "/lisa:setup:atlassian",
    },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.tracker.github.allOf[0],
        relevantWhen: [WHEN_TRACKER_GITHUB, WHEN_SOURCE_GITHUB],
        setupHint: SETUP_PROVIDER_REQUIREMENTS.tracker.github.setupHint,
    },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.tracker.github.allOf[1],
        relevantWhen: [WHEN_TRACKER_GITHUB, WHEN_SOURCE_GITHUB],
        setupHint: SETUP_PROVIDER_REQUIREMENTS.tracker.github.setupHint,
    },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.tracker.linear.allOf[0],
        relevantWhen: [WHEN_TRACKER_LINEAR, WHEN_SOURCE_LINEAR],
        setupHint: SETUP_PROVIDER_REQUIREMENTS.tracker.linear.setupHint,
    },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.tracker.linear.allOf[1],
        relevantWhen: [WHEN_TRACKER_LINEAR],
        setupHint: SETUP_PROVIDER_REQUIREMENTS.tracker.linear.setupHint,
    },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.source.notion.allOf[0],
        relevantWhen: [WHEN_SOURCE_NOTION],
        setupHint: SETUP_PROVIDER_REQUIREMENTS.source.notion.setupHint,
    },
    {
        key: SETUP_PROVIDER_REQUIREMENTS.source.notion.allOf[1],
        relevantWhen: [WHEN_SOURCE_NOTION],
        setupHint: SETUP_PROVIDER_REQUIREMENTS.source.notion.setupHint,
    },
];
//# sourceMappingURL=registry.js.map