| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- #!/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();
|