/**
 * @internal
 * consistency/rules/r1-ac-coverage.mjs — R1 (C15).
 *
 * Every AC in spec.md must be referenced by at least one subtask in
 * implementation_plan.json via `subtask.acceptance_criteria` — either the
 * canonical id ("AC3", case-insensitive) or the full AC text as a verbatim
 * substring.
 *
 * Severity: error.
 * Stages: execute, verify, review, ship.
 * Skip when: spec has 0 ACs OR plan has 0 subtasks.
 */
import { registerRule } from '../registry.mjs';
const rule = {
    id: 'r1-ac-coverage',
    severity: 'error',
    stages: ['execute', 'verify', 'review', 'ship'],
    description: 'Every spec.md acceptance criterion is referenced by ≥1 subtask.',
    async check({ parsed }) {
        const acs = parsed?.spec?.acs ?? [];
        const subtasks = parsed?.plan?.subtasks ?? [];
        if (acs.length === 0) {
            return { status: 'skip', drift: [], reason: 'spec.md has no acceptance criteria' };
        }
        if (subtasks.length === 0) {
            return {
                status: 'skip',
                drift: [],
                reason: 'implementation_plan.json has no subtasks',
            };
        }
        const drift = [];
        for (const ac of acs) {
            const idLower = ac.id.toLowerCase();
            const text = ac.text;
            const matched = subtasks.some((s) => (s.acceptance_criteria ?? []).some((ref) => {
                if (typeof ref !== 'string')
                    return false;
                if (ref.toLowerCase() === idLower)
                    return true;
                if (text && ref.includes(text))
                    return true;
                return false;
            }));
            if (!matched) {
                drift.push({ ac_id: ac.id, ac_text: ac.text, reason: 'no subtask references it' });
            }
        }
        if (drift.length > 0) {
            return {
                status: 'fail',
                drift,
                reason: `${drift.length} of ${acs.length} acceptance criteria not mapped to any subtask`,
            };
        }
        return {
            status: 'pass',
            drift: [],
            reason: `all ${acs.length} acceptance criteria mapped`,
        };
    },
};
registerRule(rule);
export default rule;
//# sourceMappingURL=r1-ac-coverage.mjs.map