const GUARDED_DOMAINS = [
    {
        name: 'billing',
        requestPattern: /\b(billing|payment|payments|paid|checkout|stripe|subscription|pricing)\b/i,
        specPattern: /\b(billing|payment|payments|checkout|stripe|subscription|pricing)\b/i,
    },
    {
        name: 'authentication',
        requestPattern: /\b(auth|authentication|authorization|login|jwt|oauth|session)\b/i,
        specPattern: /\b(auth|authentication|authorization|login|jwt|oauth|session|401|403)\b/i,
    },
    {
        name: 'database',
        requestPattern: /\b(database|schema|rls|rpc|persistence|persist|query|migration)\b/i,
        specPattern: /\b(database|schema|rls|rpc|persistence|persist|query|migration)\b/i,
    },
    {
        name: 'ui',
        requestPattern: /\b(ui|frontend|component|screen|page|form|layout|style|styling)\b/i,
        specPattern: /\b(ui|frontend|component|screen|page|form|layout|style|styling)\b/i,
    },
];
const PATH_LIKE_DOMAIN_RE = /\b(?:stores|store|modules|features|apps|packages|src)\/([a-z][\w-]*)/gi;
const INVENTED_STATUS_RE = /\b(?:(?:endpoints?|api|routes?|response|status)\b[^.\n]*(?:401|403|404|500)|(?:401|403|404|500)\b[^.\n]*(?:endpoints?|api|routes?|response|status))\b/i;
const GENERIC_COVERAGE_RE = /\b(?:coverage|test coverage)\b/i;
export function evaluateSpecAssurance(input) {
    const findings = [];
    const request = input.originalRequest;
    const spec = input.generatedSpec;
    findings.push(...findUnrequestedDomains(request, spec));
    findings.push(...findInventedEndpointRequirements(request, spec));
    findings.push(...findGenericCoverageRequirement(request, spec));
    findings.push(...findPathDerivedAssumptions(request, spec));
    return {
        passed: findings.every((finding) => finding.severity !== 'error'),
        findings,
    };
}
function findUnrequestedDomains(request, spec) {
    const findings = [];
    for (const domain of GUARDED_DOMAINS) {
        if (isDomainRequested(domain, request) || !domain.specPattern.test(spec)) {
            continue;
        }
        findings.push({
            rule: `ai-spec-unrequested-${domain.name}`,
            severity: 'error',
            message: `Generated spec introduced ${domain.name} requirements that are not present in the user request.`,
            evidence: firstMatch(spec, domain.specPattern),
        });
    }
    return findings;
}
function findInventedEndpointRequirements(request, spec) {
    if (/\b(api|endpoint|route|http|status|401|403|404|500)\b/i.test(request)) {
        return [];
    }
    if (!INVENTED_STATUS_RE.test(spec)) {
        return [];
    }
    return [
        {
            rule: 'ai-spec-invented-endpoint-status',
            severity: 'error',
            message: 'Generated spec introduced endpoint/status-code behavior not present in the user request.',
            evidence: firstMatch(spec, INVENTED_STATUS_RE),
        },
    ];
}
function findGenericCoverageRequirement(request, spec) {
    if (GENERIC_COVERAGE_RE.test(request) || !GENERIC_COVERAGE_RE.test(spec)) {
        return [];
    }
    return [
        {
            rule: 'ai-spec-generic-coverage',
            severity: 'error',
            message: 'Generated spec introduced a generic coverage requirement not tied to the requested behavior.',
            evidence: firstMatch(spec, GENERIC_COVERAGE_RE),
        },
    ];
}
function findPathDerivedAssumptions(request, spec) {
    const findings = [];
    const pathTokens = new Set();
    for (const match of request.matchAll(PATH_LIKE_DOMAIN_RE)) {
        const token = match[1]?.toLowerCase();
        if (token) {
            pathTokens.add(token);
        }
    }
    if (pathTokens.size === 0) {
        return findings;
    }
    for (const token of pathTokens) {
        const domain = GUARDED_DOMAINS.find((candidate) => candidate.name === token);
        if (!domain || isDomainRequested(domain, stripPathLikeSegments(request))) {
            continue;
        }
        if (!domain.specPattern.test(spec)) {
            continue;
        }
        findings.push({
            rule: 'ai-spec-path-derived-assumption',
            severity: 'error',
            message: `Generated spec appears to derive ${token} requirements from an incidental repository path.`,
            evidence: firstMatch(request, PATH_LIKE_DOMAIN_RE),
        });
    }
    return findings;
}
function isDomainRequested(domain, request) {
    const requestWithoutPaths = stripPathLikeSegments(request);
    if (!domain.requestPattern.test(requestWithoutPaths)) {
        return false;
    }
    const domainTerms = domain.specPattern.source
        .replaceAll('\\b', '')
        .replace(/[()?:]/g, '')
        .split('|')
        .filter((term) => /^[a-z]+$/i.test(term));
    for (const term of domainTerms) {
        const negated = new RegExp(`\\b${term}\\b[^.\\n]*(?:not in scope|out of scope|not required|not part of scope|negative example)`, 'i');
        if (negated.test(requestWithoutPaths)) {
            return false;
        }
    }
    return true;
}
function stripPathLikeSegments(value) {
    return value.replace(PATH_LIKE_DOMAIN_RE, ' ');
}
function firstMatch(value, pattern) {
    const flags = pattern.flags.includes('g') ? pattern.flags : `${pattern.flags}g`;
    const match = new RegExp(pattern.source, flags).exec(value);
    return match?.[0]?.trim() ?? '';
}
//# sourceMappingURL=spec-assurance.js.map