#!/usr/bin/env node const fs = require('fs'); const os = require('os'); const path = require('path'); const { spawnSync } = require('child_process'); const { buildStatusSummary, findOutputEvidence, hasLiveProof } = require('./optimization-status-audit'); function main() { const root = path.resolve(__dirname, '..'); const summary = buildStatusSummary(root); assert(summary.items.length >= 10, 'status audit should cover the optimization plan requirements'); assert(summary.counts.passed >= 1, 'status audit should report passed items'); assert(summary.counts.ready_not_proven >= 1, 'status audit should report ready_not_proven items'); assert(summary.counts.blocked_by_external_data >= 1, 'status audit should report external-data blockers'); assert(summary.complete === false, 'status audit should not mark the long-term goal complete without live/customer proof'); assert(hasRequirement(summary, '视频 A/B 严格验收'), 'status audit should track video A/B proof'); assert(hasRequirement(summary, '客户选中率 30%/40%/50% 和人工补号量减少 50%'), 'status audit should track customer effect proof'); assert(hasId(summary, 'video-ab-proof'), 'status audit should expose stable id for video A/B proof'); assert(hasId(summary, 'intake-readiness'), 'status audit should expose stable id for intake readiness proof gate'); assert(hasId(summary, 'business-proof-progress'), 'status audit should expose stable id for business proof progress sync'); assert(hasId(summary, 'business-proof-next-actions'), 'status audit should expose stable id for business proof next actions'); assert(hasId(summary, 'latest-form-index'), 'status audit should expose stable id for latest form index'); assert(hasId(summary, 'optimization-completion'), 'status audit should expose stable id for optimization completion audit'); assert(hasId(summary, 'customer-effect-proof'), 'status audit should expose stable id for customer effect proof'); assert(summary.items.every(item => item.id && item.title), 'status audit items should expose id and title for software-side consumption'); const handoff = getItem(summary, 'optimization-handoff'); const round = getItem(summary, 'round-deposition'); const evidence = getItem(summary, 'evidence-index'); const latestFormIndex = getItem(summary, 'latest-form-index'); const completion = getItem(summary, 'optimization-completion'); assert(handoff.next.includes('round:refresh'), 'handoff status next should prefer ordered round refresh'); assert(round.next.includes('round:refresh') && !round.next.includes('再刷新 evidence:index'), 'round deposition next should not instruct stale manual refresh order'); assert(evidence.next.includes('round:refresh'), 'evidence index status next should prefer ordered round refresh'); assert(latestFormIndex.next.includes('round:refresh'), 'latest form index status next should prefer ordered round refresh'); assert(completion.next.includes('round:refresh') && completion.next.includes('optimization:completion'), 'completion status next should expose round refresh and single audit commands'); assertOldClosableLiveProofIsDetected(); const outputDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-optimization-status-')); const run = spawnSync(process.execPath, [path.join(root, 'scripts', 'optimization-status-audit.js'), '--output', outputDir], { cwd: root, encoding: 'utf8' }); assert(run.status === 0, `optimization:status --output should pass: ${run.stderr || run.stdout}`); assert(fs.existsSync(path.join(outputDir, 'optimization-status-summary.json')), 'status audit should write summary to --output directory'); assert(fs.existsSync(path.join(outputDir, 'optimization-status-report.md')), 'status audit should write report to --output directory'); const written = JSON.parse(fs.readFileSync(path.join(outputDir, 'optimization-status-summary.json'), 'utf8')); assert(written.complete === false, 'written status should preserve incomplete long-term proof boundary'); console.log('optimization status smoke ok'); } function hasRequirement(summary, text) { return summary.items.some(item => item.requirement === text); } function hasId(summary, id) { return summary.items.some(item => item.id === id); } function getItem(summary, id) { const item = summary.items.find(entry => entry.id === id); if (!item) throw new Error(`missing status item ${id}`); return item; } function assertOldClosableLiveProofIsDetected() { const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-status-live-proof-')); const outputs = path.join(tempRoot, 'outputs'); fs.mkdirSync(outputs, { recursive: true }); for (let index = 0; index < 90; index += 1) { const dir = path.join(outputs, `newer-${String(index).padStart(2, '0')}`); fs.mkdirSync(dir, { recursive: true }); } const liveDir = path.join(outputs, 'older-closable-live'); fs.mkdirSync(liveDir, { recursive: true }); fs.writeFileSync(path.join(liveDir, 'aggregate-summary.json'), JSON.stringify({ manifest: { liveEnabled: true }, acceptance: { overallPass: true, failedGateCount: 0, tokenLeak: false }, failureCount: 0 }, null, 2), 'utf8'); assert(hasLiveProof(findOutputEvidence(tempRoot)), 'status audit should detect closable live proof outside a recent-directory window'); } function assert(condition, message) { if (!condition) throw new Error(message); } if (require.main === module) main();