/**
 * Intent Router — 意图路由器
 *
 * 根据用户意图文本确定语义通道 (route) 和执行形态 (execution_shape)。
 * 零 AI 依赖，纯规则匹配。
 *
 * 替代旧的 task_type -> strategy 入口裁决链路。
 * task_type 保留为辅助描述，不再单独决定是否进入 SoloForge。
 *
 * v2: 模块化拆分 — 路由判定由"信号提取 + 归一化 + 打分 + 冲突仲裁"完成，
 *     不再依赖单条整句正则。
 */
import { getDefaultArtifactPath } from "../contracts/artifact_contract_registry.js";
import { extractInputMaterials } from "./input_material_extractor.js";
import { extractSignals, ACTION_ALIASES, ARTIFACT_ALIASES, PURE_EXPLAIN_RULES, EXTRACTION_STRUCTURE, FULL_PIPELINE_RULES, SOURCE_MATERIAL_RULES } from "./intent_signal_extractor.js";
import { scoreRoute } from "./intent_route_scorer.js";
import { debugLog } from "../core/logger.js";
debugLog("意图路由: 模块已加载");
// ── 规则表（统一从 intent_signal_extractor 导入，消除重复定义） ──
/** 产物信号规则表 — 从 ARTIFACT_ALIASES 派生，保留 detectArtifact 回退兼容 */
const ARTIFACT_SIGNALS = ARTIFACT_ALIASES.map((a) => ({
    pattern: a.patterns.length === 1 ? a.patterns[0] : new RegExp(a.patterns.map((p) => `(?:${p.source})`).join("|")),
    artifactKind: a.kind,
    defaultName: a.defaultName,
    template: a.template,
}));
/** 产物动词: 从 ACTION_ALIASES 的 extract + generate 类别派生 */
const ARTIFACT_VERBS = [
    ...ACTION_ALIASES.filter((a) => a.category === "extract" || a.category === "generate").flatMap((a) => a.patterns),
    /整理成/, /拆(?:成|分为)/, /做成?/, /从.*(?:生成|输出|提取|抓取)/,
];
/** 源码提取信号 — 从 SOURCE_MATERIAL_RULES 转换字段名（kind → inputKind） */
const SOURCE_EXTRACTION_PATTERNS = SOURCE_MATERIAL_RULES.map((r) => ({ pattern: r.pattern, inputKind: r.kind }));
/** 提取类动词 — 使用 EXTRACTION_STRUCTURE + 路由器额外补充 */
const EXTRACTION_VERB_PATTERNS = [
    ...EXTRACTION_STRUCTURE,
    /(?:拿|用)\s*.*(?:做|生成|输出|提取|梳理|整理)/,
];
/** 代码修改模式 — 从 ACTION_ALIASES code_change 类别派生 */
const CODE_CHANGE_PATTERNS = ACTION_ALIASES.find((a) => a.category === "code_change").patterns;
/** 分析类模式 — 路由层专用（比信号提取器更精确） */
const ANALYSIS_PATTERNS = [
    /分析.*(?:模块|系统|架构|性能|安全|风险|影响)/,
    /评估.*(?:风险|可行性|影响|质量)/,
    /梳理.*(?:模型|架构|流程|依赖)/,
    /看看.*(?:风险|问题|有没有)/,
    /影响(?:哪些|范围)/,
    /为什么(?:容易|总是|频繁)/,
    /(?:报错|错误).*(?:是什么意思|怎么回事)/,
    /分析.*(?:报错|错误|异常).*(?:意思|原因|为什么)/,
];
/** 审查类模式 — 从 ACTION_ALIASES review 类别派生 */
const REVIEW_PATTERNS = ACTION_ALIASES.find((a) => a.category === "review").patterns;
/** 验收/就绪检查模式 — 从 ACTION_ALIASES acceptance 类别派生 */
const ACCEPTANCE_PATTERNS = ACTION_ALIASES.find((a) => a.category === "acceptance").patterns;
const IMPLEMENTATION_VERB_PATTERN = /修复|实现|开发|新增|添加|修改|变更|重构|删除|移除|替换|补(?:单元)?测试|写测试|编码/;
/** 规划类模式 — 从 ACTION_ALIASES plan 类别派生 */
const PLANNING_PATTERNS = ACTION_ALIASES.find((a) => a.category === "plan").patterns;
/** 全流程信号模式 — 直接使用 FULL_PIPELINE_RULES */
const FULL_PIPELINE_SIGNALS = FULL_PIPELINE_RULES;
/** 操作类模式 — 从 ACTION_ALIASES operate 类别派生 */
const OPERATION_PATTERNS = ACTION_ALIASES.find((a) => a.category === "operate").patterns;
/** 纯解释类模式 — 直接使用 PURE_EXPLAIN_RULES */
const PURE_EXPLAIN_PATTERNS = PURE_EXPLAIN_RULES;
// ── 产物检测（保留兼容） ──
function detectArtifact(intent, taskId) {
    const id = taskId || "01";
    for (const signal of ARTIFACT_SIGNALS) {
        if (signal.pattern.test(intent)) {
            return {
                kind: signal.artifactKind,
                path: getDefaultArtifactPath(signal.artifactKind, id),
                template: signal.template,
                taskId,
            };
        }
    }
    if (/(?:文档|方案|规约|计划|清单|报告|说明文档)$/.test(intent)) {
        const match = intent.match(/([一-龥]+(?:文档|方案|规约|计划|清单|报告|说明文档))$/);
        const name = match ? match[1] : "产物";
        return { kind: "unknown", path: `.soloforge/output/${id}/01-${name}.md`, taskId };
    }
    return undefined;
}
function hasArtifactVerb(intent) {
    return ARTIFACT_VERBS.some((p) => p.test(intent));
}
function hasArtifactNoun(intent) {
    return ARTIFACT_SIGNALS.some((s) => s.pattern.test(intent))
        || /(?:文档|方案|规约|计划|清单|报告|说明文档)$/.test(intent);
}
function inferMissingInputs(intent, hasPath) {
    if (hasPath)
        return { materials: [], missing: [] };
    const missing = [];
    const materials = [];
    if (/源码包|压缩包|zip包|包文件|源码/.test(intent)) {
        materials.push({ kind: "archive", required: true });
        missing.push("请提供源码包 zip 或已解压源码目录路径");
    }
    else if (/报错日志|日志/.test(intent)) {
        materials.push({ kind: "log", required: true });
        missing.push("请提供日志文件路径或内容");
    }
    else {
        materials.push({ kind: "archive", required: true });
        missing.push("请提供输入材料路径");
    }
    return { materials, missing };
}
/**
 * 主路由函数 — 根据用户意图文本确定语义路由和执行形态。
 * v2: 调用结构化信号提取 → 打分 → 冲突仲裁，不再依赖单条正则句子匹配。
 *
 * @param input - 路由输入参数，包含意图文本和可选的项目路径/任务 ID
 * @returns 意图路由决策，包含路由类型、执行形态和置信度
 */
