/**
 * @internal
 * constitution/coverage.mjs — compose parse + match into a single
 * `checkCoverage({ agentsPath, specPath })` API (C14 subtask 3).
 *
 * Envelope:
 *   {
 *     status:    'pass' | 'fail' | 'skip',
 *     principles: Array<Principle & Match>,
 *     summary:   { total, covered, na, missing },
 *     reason:    string,
 *   }
 *
 * `skip` cases (both non-failing — the gate layer maps them to `skip`):
 *   - AGENTS.md absent         → reason "no constitution — greenfield"
 *   - spec.md absent           → reason "spec.md not yet produced"
 *
 * `fail` cases:
 *   - any principle is `missing`
 *
 * `pass` cases:
 *   - all principles are `covered` or `na` (or the AGENTS.md file contained
 *     no parseable principles — vacuously satisfied; we emit `pass` with a
 *     "no principles extracted" reason so the caller can distinguish).
 */
import { existsSync, readFileSync } from 'node:fs';
import { matchPrinciple } from './match.mjs';
import { parseAgentsMd } from './parse.mjs';
/**
 * Run the full constitution coverage check.
 *
 * @param {{ agentsPath: string, specPath: string }} args
 * @returns {{
 *   status: 'pass' | 'fail' | 'skip',
 *   principles: Array<object>,
 *   summary: { total: number, covered: number, na: number, missing: number },
 *   reason: string,
 * }}
 */
export function checkCoverage({ agentsPath, specPath }) {
    if (!agentsPath || !existsSync(agentsPath)) {
        return {
            status: 'skip',
            principles: [],
            summary: { total: 0, covered: 0, na: 0, missing: 0 },
            reason: 'no constitution — greenfield',
        };
    }
    const agentsMd = readFileSync(agentsPath, 'utf-8');
    const principles = parseAgentsMd(agentsMd);
    if (principles.length === 0) {
        return {
            status: 'pass',
            principles: [],
            summary: { total: 0, covered: 0, na: 0, missing: 0 },
            reason: 'no principles extracted from AGENTS.md',
        };
    }
    if (!specPath || !existsSync(specPath)) {
        return {
            status: 'skip',
            principles: [],
            summary: { total: principles.length, covered: 0, na: 0, missing: 0 },
            reason: 'spec.md not yet produced',
        };
    }
    const specMd = readFileSync(specPath, 'utf-8');
    let covered = 0;
    let na = 0;
    let missing = 0;
    const out = [];
    for (const p of principles) {
        const m = matchPrinciple(p, specMd);
        if (m.status === 'covered')
            covered++;
        else if (m.status === 'na')
            na++;
        else
            missing++;
        out.push({
            id: p.id,
            title: p.title,
            severity: p.severity,
            source: p.source,
            status: m.status,
            evidence: m.evidence,
        });
    }
    const summary = { total: principles.length, covered, na, missing };
    if (missing > 0) {
        return {
            status: 'fail',
            principles: out,
            summary,
            reason: `${missing} of ${principles.length} principle(s) not addressed in spec.md`,
        };
    }
    return {
        status: 'pass',
        principles: out,
        summary,
        reason: `all ${principles.length} principle(s) covered (${covered} covered, ${na} N/A)`,
    };
}
//# sourceMappingURL=coverage.mjs.map