// engine/detectors/dx-score.ts — Developer Experience (DX) health score computation (SPEC-026a)
// Computes a 0-100 score based on CI/CD, testing, observability, deployment, code quality,
// documentation, and security coverage.
// === Category weights (must sum to 100) ===
const CATEGORY_WEIGHTS = {
    ciCd: 20,
    testing: 20,
    observability: 15,
    deployment: 15,
    codeQuality: 15,
    documentation: 10,
    security: 5,
};
// === Public API ===
/**
 * Computes a DX health score from detected project signals.
 * Each category scores 0-100; final score is weighted average.
 */
export function computeDxScore(completeness, ciCd, deployment, monitoring) {
    const categories = {
        ciCd: scoreCiCd(ciCd),
        testing: scoreTesting(completeness, ciCd),
        observability: scoreObservability(monitoring),
        deployment: scoreDeployment(deployment),
        codeQuality: scoreCodeQuality(completeness),
        documentation: scoreDocumentation(completeness),
        security: scoreSecurity(completeness, ciCd),
    };
    const score = Math.round((categories.ciCd * CATEGORY_WEIGHTS.ciCd +
        categories.testing * CATEGORY_WEIGHTS.testing +
        categories.observability * CATEGORY_WEIGHTS.observability +
        categories.deployment * CATEGORY_WEIGHTS.deployment +
        categories.codeQuality * CATEGORY_WEIGHTS.codeQuality +
        categories.documentation * CATEGORY_WEIGHTS.documentation +
        categories.security * CATEGORY_WEIGHTS.security) /
        100);
    const gaps = buildGaps(completeness, ciCd, deployment, monitoring, categories);
    const recommendations = buildRecommendations(gaps);
    return { score, categories, gaps, recommendations };
}
// === Category scorers ===
function scoreCiCd(ciCd) {
    if (ciCd.platform === null) {
        return 0;
    }
    let score = 40; // has CI/CD
    if (ciCd.hasTestStage) {
        score += 20;
    }
    if (ciCd.hasLintStage) {
        score += 15;
    }
    if (ciCd.hasDeployStage) {
        score += 15;
    }
    if (ciCd.hasDependencyAudit) {
        score += 10;
    }
    return Math.min(score, 100);
}
function scoreTesting(completeness, ciCd) {
    let score = 0;
    if (completeness.hasTesting) {
        score += 60;
    }
    if (ciCd.hasTestStage) {
        score += 25;
    }
    if (completeness.hasSeedData) {
        score += 15; // fixtures imply integration tests
    }
    return Math.min(score, 100);
}
function scoreObservability(monitoring) {
    const { detected } = monitoring;
    let score = 0;
    if (detected.errorTracking.length > 0) {
        score += 30;
    }
    if (detected.logging.length > 0) {
        score += 20;
    }
    if (detected.metrics.length > 0) {
        score += 20;
    }
    if (detected.tracing.length > 0) {
        score += 15;
    }
    if (detected.alerting.length > 0) {
        score += 10;
    }
    if (monitoring.hasSlo) {
        score += 5;
    }
    return Math.min(score, 100);
}
function scoreDeployment(deployment) {
    let score = 0;
    if (deployment.targets.length > 0) {
        score += 40;
    }
    if (deployment.hasInfraAsCode) {
        score += 30;
    }
    if (deployment.hasDockerCompose || deployment.hasKubernetes) {
        score += 20;
    }
    if (deployment.hasHelmChart) {
        score += 10;
    }
    return Math.min(score, 100);
}
function scoreCodeQuality(completeness) {
    let score = 0;
    if (completeness.hasLinting) {
        score += 35;
    }
    if (completeness.hasFormatting) {
        score += 20;
    }
    if (completeness.hasTypeChecking) {
        score += 25;
    }
    if (completeness.hasEditorConfig) {
        score += 10;
    }
    if (completeness.hasChangelogStrategy) {
        score += 10;
    }
    return Math.min(score, 100);
}
function scoreDocumentation(completeness) {
    let score = 0;
    if (completeness.hasReadme) {
        score += 35;
    }
    if (completeness.hasDocumentation) {
        score += 30;
    }
    if (completeness.hasContributing) {
        score += 20;
    }
    if (completeness.hasEnvExample) {
        score += 15;
    }
    return Math.min(score, 100);
}
function scoreSecurity(completeness, ciCd) {
    let score = 0;
    if (completeness.hasSecurityScanning) {
        score += 40;
    }
    if (ciCd.hasDependencyAudit) {
        score += 40;
    }
    if (completeness.hasLicense) {
        score += 20;
    }
    return Math.min(score, 100);
}
// === Gap and recommendation builders ===
function buildGaps(completeness, ciCd, deployment, monitoring, categories) {
    const gaps = [];
    if (categories.ciCd < 40) {
        gaps.push('No CI/CD pipeline detected');
    }
    else if (!ciCd.hasTestStage) {
        gaps.push('CI/CD pipeline has no automated test stage');
    }
    if (!completeness.hasTesting) {
        gaps.push('No testing framework configured');
    }
    if (categories.observability < 30) {
        gaps.push('No observability/error tracking tools detected');
    }
    if (monitoring.detected.errorTracking.length === 0) {
        gaps.push('No error tracking tool detected (Sentry, Bugsnag, Rollbar)');
    }
    if (deployment.targets.length === 0) {
        gaps.push('No deployment configuration detected');
    }
    if (!deployment.hasInfraAsCode) {
        gaps.push('No Infrastructure as Code (Terraform, Pulumi, CDK) detected');
    }
    if (!completeness.hasLinting) {
        gaps.push('No linter configured');
    }
    if (!completeness.hasSecurityScanning && !ciCd.hasDependencyAudit) {
        gaps.push('No security scanning or dependency audit configured');
    }
    if (!completeness.hasReadme) {
        gaps.push('No README.md found');
    }
    return gaps;
}
function buildRecommendations(gaps) {
    const recommendations = [];
    for (const gap of gaps) {
        if (gap.includes('CI/CD pipeline detected')) {
            recommendations.push('Add GitHub Actions: create .github/workflows/ci.yml with lint, test, and deploy jobs');
        }
        else if (gap.includes('test stage')) {
            recommendations.push('Add a test job to CI: run vitest/pytest/jest in your pipeline');
        }
        else if (gap.includes('testing framework')) {
            recommendations.push('Install a testing framework: vitest (TypeScript), pytest (Python), or Jest (JavaScript)');
        }
        else if (gap.includes('error tracking')) {
            recommendations.push('Add Sentry: npm install @sentry/node, initialize in your app entry point');
        }
        else if (gap.includes('observability')) {
            recommendations.push('Add OpenTelemetry: npm install @opentelemetry/sdk-node for metrics, tracing, and logging');
        }
        else if (gap.includes('deployment configuration')) {
            recommendations.push('Add a deployment config: vercel.json, fly.toml, or Kubernetes manifests');
        }
        else if (gap.includes('Infrastructure as Code')) {
            recommendations.push('Add Terraform or Pulumi to manage infrastructure as code');
        }
        else if (gap.includes('linter')) {
            recommendations.push('Add ESLint/Biome for TypeScript/JavaScript or ruff for Python');
        }
        else if (gap.includes('security')) {
            recommendations.push('Add SNYK or GitHub Dependabot for dependency vulnerability scanning');
        }
        else if (gap.includes('README')) {
            recommendations.push('Create a README.md documenting project setup, usage, and contribution guidelines');
        }
    }
    return recommendations;
}
//# sourceMappingURL=dx-score.js.map