// engine/platform-engineering/dx-analyzer.ts — SPEC-048
// Analyzes Developer Experience gaps and generates audit findings for platform engineering.
// Detects missing CODEOWNERS, SECURITY.md, and reproducible dev environments.
import { access } from 'node:fs/promises';
import { join } from 'node:path';
async function fileExists(path) {
    try {
        await access(path);
        return true;
    }
    catch {
        return false;
    }
}
/**
 * Checks for CODEOWNERS file in standard locations.
 */
async function hasCodeowners(projectPath) {
    return ((await fileExists(join(projectPath, 'CODEOWNERS'))) ||
        (await fileExists(join(projectPath, '.github', 'CODEOWNERS'))) ||
        (await fileExists(join(projectPath, 'docs', 'CODEOWNERS'))));
}
/**
 * Checks for SECURITY.md with vulnerability disclosure policy.
 */
async function hasSecurityMd(projectPath) {
    return ((await fileExists(join(projectPath, 'SECURITY.md'))) ||
        (await fileExists(join(projectPath, '.github', 'SECURITY.md'))));
}
/**
 * Checks for reproducible dev environment (.devcontainer or flake.nix).
 */
async function hasReproducibleDevEnv(projectPath) {
    return ((await fileExists(join(projectPath, '.devcontainer'))) ||
        (await fileExists(join(projectPath, 'flake.nix'))) ||
        (await fileExists(join(projectPath, '.devcontainer.json'))));
}
/**
 * Checks for DORA metrics documentation (runbooks, incident procedures).
 */
async function hasDoraDocumentation(projectPath) {
    const indicatorPaths = [
        join(projectPath, 'runbooks'),
        join(projectPath, 'docs', 'runbooks'),
        join(projectPath, 'RUNBOOK.md'),
        join(projectPath, 'INCIDENT.md'),
        join(projectPath, 'docs', 'incident-response.md'),
    ];
    for (const p of indicatorPaths) {
        if (await fileExists(p)) {
            return true;
        }
    }
    return false;
}
/**
 * Checks for Backstage catalog entry (catalog-info.yaml).
 */
async function hasBackstageCatalogEntry(projectPath) {
    return ((await fileExists(join(projectPath, 'catalog-info.yaml'))) ||
        (await fileExists(join(projectPath, '.backstage', 'catalog-info.yaml'))));
}
/**
 * Generates DX audit findings for multi-team projects.
 * These are governance-level findings (warning severity, not critical).
 */
export async function analyzeDXGaps(projectPath, teamScale) {
    const findings = [];
    const [codeowners, securityMd, reproEnv, doraDocs] = await Promise.all([
        hasCodeowners(projectPath),
        hasSecurityMd(projectPath),
        hasReproducibleDevEnv(projectPath),
        hasDoraDocumentation(projectPath),
    ]);
    if (!codeowners) {
        findings.push({
            file: 'CODEOWNERS',
            category: 'quality',
            severity: 'warning',
            rule: 'platform-engineering/missing-codeowners',
            message: 'No CODEOWNERS file found — code ownership is not documented',
            suggestion: 'Add CODEOWNERS in root, .github/, or docs/. Define owners per directory for multi-team projects.',
            reference: 'https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners',
        });
    }
    if (!securityMd) {
        findings.push({
            file: 'SECURITY.md',
            category: 'security',
            severity: 'warning',
            rule: 'platform-engineering/missing-security-policy',
            message: 'No SECURITY.md found — vulnerability disclosure policy is not documented',
            suggestion: 'Add SECURITY.md with: how to report vulnerabilities, response SLA, and security contact.',
            reference: 'https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository',
        });
    }
    // Only warn about dev environment for multi-team or platform-engineering-candidate
    if (!reproEnv && (teamScale === 'multi-team' || teamScale === 'platform-engineering-candidate')) {
        findings.push({
            file: '.devcontainer',
            category: 'quality',
            severity: 'warning',
            rule: 'platform-engineering/no-reproducible-dev-env',
            message: 'No reproducible dev environment (.devcontainer or flake.nix) for multi-team project',
            suggestion: 'Add .devcontainer/ with devcontainer.json for VS Code Dev Containers, or flake.nix for Nix-based reproducible environments.',
            reference: 'https://containers.dev/',
        });
    }
    if (!doraDocs && teamScale === 'platform-engineering-candidate') {
        findings.push({
            file: 'runbooks/',
            category: 'quality',
            severity: 'warning',
            rule: 'platform-engineering/no-dora-baseline',
            message: 'Multi-squad project without DORA metrics documentation (runbooks, incident response)',
            suggestion: 'Add runbooks/ directory with incident response procedures. This is required for MTTR measurement.',
        });
    }
    return findings;
}
/**
 * Generates config health check findings for platform engineering governance.
 * Used by check_config_health equivalent checks.
 */
export async function checkPlatformGovernance(projectPath, teamScale) {
    if (teamScale !== 'multi-team' && teamScale !== 'platform-engineering-candidate') {
        return [];
    }
    const findings = [];
    const [codeowners, securityMd, reproEnv, backstageCatalog] = await Promise.all([
        hasCodeowners(projectPath),
        hasSecurityMd(projectPath),
        hasReproducibleDevEnv(projectPath),
        hasBackstageCatalogEntry(projectPath),
    ]);
    if (!codeowners) {
        findings.push({
            file: 'CODEOWNERS',
            category: 'quality',
            severity: 'warning',
            rule: 'governance/codeowners-missing',
            message: 'CODEOWNERS missing in multi-team project',
            suggestion: 'Add CODEOWNERS to define code ownership per directory',
        });
    }
    if (!securityMd) {
        findings.push({
            file: 'SECURITY.md',
            category: 'security',
            severity: 'warning',
            rule: 'governance/security-policy-missing',
            message: 'SECURITY.md missing — no vulnerability disclosure policy',
            suggestion: 'Add SECURITY.md with vulnerability reporting instructions',
        });
    }
    if (!reproEnv) {
        findings.push({
            file: '.devcontainer',
            category: 'quality',
            severity: 'warning',
            rule: 'governance/no-reproducible-dev-environment',
            message: 'No .devcontainer/ or flake.nix — dev environment is not reproducible',
            suggestion: 'Add .devcontainer/devcontainer.json for reproducible local setup',
            reference: 'https://containers.dev/',
        });
    }
    if (!backstageCatalog) {
        findings.push({
            file: 'catalog-info.yaml',
            category: 'quality',
            severity: 'info',
            rule: 'governance/backstage-catalog-missing',
            message: 'No Backstage catalog-info.yaml found',
            suggestion: 'Add catalog-info.yaml to register this service in the developer portal software catalog.',
            reference: 'https://backstage.io/docs/features/software-catalog/descriptor-format',
        });
    }
    return findings;
}
//# sourceMappingURL=dx-analyzer.js.map