// Planu — NFR Profile Detector (SPEC-027)
// Derives Non-Functional Requirement profiles from project knowledge.
// Maps system types to realistic latency, throughput, and availability targets.
// Stack signals that indicate low-latency API requirements
const LOW_LATENCY_SIGNALS = [
    'express',
    'fastify',
    'hono',
    'graphql',
    'grpc',
    'rest',
    'api',
    'gateway',
    'redis',
    'realtime',
    'websocket',
];
// Stack signals that indicate batch processing systems
const BATCH_SIGNALS = [
    'celery',
    'bull',
    'bullmq',
    'sidekiq',
    'resque',
    'kafka',
    'rabbitmq',
    'airflow',
    'dbt',
    'spark',
    'beam',
    'cron',
    'queue',
    'worker',
    'job',
    'batch',
];
// Stack signals that indicate interactive apps
const INTERACTIVE_SIGNALS = [
    'react',
    'vue',
    'angular',
    'svelte',
    'next',
    'nuxt',
    'remix',
    'spa',
    'frontend',
    'ui',
    'dashboard',
];
// Stack signals that indicate background services
const BACKGROUND_SIGNALS = [
    'daemon',
    'service',
    'scheduler',
    'monitor',
    'crawler',
    'scraper',
    'sync',
    'pipeline',
];
const NFR_DEFAULTS = {
    'low-latency-api': {
        systemType: 'low-latency-api',
        p95LatencyMs: 100,
        p99LatencyMs: 200,
        minThroughputRps: 100,
        availabilityTarget: '99.9%',
        maxPayloadBytes: 1_000_000,
        dailyRecords: 100_000,
    },
    'batch-processing': {
        systemType: 'batch-processing',
        p95LatencyMs: 5000,
        p99LatencyMs: 30_000,
        minThroughputRps: 1,
        availabilityTarget: '99%',
        maxPayloadBytes: 100_000_000,
        dailyRecords: 1_000_000,
    },
    'interactive-app': {
        systemType: 'interactive-app',
        p95LatencyMs: 200,
        p99LatencyMs: 500,
        minThroughputRps: 50,
        availabilityTarget: '99.9%',
        maxPayloadBytes: 5_000_000,
        dailyRecords: 10_000,
    },
    'background-service': {
        systemType: 'background-service',
        p95LatencyMs: 2000,
        p99LatencyMs: 10_000,
        minThroughputRps: 5,
        availabilityTarget: '99%',
        maxPayloadBytes: 10_000_000,
        dailyRecords: 50_000,
    },
    unknown: {
        systemType: 'unknown',
        p95LatencyMs: 500,
        p99LatencyMs: 2000,
        minThroughputRps: 10,
        availabilityTarget: '99%',
        maxPayloadBytes: 10_000_000,
        dailyRecords: 10_000,
    },
};
/**
 * Detect the system profile type from stack signals.
 * Returns the most likely profile based on matched signals.
 */
export function detectSystemProfile(stack) {
    const lower = stack.map((s) => s.toLowerCase());
    const scores = {
        'low-latency-api': 0,
        'batch-processing': 0,
        'interactive-app': 0,
        'background-service': 0,
        unknown: 0,
    };
    for (const s of lower) {
        for (const signal of LOW_LATENCY_SIGNALS) {
            if (s.includes(signal)) {
                scores['low-latency-api'] += 1;
            }
        }
        for (const signal of BATCH_SIGNALS) {
            if (s.includes(signal)) {
                scores['batch-processing'] += 1;
            }
        }
        for (const signal of INTERACTIVE_SIGNALS) {
            if (s.includes(signal)) {
                scores['interactive-app'] += 1;
            }
        }
        for (const signal of BACKGROUND_SIGNALS) {
            if (s.includes(signal)) {
                scores['background-service'] += 1;
            }
        }
    }
    const best = Object.entries(scores).reduce((max, entry) => (entry[1] > max[1] ? entry : max), ['unknown', 0]);
    return best[1] > 0 ? best[0] : 'unknown';
}
/**
 * Get the NFR profile for a given system type.
 * Returns sensible defaults when type is unknown.
 */
export function getNFRProfile(systemType) {
    return NFR_DEFAULTS[systemType];
}
/**
 * Derive NFRs from a stack array.
 */
export function deriveNFRProfile(stack) {
    const systemType = detectSystemProfile(stack);
    return getNFRProfile(systemType);
}
/**
 * Generate NFR section lines for inclusion in HU.md content.
 */
export function generateNFRSection(profile) {
    return [
        '',
        '## Non-Functional Requirements',
        '',
        `> System profile: **${profile.systemType}**`,
        '',
        '### Performance',
        '',
        `- [ ] P95 latency < **${profile.p95LatencyMs}ms** under normal load`,
        `- [ ] P99 latency < **${profile.p99LatencyMs}ms** under peak load`,
        `- [ ] Minimum throughput: **${profile.minThroughputRps} req/s** sustained`,
        '',
        '### Reliability',
        '',
        `- [ ] Availability target: **${profile.availabilityTarget}** (measured monthly)`,
        '- [ ] Graceful degradation under partial failures',
        '',
        '### Data Volume',
        '',
        `- [ ] Max payload size: **${formatBytes(profile.maxPayloadBytes)}** per request`,
        `- [ ] Daily volume estimate: **${formatNumber(profile.dailyRecords)} records/day**`,
        '',
        '### Observability',
        '',
        '- [ ] Key metrics instrumented (latency, error rate, throughput)',
        '- [ ] Distributed tracing enabled for cross-service calls',
        '- [ ] Alerts configured for SLO violations',
    ];
}
function formatBytes(bytes) {
    if (bytes >= 1_000_000) {
        return `${(bytes / 1_000_000).toFixed(0)}MB`;
    }
    if (bytes >= 1_000) {
        return `${(bytes / 1_000).toFixed(0)}KB`;
    }
    return `${bytes}B`;
}
function formatNumber(n) {
    if (n >= 1_000_000) {
        return `${(n / 1_000_000).toFixed(1)}M`;
    }
    if (n >= 1_000) {
        return `${(n / 1_000).toFixed(0)}K`;
    }
    return String(n);
}
//# sourceMappingURL=nfr-profile-detector.js.map