import type { Classification, TaskKind } from "./types.js"; interface Rule { kind: TaskKind; score: number; pattern: RegExp; reason: string; } const rules: readonly Rule[] = [ { kind: "architecture", score: 78, pattern: /\b(architect(?:ure|ural)?|redesign|security audit|system design|migration plan|(?:database|data|schema) migrat(?:e|ion))\b/i, reason: "architecture evidence" }, { kind: "debugging", score: 70, pattern: /\b(debug across|race condition|multi[- ]file debug|trace .* root cause|deadlock)\b/i, reason: "complex debugging evidence" }, { kind: "research", score: 65, pattern: /\b(compare|research|investigate|find out|external behavior|dependency api)\b/i, reason: "research evidence" }, { kind: "refactor", score: 58, pattern: /\b(refactor|reorganize|extract (?:the )?\w+|cleanup)\b/i, reason: "refactor evidence" }, { kind: "bugfix", score: 35, pattern: /\b(fix|bug|regression|broken|failing|error)\b/i, reason: "bug-fix evidence" }, { kind: "explanation", score: 18, pattern: /\b(explain|what does|how does|documentation|where is)\b/i, reason: "explanation evidence" }, { kind: "simple", score: 10, pattern: /\b(rename|typo|format|whitespace|lint)\b/i, reason: "simple task keyword" }, { kind: "feature", score: 48, pattern: /\b(add|implement|create|update|test)\b/i, reason: "feature evidence" }, ]; const risks: readonly [RegExp, string, number][] = [ [/\b(security|auth(?:entication|orization)?|credential)\b/i, "security", 12], [/\b(data loss|delete(?: all)? data|backup)\b/i, "data loss", 12], [/\b(migrat(?:e|ion)|production|prod)\b/i, "production or migration", 6], [/\b(concurren(?:cy|t)|race condition|deadlock)\b/i, "concurrency", 12], ]; export function classify(prompt: string): Classification { const isExplanation = /\b(explain|what does|how does|where is)\b/i.test(prompt); const isSimple = /\b(rename|typo|format|whitespace|lint)\b/i.test(prompt); const candidates = isExplanation ? rules.filter((rule) => rule.kind === "explanation") : isSimple ? rules.filter((rule) => rule.kind === "simple") : rules; const matched = candidates.find((rule) => rule.pattern.test(prompt)); const kind = matched?.kind ?? "feature"; let score = matched?.score ?? 48; const reasons = [matched?.reason ?? "default feature routing"]; for (const [pattern, reason, weight] of risks) { if (pattern.test(prompt)) { score += weight; reasons.push(`risk: ${reason}`); } } return { kind, score: Math.min(score, 95), reasons }; }