const GENERIC_CRITERION_PATTERNS = [
    /\bimplementation complete\b/i,
    /\bcomplete and tested\b/i,
    /\bensure (adequate )?coverage\b/i,
    /\ball edge cases\b/i,
    /\bgeneric validation\b/i,
    /\bautopilot could not infer testable behavior\b/i,
    /\bdefine acceptance criteria\b/i,
];
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---/;
export function normalizeCriterionText(text) {
    return text
        .replace(/^[-*]\s*\[[ xX]\]\s*/, '')
        .replace(/\s+/g, ' ')
        .trim()
        .toLowerCase();
}
export function isGenericCriterion(text) {
    return GENERIC_CRITERION_PATTERNS.some((pattern) => pattern.test(text));
}
export function filterGroundedCriteria(criteria) {
    return criteria.filter((criterion) => criterion.trim().length > 0 && !isGenericCriterion(criterion));
}
export function buildCriterionGroundingRecords(args) {
    const userInput = normalizeCriterionText(args.userInput);
    const projectEvidence = args.projectEvidence ?? [];
    const generatedEvidence = args.generatedEvidence ?? [];
    return args.criteria.map((criterion) => {
        const normalized = normalizeCriterionText(criterion);
        if (isGenericCriterion(criterion)) {
            return {
                text: criterion,
                source: 'ungrounded_advisory',
                evidence: [],
                confidence: 'low',
            };
        }
        if (normalized.length > 0 && userInput.includes(normalized)) {
            return {
                text: criterion,
                source: 'user_input',
                evidence: ['create_spec.description'],
                confidence: 'high',
            };
        }
        if (projectEvidence.length > 0) {
            return {
                text: criterion,
                source: 'project_evidence',
                evidence: projectEvidence.slice(0, 8),
                confidence: 'medium',
            };
        }
        return {
            text: criterion,
            source: 'documented_assumption',
            evidence: generatedEvidence.length > 0 ? generatedEvidence.slice(0, 4) : ['generated-spec-body'],
            confidence: 'medium',
        };
    });
}
export function getContractCriteria(records) {
    return records.filter((record) => record.source === 'user_input' || record.source === 'project_evidence');
}
export function getAdvisoryCriteria(records) {
    return records.filter((record) => record.source === 'documented_assumption' || record.source === 'ungrounded_advisory');
}
export function renderGroundingFrontmatter(records) {
    if (records.length === 0) {
        return ['grounding_required: true', 'grounding:', '  criteria: []'];
    }
    return [
        'grounding_required: true',
        'grounding:',
        '  criteria:',
        ...records.flatMap((record) => [
            `    - text: "${escapeYaml(record.text)}"`,
            `      source: ${record.source}`,
            `      evidence: [${record.evidence.map((item) => `"${escapeYaml(item)}"`).join(', ')}]`,
            `      confidence: ${record.confidence}`,
        ]),
    ];
}
export function renderTechnicalReferenceGroundingFrontmatter(records) {
    if (records.length === 0) {
        return ['  technicalReferences: []'];
    }
    return [
        '  technicalReferences:',
        ...records.flatMap((record) => [
            `    - path: "${escapeYaml(record.path)}"`,
            `      section: ${record.section}`,
            `      source: ${record.source}`,
            `      evidence: [${record.evidence.map((item) => `"${escapeYaml(item)}"`).join(', ')}]`,
            `      confidence: ${record.confidence}`,
        ]),
    ];
}
export function checkGroundedSpecContract(spec, content) {
    const frontmatter = FRONTMATTER_RE.exec(content)?.[1] ?? '';
    const required = /^grounding_required:\s*true\s*$/m.test(frontmatter);
    const records = parseCriterionGroundingRecords(frontmatter);
    if (!required) {
        return { passed: true, required: false, issues: [], records };
    }
    const issues = [];
    if (records.length === 0 && spec.scope !== 'trivial') {
        issues.push(`Spec ${spec.id} requires grounding metadata but has no grounded criteria records.`);
    }
    for (const record of records) {
        if (record.source === 'ungrounded_advisory') {
            issues.push(`Criterion is advisory-only and cannot be approved as contract: ${record.text}`);
        }
        if (record.evidence.length === 0 && record.source !== 'ungrounded_advisory') {
            issues.push(`Criterion has no grounding evidence: ${record.text}`);
        }
    }
    const technicalRecords = parseTechnicalReferenceGroundingRecords(frontmatter);
    for (const record of technicalRecords) {
        if (record.source === 'ungrounded_advisory') {
            issues.push(`Technical reference is advisory-only and cannot be contract: ${record.path}`);
        }
        if (record.evidence.length === 0 && record.source !== 'ungrounded_advisory') {
            issues.push(`Technical reference has no grounding evidence: ${record.path}`);
        }
    }
    return {
        passed: issues.length === 0,
        required: true,
        issues,
        records,
    };
}
export function parseCriterionGroundingRecords(frontmatter) {
    const records = [];
    const chunks = frontmatter.split(/\n\s{4}- text:\s*/).slice(1);
    for (const chunk of chunks) {
        const text = /^"((?:\\"|[^"])*)"/.exec(chunk)?.[1]?.replace(/\\"/g, '"') ?? '';
        const source = /^\s{6}source:\s*(\S+)/m.exec(chunk)?.[1];
        const confidence = /^\s{6}confidence:\s*(\S+)/m.exec(chunk)?.[1];
        const evidenceRaw = /^\s{6}evidence:\s*\[(.*)\]/m.exec(chunk)?.[1] ?? '';
        if (!text || !source || !confidence) {
            continue;
        }
        records.push({
            text,
            source,
            evidence: parseYamlInlineStringArray(evidenceRaw),
            confidence,
        });
    }
    return records;
}
export function parseTechnicalReferenceGroundingRecords(frontmatter) {
    const records = [];
    const chunks = frontmatter.split(/\n\s{4}- path:\s*/).slice(1);
    for (const chunk of chunks) {
        const path = /^"((?:\\"|[^"])*)"/.exec(chunk)?.[1]?.replace(/\\"/g, '"') ?? '';
        const section = /^\s{6}section:\s*(\S+)/m.exec(chunk)?.[1];
        const source = /^\s{6}source:\s*(\S+)/m.exec(chunk)?.[1];
        const confidence = /^\s{6}confidence:\s*(\S+)/m.exec(chunk)?.[1];
        const evidenceRaw = /^\s{6}evidence:\s*\[(.*)\]/m.exec(chunk)?.[1] ?? '';
        if (!path || !section || !source || !confidence) {
            continue;
        }
        records.push({
            path,
            section,
            source,
            evidence: parseYamlInlineStringArray(evidenceRaw),
            confidence,
        });
    }
    return records;
}
function parseYamlInlineStringArray(raw) {
    if (raw.trim().length === 0) {
        return [];
    }
    const matches = raw.matchAll(/"((?:\\"|[^"])*)"/g);
    return [...matches].map((match) => match[1]?.replace(/\\"/g, '"') ?? '').filter(Boolean);
}
function escapeYaml(value) {
    return value.replace(/"/g, '\\"');
}
//# sourceMappingURL=contract.js.map