#!/usr/bin/env node /** * Task3 补丁 — 2026-04-20 路由精准度审查 * * 问题: 2-3 字短查询(token 数 ≤3)信息量不足,BM25 仍可算出 confidence=1.0, * 导致 100% 置信度过拟合(如"自动修复"→ browser-automation-expert 100%)。 * * 修复方案: 在 route-engine.js 返回结果前加一层置信度上限: * 若 queryTokens.length ≤ 3,则 confidence = min(confidence, 0.8) * 并写入调试日志便于后续观察。 * * 最小侵入: 仅在 return 语句前插入 4 行代码。 * * 幂等: sentinel = 'CONFIDENCE_CAP_SHORT_QUERY_PATCH_2026_04_20' */ 'use strict'; const fs = require('fs'); const path = require('path'); const SCRIPTS_DIR = path.join(__dirname, '..'); const TARGET = path.join(SCRIPTS_DIR, 'route-engine.js'); const SENTINEL = 'CONFIDENCE_CAP_SHORT_QUERY_PATCH_2026_04_20'; function main() { if (!fs.existsSync(TARGET)) { console.error('[patch-task3] 目标文件不存在:', TARGET); process.exit(1); } const before = fs.readFileSync(TARGET, 'utf8'); // 幂等检查 if (before.includes(SENTINEL)) { console.log('[patch-task3] 已打过补丁 (发现 sentinel),跳过'); process.exit(0); } // 锚点: return 语句前的 confidence 计算行 const anchor = ' const confidence = normalized[0]?.confidence || 0;\n' + '\n' + ' return {'; if (!before.includes(anchor)) { console.error('[patch-task3] 找不到 confidence 计算锚点,route-engine.js 结构已变更'); process.exit(2); } // 注入: confidence 上限 + debug log const injection = ' const confidence = normalized[0]?.confidence || 0;\n' + '\n' + ' // ' + SENTINEL + '\n' + ' // 短查询置信度上限: token 数 ≤3 时 confidence 不超过 0.8,防 BM25 过拟合\n' + ' let _finalConfidence = confidence;\n' + ' if (queryTokens.size <= 3 && _finalConfidence > 0.8) {\n' + ' _finalConfidence = 0.8;\n' + ' try {\n' + ' const logLine = JSON.stringify({\n' + ' t: Date.now(), event: \'confidence_cap\',\n' + ' tokens: queryTokens.size, original: confidence, capped: 0.8,\n' + ' primary: normalized[0] && normalized[0].name,\n' + ' }) + \'\\n\';\n' + ' fs.appendFileSync(path.join(DEBUG_DIR, \'confidence-cap.log\'), logLine);\n' + ' } catch {}\n' + ' }\n' + '\n' + ' return {'; const after = before.replace(anchor, injection); // 同时将 return 对象中的 confidence 替换为 _finalConfidence const returnAnchor = ' primary, candidates, confidence, chain, composable,'; if (!after.includes(returnAnchor)) { console.error('[patch-task3] 找不到 return 对象中的 confidence 字段'); process.exit(3); } const finalAfter = after.replace( returnAnchor, ' primary, candidates, confidence: _finalConfidence, chain, composable,' ); // ==== 原子写入 (.bak 备份 + tmp 文件) ==== const bakFile = TARGET + '.bak.task3.' + Date.now(); fs.copyFileSync(TARGET, bakFile); console.log('[patch-task3] 备份已写入:', bakFile); const tmpFile = TARGET + '.tmp'; fs.writeFileSync(tmpFile, finalAfter, 'utf8'); fs.renameSync(tmpFile, TARGET); console.log('[patch-task3] 补丁已应用到:', TARGET); // 验证 const verify = fs.readFileSync(TARGET, 'utf8'); if (!verify.includes(SENTINEL)) { console.error('[patch-task3] 验证失败: sentinel 未找到!'); process.exit(4); } if (!verify.includes('_finalConfidence')) { console.error('[patch-task3] 验证失败: _finalConfidence 未注入!'); process.exit(5); } console.log('[patch-task3] PASS — sentinel + _finalConfidence 验证通过'); } main();