#!/usr/bin/env node const fs = require('fs'); const os = require('os'); const path = require('path'); const { spawnSync } = require('child_process'); const { buildMetrics, readCsv } = require('./review-metrics'); const root = path.resolve(__dirname, '..'); function main() { const output = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-overnight-review-')); const result = spawnSync(process.execPath, [ path.join(root, 'scripts', 'overnight-quality-campaign.js') ], { cwd: root, encoding: 'utf8', env: { ...process.env, TIHAO_OVERNIGHT_LIVE: 'false', TIHAO_OVERNIGHT_OUTPUT: output, TIHAO_OVERNIGHT_FIXTURES: 'dha-mom-baby', TIHAO_OVERNIGHT_VARIANTS: 'baseline-live,result-first', TIHAO_OVERNIGHT_MAX_RUNS: '2', TIHAO_OVERNIGHT_FAIL_ON_GATES: 'false' } }); if (result.status !== 0) { process.stderr.write(result.stderr || result.stdout || ''); throw new Error('overnight quality smoke run failed'); } const reviewCsv = path.join(output, 'manual-review-sample.csv'); const aggregateReport = path.join(output, 'aggregate-report.md'); assert(fs.existsSync(reviewCsv), 'manual-review-sample.csv should be written'); assert(fs.existsSync(aggregateReport), 'aggregate-report.md should be written'); const rows = readCsv(reviewCsv); for (const column of ['人工复核标签', '客户选择', '归因类型', '反馈原因']) { assert(rows.header.includes(column), `manual review sample should include ${column}`); } const metrics = buildMetrics({ inputPath: reviewCsv, rows }); assert(metrics.headerOk, 'manual review sample should keep software table prefix header'); assert(metrics.duplicateKeyCount === 0, 'manual review sample should have zero duplicate keys'); assert(metrics.rankContinuous, 'manual review sample ranks should be continuous per brief'); const report = fs.readFileSync(aggregateReport, 'utf8'); assert(report.includes('归因类型'), 'aggregate report should instruct failure attribution'); assert(report.includes('客户选择'), 'aggregate report should instruct customer decision labeling'); assert(report.includes('参考账号不像'), 'aggregate report should list reference mismatch label'); console.log(JSON.stringify({ ok: true, output, reviewCsv, rows: metrics.total, duplicateKeyCount: metrics.duplicateKeyCount, rankContinuous: metrics.rankContinuous }, null, 2)); } function assert(condition, message) { if (!condition) throw new Error(message); } main();