function logRouteHit(decision) {
    debugLog(JSON.stringify({
        sf_route_hit: true,
        route: decision.route,
        execution_shape: decision.execution_shape,
        input_materials: decision.input_materials.map((m) => m.kind).join(",") || "none",
        output_artifact: decision.output_artifact?.kind ?? "-",
        prompt_template: selectPromptTemplate(decision),
        confidence: decision.confidence,
    }));
}
export function routeIntent(input) {
    // 安全校验: 意图文本不能为空或超长（防止资源耗尽）
    if (!input.intent || input.intent.trim().length === 0) {
        return {
            ...mk("skip_chat", "none", false, [], [], undefined, undefined, 0),
            skip_reason: "意图文本为空",
            evidence: ["empty_intent"],
            rejected_routes: [],
            conflicts: [],
            decision_version: 2,
        };
    }
    const MAX_INTENT_LENGTH = 10_000;
    if (input.intent.length > MAX_INTENT_LENGTH) {
        return {
            ...mk("skip_chat", "none", false, [], [], undefined, undefined, 0),
            skip_reason: `意图文本超长 (${input.intent.length} > ${MAX_INTENT_LENGTH})`,
            evidence: ["oversized_intent"],
            rejected_routes: [],
            conflicts: [],
            decision_version: 2,
        };
    }
    const decision = routeIntentCore(input);
    logRouteHit(decision);
    // v2 评分告警：v1 兼容层路由与 v2 评分器推荐路由不一致时记录告警
    const v2Signals = extractSignals(input.intent);
    const v2Materials = extractInputMaterials(input.intent);
    const v2Scored = scoreRoute(input.intent, v2Signals, v2Materials, input.task_id);
    const v2TopRoute = v2Scored.score_breakdown.length > 0 ? v2Scored.score_breakdown[0].route : undefined;
    if (v2TopRoute && decision.route !== v2TopRoute) {
        debugLog(`v2评分告警: v1=${decision.route} v2=${v2TopRoute} intent="${input.intent.slice(0, 60)}"`);
    }
    // 知识消费: router 消费 routes/primary_triggers/specificity
    recordRouterConsumption(decision);
    return decision;
}
/**
 * 知识消费钩子: 记录 intent_router 的知识资产消费到统一 trace store。
 */
