#!/usr/bin/env node const fs = require('fs'); const os = require('os'); const path = require('path'); const { runTihaoSourcing } = require('../mcp/src/tools/tihao-brief-sourcing-run'); const { rankCreators } = require('../mcp/src/features/tihao-sourcing/ranker'); async function main() { const output = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-reference-rules-')); const result = await runTihaoSourcing({ collectionMode: 'sample', briefText: [ '客户名称:花漾肌研', '产品:敏感肌屏障修护精华', '平台:小红书', '参考账号:一个是专业成分科普,一个是轻娱乐剧情种草。', '关键词:敏感肌、屏障、修护、成分党、真实体验', '偏好真实体验、素人感、成分拆解,不要硬广。' ].join('\n'), referenceStyleFingerprints: [ { referenceId: 'ref-professional-science', url: 'https://www.xiaohongshu.com/explore/ref-professional-science', platform: 'xiaohongshu', contentType: 'image_text', accountName: '专业成分科普号', personaType: '专业成分党', contentStructure: '成分解释-功效边界-使用建议', tone: '理性科普、低情绪', title: '敏感肌屏障修护怎么选' }, { referenceId: 'ref-light-entertainment', url: 'https://www.xiaohongshu.com/explore/ref-light-entertainment', platform: 'xiaohongshu', contentType: 'video', accountName: '轻娱乐剧情种草号', personaType: '剧情生活方式', contentStructure: '剧情冲突-夸张反应-种草转折', tone: '轻娱乐、情绪化、剧情感', title: '办公室女孩的护肤翻车剧情', asrText: '用剧情方式展示护肤翻车和修护体验', frameUrls: ['https://cdn.example.test/reference-frame.jpg'] } ], output }); assert(result.status === 'ok', 'reference rules sample should run ok'); const usability = result.data.criteria.referenceUsability || {}; assert(usability.status === 'reference_conflict', 'conflicting reference fingerprints should be marked as reference_conflict'); assert(usability.conflict === true, 'reference usability should mark conflict=true'); assert(String(usability.note || '').includes('不能强行合并'), 'reference conflict note should prevent forced unified standard'); const reportPath = path.join(output, 'tihao-sourcing-report.md'); const report = fs.readFileSync(reportPath, 'utf8'); assert(report.includes('reference_conflict'), 'report should expose reference conflict status'); assert(report.includes('不能强行合并为单一调性标准'), 'report should explain that conflicting references cannot be merged'); const strong = (result.data.candidates || []).filter(item => item.recommendStatus === '强推荐'); assert(strong.length >= 1, 'sample should still produce strong candidates'); assert(strong.every(item => (item.briefHitConditions || []).length >= 2), 'strong candidates should have at least two brief hit conditions'); assert(strong.every(item => ((item.referenceStyleHitPoints || []).length + (item.homepageEvidenceHitPoints || []).length) >= 1), 'strong candidates should have reference style or homepage evidence'); assert(strong.every(item => !(item.referenceStyleHitPoints || []).some(point => /待补|需补/.test(String(point)))), 'strong reference style hit points should not contain placeholder evidence'); assert(strong.every(item => String(item.recommendReason || '').includes('参考/风格命中')), 'strong candidate reasons should explain reference/style evidence'); assert(strong.every(item => String(item.recommendReason || '').includes('主页证据命中')), 'strong candidate reasons should explain homepage evidence'); const weakReferenceOnly = rankCreators([{ platform: 'xiaohongshu', platformUserId: 'weak-reference-placeholder', displayName: '泛生活方式弱参考号', profileUrl: 'https://www.xiaohongshu.com/user/profile/weak-reference-placeholder', fansCount: 90000, minPrice: 7000, contentTags: ['护肤', '女性', '生活方式'], personaTags: ['好物分享'], recentEvidence: ['近期内容泛生活方式,没有命中参考账号调性'] }], { brand: '花漾肌研', category: '护肤', platforms: ['xiaohongshu'], keywords: ['护肤', '女性'], stylePreferences: [], referenceSignals: ['专业成分党', '低情绪理性科普'], referenceLinks: [{ url: 'https://www.xiaohongshu.com/user/profile/ref-account', platform: 'xiaohongshu' }], fanRange: { min: 10000, max: 500000 }, budgetRange: { min: 3000, max: 10000 } })[0]; assert((weakReferenceOnly.referenceFallbackHitPoints || []).some(point => /需补/.test(String(point))), 'weak reference candidate should keep fallback reference hint'); assert((weakReferenceOnly.referenceStyleHitPoints || []).length === 0, 'fallback reference hints should not enter concrete reference style hit points'); assert(weakReferenceOnly.referenceEvidenceConcrete === false, 'weak reference candidate should mark reference evidence as non-concrete'); assert(weakReferenceOnly.recommendStatus !== '强推荐', 'weak placeholder reference evidence should not be enough for strong recommendation'); console.log(JSON.stringify({ ok: true, output, referenceStatus: usability.status, strong: strong.length }, null, 2)); } function assert(condition, message) { if (!condition) throw new Error(message); } main().catch(error => { console.error(error && error.stack ? error.stack : String(error)); process.exit(1); });