// ---------------------------------------------------------------------------
// Contradiction patterns
// ---------------------------------------------------------------------------
const CONTRADICTION_PATTERNS = [
    {
        name: 'offline-vs-realtime',
        sideA: ['offline', 'offline-first', 'no internet', 'without internet', 'disconnected'],
        sideB: ['real-time', 'realtime', 'online', 'sync', 'synchronization', 'live', 'streaming'],
        severity: 'blocker',
        descriptionTemplate: '{specA} requires offline capability while {specB} requires real-time synchronization — these are mutually exclusive without explicit conflict resolution.',
        recommendation: 'Define a clear synchronization strategy: optimistic updates with eventual consistency, or restrict real-time features to connected mode only.',
    },
    {
        name: 'sync-vs-async',
        sideA: ['synchronous', 'blocking', 'sequential', 'serial'],
        sideB: ['asynchronous', 'async', 'non-blocking', 'concurrent', 'parallel', 'event-driven'],
        severity: 'warning',
        descriptionTemplate: '{specA} implies synchronous execution while {specB} implies asynchronous processing — mixing these requires careful interface design.',
        recommendation: 'Decide on a unified execution model. If both are needed, document clearly which parts are sync vs async and add adapters at boundaries.',
    },
    {
        name: 'simple-vs-complex',
        sideA: ['simple', 'minimal', 'lightweight', 'basic', 'mvp'],
        sideB: ['complex', 'enterprise', 'advanced', 'comprehensive', 'full-featured', 'sophisticated'],
        severity: 'warning',
        descriptionTemplate: '{specA} targets simplicity/MVP while {specB} targets enterprise complexity — these have opposing design priorities.',
        recommendation: 'Clarify which spec defines the North Star. Consider a phased approach: start minimal, extend to complex in a later iteration.',
    },
    {
        name: 'performance-vs-security',
        sideA: ['fast', 'performance', 'speed', 'low latency', 'optimized', 'cache'],
        sideB: ['security', 'encrypted', 'encryption', 'audit', 'compliant', 'zero-trust'],
        severity: 'warning',
        descriptionTemplate: '{specA} prioritizes performance while {specB} prioritizes security — these often create architectural tradeoffs.',
        recommendation: 'Define explicit performance budgets for security operations. Benchmark encryption overhead. Consider hardware acceleration for crypto.',
    },
    {
        name: 'local-vs-cloud',
        sideA: ['local', 'on-premise', 'self-hosted', 'air-gapped', 'desktop', 'embedded'],
        sideB: ['cloud', 'remote', 'saas', 'hosted', 'serverless', 'managed service'],
        severity: 'blocker',
        descriptionTemplate: '{specA} requires local/on-premise deployment while {specB} assumes cloud/remote infrastructure — these are incompatible deployment targets.',
        recommendation: 'Choose a single deployment model or build explicit abstraction layers that support both. Hybrid architectures significantly increase complexity.',
    },
];
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
/**
 * Check if content contains any keyword from the provided list.
 */
function containsAny(content, keywords) {
    const lower = content.toLowerCase();
    return keywords.some((kw) => lower.includes(kw.toLowerCase()));
}
/**
 * Build a contradiction description from a pattern and two spec IDs.
 */
function buildDescription(template, specA, specB) {
    return template.replace('{specA}', specA).replace('{specB}', specB);
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Detect semantic contradictions between a list of specs.
 * Each spec is compared against every other spec for all known patterns.
 */
export function detectContradictions(specs) {
    if (specs.length < 2) {
        return [];
    }
    const contradictions = [];
    for (let i = 0; i < specs.length; i++) {
        for (let j = i + 1; j < specs.length; j++) {
            const specA = specs[i];
            const specB = specs[j];
            // Guard — TypeScript noUncheckedIndexedAccess
            if (!specA || !specB) {
                continue;
            }
            const combinedA = `${specA.title} ${specA.content}`;
            const combinedB = `${specB.title} ${specB.content}`;
            for (const pattern of CONTRADICTION_PATTERNS) {
                const aHasSideA = containsAny(combinedA, pattern.sideA);
                const bHasSideB = containsAny(combinedB, pattern.sideB);
                const aHasSideB = containsAny(combinedA, pattern.sideB);
                const bHasSideA = containsAny(combinedB, pattern.sideA);
                if ((aHasSideA && bHasSideB) || (aHasSideB && bHasSideA)) {
                    // Determine which spec "owns" which side for accurate description
                    const [ownerA, ownerB] = aHasSideA && bHasSideB ? [specA.id, specB.id] : [specB.id, specA.id];
                    contradictions.push({
                        specA: ownerA,
                        specB: ownerB,
                        description: buildDescription(pattern.descriptionTemplate, ownerA, ownerB),
                        severity: pattern.severity,
                        recommendation: pattern.recommendation,
                        pattern: pattern.name,
                    });
                }
            }
        }
    }
    return contradictions;
}
/**
 * Build a full ConflictReport from a list of specs.
 */
export function buildConflictReport(specs) {
    const contradictions = detectContradictions(specs);
    const specsWithConflicts = [...new Set(contradictions.flatMap((c) => [c.specA, c.specB]))];
    const blockerCount = contradictions.filter((c) => c.severity === 'blocker').length;
    const warningCount = contradictions.filter((c) => c.severity === 'warning').length;
    let summary;
    if (contradictions.length === 0) {
        summary = 'No contradictions detected between specs.';
    }
    else if (blockerCount > 0) {
        summary = `${contradictions.length} contradiction(s) found — ${blockerCount} blocker(s) require immediate resolution before implementation.`;
    }
    else {
        summary = `${contradictions.length} contradiction(s) found — ${warningCount} warning(s) can coexist with tradeoffs but should be documented.`;
    }
    return {
        contradictions,
        summary,
        specsWithConflicts,
        blockerCount,
        warningCount,
    };
}
/**
 * Format a ConflictReport as a markdown string.
 */
export function formatConflictReport(report) {
    if (report.contradictions.length === 0) {
        return `## Contradiction Report\n\nNo contradictions detected between specs.`;
    }
    const lines = [
        `## Contradiction Report`,
        ``,
        `**Summary:** ${report.summary}`,
        `**Blockers:** ${report.blockerCount} | **Warnings:** ${report.warningCount}`,
        `**Specs with conflicts:** ${report.specsWithConflicts.join(', ')}`,
        ``,
        `---`,
        ``,
    ];
    for (const c of report.contradictions) {
        const icon = c.severity === 'blocker' ? '[BLOCKER]' : '[WARNING]';
        lines.push(`### ${icon} ${c.pattern} — ${c.specA} vs ${c.specB}`);
        lines.push(`**Description:** ${c.description}`);
        lines.push(`**Recommendation:** ${c.recommendation}`);
        lines.push(``);
    }
    return lines.join('\n');
}
//# sourceMappingURL=contradiction-detector.js.map