import { recordConsumptionTrace, getTracesByConsumer, CONSUMER_FIELD_CONTRACTS } from "../templates/consumption_trace_store.js";
import { listConsumableAssetsByConsumer } from "../templates/consumable_asset_registry.js";
function recordRouterConsumption(decision) {
    const routerAssets = listConsumableAssetsByConsumer("intent_router")
        .filter(a => a.consumption_mode === "required");
    if (routerAssets.length === 0)
        return;
    for (const asset of routerAssets) {
        recordConsumptionTrace({
            consumer: "router",
            asset_id: asset.id,
            fields_consumed: CONSUMER_FIELD_CONTRACTS.router,
            matched_reason: `route=${decision.route} shape=${decision.execution_shape} intent=${decision.workflow_intent || "none"} evidence=${(decision.evidence || []).slice(0, 3).join(",")}`,
            task_id_or_route: decision.route,
            consumed_at: new Date().toISOString(),
        });
    }
}
/** 获取路由消费追踪 */
export function getRouterConsumptionTrace() {
    return getTracesByConsumer("router").map(t => ({
        route: t.task_id_or_route,
        execution_shape: t.matched_reason.split("shape=")[1]?.split(" ")[0] || "",
        consumed_triggers: t.fields_consumed,
        consumed_at: t.consumed_at,
    }));
}
function routeIntentCore(input) {
    const { intent, task_id: taskId } = input;
    const normalized = intent.toLowerCase();
    debugLog("意图路由: 开始意图路由 (v2 signal-based)");
    // ── 阶段 1: 信号提取 ──
    const signals = extractSignals(intent);
    const materialResult = extractInputMaterials(intent);
    const scoredResult = scoreRoute(intent, signals, materialResult, taskId);
    // ── 阶段 1.5: 工作流意图优先检查 ──
    // 在所有标准路由之前检查 工作流意图，确保精准路由
    if (signals.workflow_intent) {
        const workflowResolveResult = buildResolveWorkflowDecision(signals, materialResult, scoredResult, taskId);
        if (workflowResolveResult) {
            debugLog(`意图路由: 工作流意图命中 workflow_intent=${signals.workflow_intent}`);
            return workflowResolveResult;
        }
    }
    // ── 阶段 2: 兼容层 — 将新模块结果映射回原有分层逻辑 ──
    // 这确保所有现有测试用例的行为不变
    // v2 评分告警：对比 v1 兼容层最终路由与 v2 评分器推荐路由，不一致时记录告警
    const inputPaths = materialResult.materials.map((m) => ({
        kind: m.kind,
        path: m.path,
        ingestion_status: m.ingestion_status,
    }));
    const hasInputPaths = inputPaths.length > 0;
    // 层 0: 跳过类
    if (signals.is_skip) {
        debugLog(`意图路由: 匹配跳过模式 (${signals.skip_reason})，路由到 skip_chat`);
        const skipRejected = scoredResult.score_breakdown
            .filter(s => s.route !== "skip_chat")
            .slice(0, 3)
            .map(s => ({ route: s.route, reason: s.reasons.join("; "), score: s.score }));
        const skipConflicts = signals.negations.length > 0
            ? signals.negations.map(n => ({ description: `negation: ${n.negates}`, resolution: `skip_chat via ${signals.skip_reason}` }))
            : [];
        return {
            ...mk("skip_chat", "none", false, [], [], undefined, undefined, 0.95),
            skip_reason: signals.skip_reason,
            evidence: ["skip:" + signals.skip_reason],
            rejected_routes: skipRejected,
            conflicts: skipConflicts,
            decision_version: 2,
        };
    }
    if (signals.is_general_qa) {
        debugLog("意图路由: 匹配通用问答模式，路由到 direct_answer");
        const qaRejected = scoredResult.score_breakdown
            .filter(s => s.route !== "direct_answer")
            .slice(0, 3)
            .map(s => ({ route: s.route, reason: s.reasons.join("; "), score: s.score }));
        return {
            ...mk("direct_answer", "none", false, [], [], undefined, undefined, 0.9),
            evidence: ["general_qa"],
            rejected_routes: qaRejected,
            decision_version: 2,
        };
    }
    const artifactVerbPresent = hasArtifactVerb(intent);
    const hasArtifactSignal = artifactVerbPresent && hasArtifactNoun(intent);
    const artifact = detectArtifact(intent, taskId);
    const hasArchiveLogSignal = SOURCE_EXTRACTION_PATTERNS.some((s) => s.pattern.test(intent));
    const hasExtractionVerb = EXTRACTION_VERB_PATTERNS.some((p) => p.test(intent));
    const hasSourceExtraction = hasArchiveLogSignal
        || (hasExtractionVerb && (hasInputPaths || /源码/.test(intent)));
    const isFullPipeline = FULL_PIPELINE_SIGNALS.some((p) => p.test(intent));
    // ── 冲突仲裁：检查否定/约束信号 ──
    const hasNoPipeline = signals.negations.some((n) => n.negates === "pipeline");
    // 层 1: 源码/材料提取
    if (hasSourceExtraction && (hasArtifactSignal || artifact)) {
        debugLog("意图路由: 路由到 source_extraction");
        const materials = hasInputPaths
            ? inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: true, ingestion_status: p.ingestion_status }))
            : inferMissingInputs(intent, false).materials.map((m) => ({ kind: m.kind, required: m.required }));
        const missing = hasInputPaths
            ? []
            : inferMissingInputs(intent, false).missing;
        const inferred = hasInputPaths ? undefined : inferMissingInputs(intent, false).materials;
        const rejectedRoutes = scoredResult.score_breakdown
            .filter(s => s.route !== "source_extraction")
            .slice(0, 3)
            .map(s => ({ route: s.route, reason: s.reasons.join("; "), score: s.score }));
        return {
            ...mk("source_extraction", "single_artifact", false, materials, missing, artifact ?? { kind: "custom", path: `.soloforge/output/${taskId ?? "01"}/01-提取产物.md`, taskId }, inferPipelineHint(intent, artifact?.kind), 0.8),
            operation_type: resolveOperationType("source_extraction"),
            inferred_materials: inferred,
            needs_clarification: missing.length > 0,
            route_reason: scoredResult.route_reason,
            signal_evidence: scoredResult.signal_evidence,
            evidence: scoredResult.signal_evidence,
            rejected_routes: rejectedRoutes,
            decision_version: 2,
        };
    }
    // 层 2: 规划
    if (PLANNING_PATTERNS.some((p) => p.test(normalized)) || isFullPipeline) {
        debugLog("意图路由: 路由到 planning");
        if (isFullPipeline && !hasNoPipeline) {
            return {
                ...mk("planning", "multi_stage_plan", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], artifact, inferPipelineHint(intent, artifact?.kind), 0.75),
                route_reason: scoredResult.route_reason,
                signal_evidence: scoredResult.signal_evidence,
                decision_version: 2,
            };
        }
        return {
            ...mk("planning", "single_artifact", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], { kind: "task_breakdown", path: `.soloforge/output/${taskId ?? "01"}/01-任务拆解.md`, taskId }, undefined, 0.8),
            route_reason: scoredResult.route_reason,
            signal_evidence: scoredResult.signal_evidence,
            decision_version: 2,
        };
    }
    // 层 3: 操作
    if (OPERATION_PATTERNS.some((p) => p.test(normalized))) {
        debugLog("意图路由: 路由到 operation");
        return {
            ...mk("operation", "verification_only", false, [], [], undefined, undefined, 0.8),
            route_reason: scoredResult.route_reason,
            decision_version: 2,
        };
    }
    // 层 3.5: 分析
    if (ANALYSIS_PATTERNS.some((p) => p.test(normalized)) && !artifactVerbPresent) {
        debugLog("意图路由: 路由到 analysis（分析优先）");
        const _analysisEarlyArtifact = detectArtifact(normalized, taskId);
        return {
            ...mk("analysis", "read_only_analysis", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], _analysisEarlyArtifact, undefined, 0.8),
            operation_type: resolveOperationType("analysis"),
            route_reason: scoredResult.route_reason,
            decision_version: 2,
        };
    }
    // 层 4: 产物生成
    if (hasArtifactSignal || (artifactVerbPresent && artifact && !PURE_EXPLAIN_PATTERNS.some((p) => p.test(intent)))) {
        debugLog("意图路由: 路由到 artifact_generation");
        const missing = [];
        if (/根据\s*(?:PRD|需求文档|原型|接口文档|设计文档|源码)/i.test(intent) && inputPaths.length === 0) {
            const refMatch = intent.match(/根据\s*(PRD|需求文档|原型|接口文档|设计文档|源码)/i);
            if (refMatch)
                missing.push(`请提供 ${refMatch[1]} 文件路径或内容`);
        }
        return {
            ...mk("artifact_generation", "single_artifact", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), missing, artifact ?? { kind: "custom", path: `.soloforge/output/${taskId ?? "01"}/01-产物.md`, taskId }, inferPipelineHint(intent, artifact?.kind), 0.8),
            operation_type: resolveOperationType("artifact_generation"),
            needs_clarification: missing.length > 0,
            route_reason: scoredResult.route_reason,
            signal_evidence: scoredResult.signal_evidence,
            decision_version: 2,
        };
    }
    // 层 5: 纯验收/就绪检查
    // "检查脚手架是否就绪" 是只读验收，不应因出现"脚手架"就进入 scaffold/code_change。
    // 但 "验收失败后修复代码" 仍是施工任务，交给 code_change。
    if (ACCEPTANCE_PATTERNS.some((p) => p.test(normalized)) && !IMPLEMENTATION_VERB_PATTERN.test(normalized)) {
        debugLog("意图路由: 路由到 acceptance（只读验收/就绪检查）");
        const _artifact = detectArtifact(normalized, taskId);
        return {
            ...mk("acceptance", "read_only_analysis", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], _artifact, undefined, 0.9),
            operation_type: resolveOperationType("acceptance"),
            route_reason: scoredResult.route_reason || "acceptance_readiness_check",
            signal_evidence: scoredResult.signal_evidence.length > 0 ? scoredResult.signal_evidence : ["acceptance"],
            evidence: scoredResult.signal_evidence.length > 0 ? scoredResult.signal_evidence : ["acceptance"],
            decision_version: 2,
        };
    }
    // 层 6: 代码修改
    if (CODE_CHANGE_PATTERNS.some((p) => p.test(normalized))) {
        debugLog("意图路由: 路由到 code_change");
        const _codeChangeArtifact = detectArtifact(normalized, taskId);
        return {
            ...mk("code_change", "code_execution", true, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], _codeChangeArtifact, undefined, 0.85),
            operation_type: resolveOperationType("code_change"),
            route_reason: scoredResult.route_reason,
            decision_version: 2,
        };
    }
    // 层 7: 审查
    if (REVIEW_PATTERNS.some((p) => p.test(normalized))) {
        debugLog("意图路由: 路由到 review");
        const _reviewArtifact = detectArtifact(normalized, taskId);
        return {
            ...mk("review", "read_only_analysis", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], _reviewArtifact, undefined, 0.85),
            operation_type: resolveOperationType("review"),
            route_reason: scoredResult.route_reason,
            decision_version: 2,
        };
    }
    // 层 8: 通用分析
    if (ANALYSIS_PATTERNS.some((p) => p.test(normalized))) {
        debugLog("意图路由: 路由到 analysis（通用）");
        const _analysisArtifact = detectArtifact(normalized, taskId);
        return {
            ...mk("analysis", "read_only_analysis", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], _analysisArtifact, undefined, 0.8),
            operation_type: resolveOperationType("analysis"),
            route_reason: scoredResult.route_reason,
            decision_version: 2,
        };
    }
    // 层 9: 灰区
    if (/整理(?:一下|下)?/.test(intent)) {
        if (!hasArtifactNoun(intent)) {
            return {
                ...mk("direct_answer", "none", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], undefined, undefined, 0.6),
                route_reason: "gray_zone:organize",
                decision_version: 2,
            };
        }
    }
    // 层 10: 纯解释
    if (PURE_EXPLAIN_PATTERNS.some((p) => p.test(intent))) {
        if (/(?:这个|这|项目里|项目中的|当前|现有)/.test(intent)) {
            return {
                ...mk("analysis", "read_only_analysis", false, [], [], undefined, undefined, 0.7),
                operation_type: resolveOperationType("analysis"),
                route_reason: "pure_explain+context",
                decision_version: 2,
            };
        }
        return {
            ...mk("direct_answer", "none", false, [], [], undefined, undefined, 0.85),
            route_reason: "pure_explain",
            decision_version: 2,
        };
    }
    // 层 11: "看看" 灰区
    if (/看看|看下/.test(intent)) {
        if (/(?:风险|问题|有没有)/.test(intent)) {
            const _grayReviewArtifact = detectArtifact(intent, taskId);
            return {
                ...mk("review", "read_only_analysis", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], _grayReviewArtifact, undefined, 0.7),
                operation_type: resolveOperationType("review"),
                route_reason: "gray:review",
                decision_version: 2,
            };
        }
        return {
            ...mk("direct_answer", "none", false, inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: false, ingestion_status: p.ingestion_status })), [], undefined, undefined, 0.6),
            route_reason: "gray:look",
            decision_version: 2,
        };
    }
    // 兜底
    debugLog("意图路由: 未匹配任何规则，兜底路由到 direct_answer");
    return {
        ...mk("direct_answer", "none", false, [], [], undefined, undefined, 0.3),
        decision_version: 2,
    };
}
const EXTENSION_WORKFLOW_MAP = {
    architecture_design: {
        route: "artifact_generation",
        execution_shape: "multi_stage_plan",
        mutation_allowed: false,
        prompt_template: "architecture_design_prompt",
        pipeline_hint: "architecture-design",
        confidence: 0.9,
    },
    existing_system_gap_analysis: {
        route: "analysis",
        execution_shape: "multi_stage_plan",
        mutation_allowed: false,
        prompt_template: "gap_analysis_prompt",
        pipeline_hint: "existing-system-gap-analysis",
        confidence: 0.9,
    },
    test_first_coding: {
        route: "code_change",
        execution_shape: "multi_stage_plan",
        mutation_allowed: true,
        prompt_template: "test_first_coding_prompt",
        pipeline_hint: "test-first-coding",
        confidence: 0.9,
    },
    local_browser_acceptance: {
        route: "operation",
        execution_shape: "read_only_analysis",
        mutation_allowed: false,
        prompt_template: "local_acceptance_prompt",
        pipeline_hint: "local-browser-acceptance",
        confidence: 0.9,
    },
};
/**
 * 根据 工作流意图信号构建完整路由决策。
 * 在标准路由之前检查，确保精准路由到扩展平台工作流。
 */
