// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// tools/create-spec/autopilot-analyzer.ts — SPEC-461 Phase 3: Autopilot analysis for create_spec
// Analyzes project code to suggest real files, detect patterns, and enrich specs automatically.
import { relative, extname } from 'node:path';
import { detectTrivial } from '../../engine/complexity-budget/index.js';
import { extractKeywords as extractKeywordsScorer, findRelevantFiles } from './relevance-scorer.js';
/** Return an empty/default AutopilotAnalysis when analysis is unavailable or timed out. */
export function getEmptyAutopilotResult() {
    return {
        suggestedFiles: { create: [], modify: [], test: [] },
        detectedPatterns: [],
        suggestedCriteria: [],
        isIdea: false,
        needsClarification: false,
    };
}
/**
 * Analyze the project to enrich a spec with real file paths and patterns.
 * Runs automatically during create_spec — no user interaction needed.
 */
export async function analyzeProjectForSpec(projectPath, description, title, knowledge) {
    const result = {
        suggestedFiles: { create: [], modify: [], test: [] },
        detectedPatterns: [],
        suggestedCriteria: [],
        isIdea: false,
        needsClarification: false,
    };
    const wordCount = description.trim().split(/\s+/).length;
    // SPEC-614: trivial detector — ≤5 words with no tech terms → capture as backlog idea
    const trivial = detectTrivial(description);
    if (trivial.isTrivial) {
        result.isIdea = true;
        return result;
    }
    // AC3 (SPEC-619): clarification needed when <20 words and no technical terms
    if (wordCount < 20 && !hasTechnicalTerms(description)) {
        result.needsClarification = true;
    }
    // AC1 (SPEC-619): broad-scope check — 2+ major subsystems → always clarify
    if (!result.needsClarification && detectBroadScope(description)) {
        result.needsClarification = true;
    }
    // SPEC-778: Extract keywords and find semantically relevant files only
    const keywords = extractKeywordsScorer(`${title} ${description}`);
    // Scan project files to find semantically related ones
    try {
        const relatedFiles = await findRelevantFiles(projectPath, keywords, 10);
        if (relatedFiles.length === 0) {
            result.noRelatedFilesMessage =
                'No related files detected — please populate ## Technical manually';
        }
        else {
            result.suggestedFiles.modify = relatedFiles.map((f) => ({
                path: relative(projectPath, f),
                status: 'pending',
            }));
            // Suggest test files based on modify files
            for (const f of result.suggestedFiles.modify) {
                const testPath = inferTestPath(f.path);
                if (testPath) {
                    result.suggestedFiles.test.push({ path: testPath, status: 'pending' });
                }
            }
        }
    }
    catch {
        // Best-effort — file scanning failure doesn't block spec creation
    }
    // Detect stack patterns and suggest relevant criteria
    if (knowledge) {
        result.detectedPatterns = detectPatterns(knowledge, description);
    }
    return result;
}
/** Check if description contains technical terms (stack, framework, or code references). */
function hasTechnicalTerms(description) {
    const techTerms = [
        /\b(api|endpoint|route|handler|middleware|controller)\b/i,
        /\b(database|schema|migration|table|query|sql)\b/i,
        /\b(component|hook|state|props|render)\b/i,
        /\b(auth|login|session|token|jwt|oauth)\b/i,
        /\b(test|spec|coverage|mock|stub)\b/i,
        /\b(deploy|ci|cd|docker|kubernetes)\b/i,
        /\b(supabase|firebase|prisma|drizzle)\b/i,
        /\b(react|next|vue|angular|svelte)\b/i,
        /\b(express|fastapi|django|spring|rails)\b/i,
        /\.\w{2,4}\b/, // file extensions like .ts, .py
        /src\/|tests\/|lib\/|app\//, // file paths
    ];
    return techTerms.some((re) => re.test(description));
}
/**
 * SPEC-619 AC1: Detect broad-scope descriptions that mention 2+ major subsystems.
 * When true, create_spec should ask clarifying questions before proceeding.
 *
 * Threshold scales with description length: longer descriptions are more specific
 * and naturally mention adjacent domain terms (e.g. Stripe billing + webhooks is
 * one feature, not two independent systems).
 */
