// engine/convention-injector.ts
// SPEC-230: Inject project-specific acceptance criteria based on scanned conventions.
// Reads conventions.json produced by SPEC-228 (project-scanner) and appends stack-specific
// ACs to every spec's acceptance criteria list.
/**
 * Appends stack-specific acceptance criteria to an existing list.
 * Based on language, testRunner, testLocation, errorHandling, and lintBaseline.
 * Gracefully skips any field with value 'unknown' or null.
 */
export function injectConventionCriteria(criteria, conventions) {
    const result = [...criteria];
    // --- Language-based criteria ---
    const lang = conventions.stack.language;
    if (lang === 'typescript') {
        result.push('- [ ] No TypeScript errors (tsc --noEmit passes)', '- [ ] New public functions have explicit return type annotations');
    }
    else if (lang === 'python') {
        result.push('- [ ] No mypy type errors', '- [ ] Follows PEP 8 style');
    }
    else if (lang === 'go') {
        result.push('- [ ] go vet passes with no errors', '- [ ] Error returns are explicitly handled');
    }
    else if (lang === 'rust') {
        result.push('- [ ] cargo clippy passes with no warnings');
    }
    // --- Test runner criteria ---
    const testRunner = conventions.stack.testRunner;
    if (testRunner === 'vitest' || testRunner === 'jest') {
        result.push('- [ ] New test file added for each new module');
    }
    else if (testRunner === 'pytest') {
        result.push('- [ ] pytest tests added for new functionality');
    }
    // --- Test location criteria ---
    const testLocation = conventions.conventions.testLocation;
    if (testLocation === 'separate') {
        result.push('- [ ] Test file located in tests/<module>.test.<ext>');
    }
    else if (testLocation === 'colocated') {
        result.push('- [ ] Test file co-located at src/<module>.test.<ext>');
    }
    // --- Error handling criteria ---
    const errorHandling = conventions.conventions.errorHandling;
    if (errorHandling === 'exceptions') {
        result.push('- [ ] Errors thrown as Error instances (not raw strings)');
    }
    else if (errorHandling === 'result-type') {
        result.push('- [ ] Functions return Result type — no exceptions thrown');
    }
    // --- Lint baseline criteria ---
    const lintWarnings = conventions.baseline.lintWarnings;
    if (lintWarnings !== null && lintWarnings > 0) {
        result.push(`- [ ] Lint warning count doesn't increase vs baseline (currently ${lintWarnings} warnings)`);
    }
    return result;
}
/**
 * Builds a YAML block string summarising the detected conventions.
 * Only includes fields that are not 'unknown' or null.
 */
export function buildConventionsFrontmatter(conventions) {
    const lines = ['conventions:'];
    const { fileNaming, testLocation, errorHandling } = conventions.conventions;
    const { lintWarnings } = conventions.baseline;
    if (fileNaming !== 'unknown') {
        lines.push(`  fileNaming: ${fileNaming}`);
    }
    if (testLocation !== 'unknown') {
        lines.push(`  testLocation: ${testLocation}`);
    }
    if (errorHandling !== 'unknown') {
        lines.push(`  errorHandling: ${errorHandling}`);
    }
    if (lintWarnings !== null) {
        lines.push(`  lintBaseline: ${lintWarnings}`);
    }
    // Return empty string if no meaningful fields were added (only header)
    if (lines.length === 1) {
        return '';
    }
    return lines.join('\n');
}
//# sourceMappingURL=convention-injector.js.map