#!/usr/bin/env node /** * P0 端到端冒烟测试 — 验证完整路由管道 */ const ra = require('./route-analyzer.js'); const rt = require('./route-telemetry.js'); const fs = require('fs'); const path = require('path'); const idxFile = path.join(__dirname, '..', 'skills-index.json'); if (!fs.existsSync(idxFile)) { console.log('⊘ 无编译索引 (skill-index-compiled.json),跳过端到端测试'); process.exit(0); } const index = JSON.parse(fs.readFileSync(idxFile, 'utf8')); console.log(`索引加载: ${index.skills.length} 技能\n`); const testQueries = [ 'debug React component performance issue', '帮我写一个 Python 爬虫', 'review this PR for security vulnerabilities', '部署 Docker 到 K8s', ]; let pass = 0; for (const query of testQueries) { try { const tokens = ra.tokenize(query); const bm25 = ra.buildBM25Params(index); const results = index.skills.map(s => { const { totalScore } = ra.scoreSkill(s, tokens, bm25); return { name: s.name, score: Math.round(totalScore * 100) / 100 }; }).sort((a, b) => b.score - a.score); // 消歧 const { results: disamb, firedRules } = ra.applyDisambiguation(results, query, index); // 冷启动 const stats = rt.getSkillRouteStats(30); const { boostedSkills } = ra.applyColdStartBoost(disamb, stats); // 归一化 const norm = ra.normalizeScores(disamb).slice(0, 3); const top = norm[0]?.name || 'none'; const conf = ((norm[0]?.confidence || 0) * 100).toFixed(0); const rules = firedRules.length > 0 ? firedRules.join(',') : '-'; const cold = (boostedSkills && boostedSkills.length > 0) ? boostedSkills.join(',') : '-'; console.log(`✓ "${query.slice(0, 40)}"`); console.log(` → ${top} (${conf}%) | rules: ${rules} | cold: ${cold}`); pass++; } catch (err) { console.log(`✗ "${query.slice(0, 40)}": ${err.message}`); } } console.log(`\n${pass}/${testQueries.length} 通过`); process.exit(pass === testQueries.length ? 0 : 1);