export function detectBroadScope(description) {
    const lower = description.toLowerCase();
    const wordCount = lower.trim().split(/\s+/).length;
    const subsystems = [
        /\b(auth|authentication|login|signup|sign.?up|register|oauth|sso)\b/,
        /\b(payment|billing|invoice|subscription|stripe|checkout|pricing)\b/,
        /\b(notification|email|sms|push.?notification|alert|webhook)\b/,
        /\b(analytics|reporting|dashboard|metrics|stats|statistics|chart)\b/,
        /\b(admin|administration|back.?office|management.?panel|cms)\b/,
        /\b(search|full.?text.?search|elasticsearch|algolia|indexing)\b/,
        /\b(file.?upload|storage|media|image.?processing|cdn|s3)\b/,
        /\b(inventory|catalog|product|cart|order|e.?commerce)\b/,
        /\b(user.?management|profile|account|role|permission|rbac)\b/,
        /\b(chat|messaging|real.?time|websocket|feed|timeline)\b/,
    ];
    const matched = subsystems.filter((re) => re.test(lower));
    // Longer descriptions are specific enough to reference adjacent domain terms
    // without being genuinely broad (e.g. "Stripe billing + webhook handler" = one feature).
    const threshold = wordCount >= 20 ? 3 : 2;
    return matched.length >= threshold;
}
/** Infer the test file path from a source file path. */
function inferTestPath(srcPath) {
    if (srcPath.includes('test') || srcPath.includes('spec')) {
        return null; // Already a test file
    }
    const ext = extname(srcPath);
    const withoutExt = srcPath.replace(ext, '');
    // src/foo/bar.ts → tests/foo/bar.test.ts
    if (srcPath.startsWith('src/')) {
        return `tests/${withoutExt.slice(4)}.test${ext}`;
    }
    // lib/foo.ts → tests/lib/foo.test.ts
    return `tests/${withoutExt}.test${ext}`;
}
/** Detect relevant patterns from project knowledge. */
function detectPatterns(knowledge, description) {
    const patterns = [];
    const desc = description.toLowerCase();
    const hasDatabaseIntent = desc.includes('data') ||
        desc.includes('database') ||
        desc.includes('tabla') ||
        desc.includes('schema') ||
        desc.includes('rls') ||
        desc.includes('rpc') ||
        desc.includes('migration') ||
        desc.includes('persistence') ||
        desc.includes('data access');
    const hasUiIntent = desc.includes('component') ||
        desc.includes('ui') ||
        desc.includes('page') ||
        desc.includes('screen') ||
        desc.includes('form') ||
        desc.includes('layout') ||
        desc.includes('style') ||
        desc.includes('button') ||
        desc.includes('modal') ||
        desc.includes('dialog');
    if (hasDatabaseIntent) {
        patterns.push('database');
    }
    if (knowledge.framework?.toLowerCase().includes('next') && desc.includes('page')) {
        patterns.push('nextjs-pages');
    }
    if (knowledge.framework?.toLowerCase().includes('react') && hasUiIntent) {
        patterns.push('react-components');
    }
    if (desc.includes('api') || desc.includes('endpoint')) {
        patterns.push('api-endpoint');
    }
    if (desc.includes('auth') || desc.includes('login')) {
        patterns.push('authentication');
    }
    if (desc.includes('test') || desc.includes('coverage')) {
        patterns.push('testing');
    }
    if (knowledge.stack.some((s) => s.toLowerCase().includes('supabase')) && hasDatabaseIntent) {
        patterns.push('supabase');
    }
    // SPEC-535: Detect LLM/foundation model features for EU AI Act Article 53-55 compliance
    if (desc.includes('llm') ||
        desc.includes('ai ') ||
        desc.includes(' ai') ||
        desc.includes('claude') ||
        desc.includes('openai') ||
        desc.includes('gpt') ||
        desc.includes('gemini') ||
        desc.includes('anthropic') ||
        desc.includes('chatbot') ||
        desc.includes('language model') ||
        desc.includes('foundation model') ||
        (desc.includes('chat') && desc.includes('model'))) {
        patterns.push('llm-feature');
    }
    return patterns;
}
//# sourceMappingURL=autopilot-analyzer.js.map