function buildResolveWorkflowDecision(signals, materialResult, scoredResult, taskId) {
    const workflowIntent = signals.workflow_intent;
    if (!workflowIntent)
        return null;
    const mapping = EXTENSION_WORKFLOW_MAP[workflowIntent];
    if (!mapping)
        return null;
    // 有源码提取材料（archive 等）时优先走 source_extraction，不拦截到扩展平台工作流
    const hasArchiveMaterial = materialResult.materials.some((m) => m.kind === "archive");
    if (hasArchiveMaterial)
        return null;
    const inputPaths = materialResult.materials.map((m) => ({
        kind: m.kind,
        path: m.path,
        ingestion_status: m.ingestion_status,
    }));
    const artifact = workflowIntent === "architecture_design"
        ? detectArtifact("架构设计", taskId)
        : undefined;
    const rejectedRoutes = scoredResult.score_breakdown
        .filter(s => s.route !== mapping.route)
        .slice(0, 3)
        .map(s => ({ route: s.route, reason: s.reasons.join("; "), score: s.score }));
    return {
        ...mk(mapping.route, mapping.execution_shape, mapping.mutation_allowed, inputPaths.length > 0
            ? inputPaths.map((p) => ({ kind: p.kind, path: p.path, required: true, ingestion_status: p.ingestion_status }))
            : [], [], artifact, mapping.pipeline_hint, mapping.confidence),
        operation_type: resolveOperationType(mapping.route),
        workflow_intent: workflowIntent,
        route_reason: `workflow_resolve:${workflowIntent}`,
        signal_evidence: [`workflow_intent:${workflowIntent}`],
        evidence: [`workflow_resolve:${workflowIntent}`],
        rejected_routes: rejectedRoutes,
        decision_version: 2,
    };
}
// ── 构造函数 ──
/** 从意图路由推导产物操作类型 */
function resolveOperationType(route) {
    switch (route) {
        case "source_extraction": return "extract";
        case "artifact_generation": return "extract";
        case "review": return "review";
        case "code_change": return "fix";
        case "acceptance": return "review";
        case "analysis": return "review";
        default: return "iterate";
    }
}
function mk(route, execution_shape, mutation_allowed, input_materials, missing, output_artifact, pipeline_hint, confidence) {
    return {
        route, execution_shape, mutation_allowed, input_materials,
        output_artifact, pipeline_hint, missing_required_inputs: missing, confidence,
        scope: { read_only: !mutation_allowed, description: route + " scope" },
        constraints: mutation_allowed ? [] : ["no_mutation"],
        language_policy: { primary: "zh-CN", fallback: "en" },
        evidence: [],
        rejected_routes: [],
        conflicts: [],
    };
}
// ── 流水线提示 ──
function inferPipelineHint(intent, artifactKind) {
    if (/源码.*原型|原型.*源码|源码包.*原型|prototype/i.test(intent)) {
        return "source-prototype-to-delivery:step-1";
    }
    if (/从.*(?:设计|需求|原型).*到.*(?:交付|完成)/.test(intent)) {
        return "source-prototype-to-delivery";
    }
    switch (artifactKind) {
        case "prototype_spec": return "source-prototype-to-delivery:step-1";
        case "api_spec": return "source-prototype-to-delivery:step-4";
        case "design_doc": return "source-prototype-to-delivery:step-3";
        case "test_plan": return "source-prototype-to-delivery:step-5";
        default: return undefined;
    }
}
// ── 外部 API（保持不变） ──
export function shouldEnterSoloForge(decision) {
    debugLog("意图路由: 判断是否进入 SoloForge，当前路由: " + decision.route);
    return decision.route !== "skip_chat" && decision.route !== "direct_answer";
}
export function selectPromptTemplate(decision) {
    debugLog("意图路由: 选择 Prompt 模板，路由: " + decision.route + ", 执行形态: " + decision.execution_shape + ", workflow_intent: " + (decision.workflow_intent ?? "none"));
    // 工作流意图优先选择对应模板
    if (decision.workflow_intent) {
        const mapping = EXTENSION_WORKFLOW_MAP[decision.workflow_intent];
        if (mapping)
            return mapping.prompt_template;
    }
    if (decision.route === "source_extraction")
        return "source_extraction_prompt";
    if (decision.route === "direct_answer")
        return "direct_answer_prompt";
    if (decision.route === "acceptance")
        return "acceptance_prompt";
    switch (decision.execution_shape) {
        case "code_execution": return "code_execution_prompt";
        case "single_artifact": return "single_artifact_prompt";
        case "read_only_analysis": return "read_only_analysis_prompt";
        case "verification_only": return "verification_only_prompt";
        case "multi_stage_plan": return "single_artifact_prompt";
        case "none": return "direct_answer_prompt";
        default: return "code_execution_prompt";
    }
}
export function debugRouteIntent(input) {
    const { intent, task_id: taskId } = input;
    const materialResult = extractInputMaterials(intent);
    const signals = extractSignals(intent);
    const scored = scoreRoute(intent, signals, materialResult, taskId);
    const decision = routeIntent(input);
    const whyNotSkip = signals.is_skip
        ? `skip detected: ${signals.skip_reason}`
        : signals.is_general_qa
            ? "general QA pattern"
            : "has SoloForge-relevant signals";
    return {
        intent,
        extracted_materials: materialResult,
        signals,
        scored,
        final_decision: decision,
        why_not_skip: whyNotSkip,
    };
}
//# sourceMappingURL=intent_router.js.map