optimization-status-smoke.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #!/usr/bin/env node
  2. const fs = require('fs');
  3. const os = require('os');
  4. const path = require('path');
  5. const { spawnSync } = require('child_process');
  6. const { buildStatusSummary, findOutputEvidence, hasLiveProof } = require('./optimization-status-audit');
  7. function main() {
  8. const root = path.resolve(__dirname, '..');
  9. const summary = buildStatusSummary(root);
  10. assert(summary.items.length >= 10, 'status audit should cover the optimization plan requirements');
  11. assert(summary.counts.passed >= 1, 'status audit should report passed items');
  12. assert(summary.counts.ready_not_proven >= 1, 'status audit should report ready_not_proven items');
  13. assert(summary.counts.blocked_by_external_data >= 1, 'status audit should report external-data blockers');
  14. assert(summary.complete === false, 'status audit should not mark the long-term goal complete without live/customer proof');
  15. assert(hasRequirement(summary, '视频 A/B 严格验收'), 'status audit should track video A/B proof');
  16. assert(hasRequirement(summary, '客户选中率 30%/40%/50% 和人工补号量减少 50%'), 'status audit should track customer effect proof');
  17. assert(hasId(summary, 'video-ab-proof'), 'status audit should expose stable id for video A/B proof');
  18. assert(hasId(summary, 'intake-readiness'), 'status audit should expose stable id for intake readiness proof gate');
  19. assert(hasId(summary, 'business-proof-progress'), 'status audit should expose stable id for business proof progress sync');
  20. assert(hasId(summary, 'business-proof-next-actions'), 'status audit should expose stable id for business proof next actions');
  21. assert(hasId(summary, 'latest-form-index'), 'status audit should expose stable id for latest form index');
  22. assert(hasId(summary, 'optimization-completion'), 'status audit should expose stable id for optimization completion audit');
  23. assert(hasId(summary, 'customer-effect-proof'), 'status audit should expose stable id for customer effect proof');
  24. assert(summary.items.every(item => item.id && item.title), 'status audit items should expose id and title for software-side consumption');
  25. const handoff = getItem(summary, 'optimization-handoff');
  26. const round = getItem(summary, 'round-deposition');
  27. const evidence = getItem(summary, 'evidence-index');
  28. const latestFormIndex = getItem(summary, 'latest-form-index');
  29. const completion = getItem(summary, 'optimization-completion');
  30. assert(handoff.next.includes('round:refresh'), 'handoff status next should prefer ordered round refresh');
  31. assert(round.next.includes('round:refresh') && !round.next.includes('再刷新 evidence:index'), 'round deposition next should not instruct stale manual refresh order');
  32. assert(evidence.next.includes('round:refresh'), 'evidence index status next should prefer ordered round refresh');
  33. assert(latestFormIndex.next.includes('round:refresh'), 'latest form index status next should prefer ordered round refresh');
  34. assert(completion.next.includes('round:refresh') && completion.next.includes('optimization:completion'), 'completion status next should expose round refresh and single audit commands');
  35. assertOldClosableLiveProofIsDetected();
  36. const outputDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-optimization-status-'));
  37. const run = spawnSync(process.execPath, [path.join(root, 'scripts', 'optimization-status-audit.js'), '--output', outputDir], {
  38. cwd: root,
  39. encoding: 'utf8'
  40. });
  41. assert(run.status === 0, `optimization:status --output should pass: ${run.stderr || run.stdout}`);
  42. assert(fs.existsSync(path.join(outputDir, 'optimization-status-summary.json')), 'status audit should write summary to --output directory');
  43. assert(fs.existsSync(path.join(outputDir, 'optimization-status-report.md')), 'status audit should write report to --output directory');
  44. const written = JSON.parse(fs.readFileSync(path.join(outputDir, 'optimization-status-summary.json'), 'utf8'));
  45. assert(written.complete === false, 'written status should preserve incomplete long-term proof boundary');
  46. console.log('optimization status smoke ok');
  47. }
  48. function hasRequirement(summary, text) {
  49. return summary.items.some(item => item.requirement === text);
  50. }
  51. function hasId(summary, id) {
  52. return summary.items.some(item => item.id === id);
  53. }
  54. function getItem(summary, id) {
  55. const item = summary.items.find(entry => entry.id === id);
  56. if (!item) throw new Error(`missing status item ${id}`);
  57. return item;
  58. }
  59. function assertOldClosableLiveProofIsDetected() {
  60. const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-status-live-proof-'));
  61. const outputs = path.join(tempRoot, 'outputs');
  62. fs.mkdirSync(outputs, { recursive: true });
  63. for (let index = 0; index < 90; index += 1) {
  64. const dir = path.join(outputs, `newer-${String(index).padStart(2, '0')}`);
  65. fs.mkdirSync(dir, { recursive: true });
  66. }
  67. const liveDir = path.join(outputs, 'older-closable-live');
  68. fs.mkdirSync(liveDir, { recursive: true });
  69. fs.writeFileSync(path.join(liveDir, 'aggregate-summary.json'), JSON.stringify({
  70. manifest: { liveEnabled: true },
  71. acceptance: {
  72. overallPass: true,
  73. failedGateCount: 0,
  74. tokenLeak: false
  75. },
  76. failureCount: 0
  77. }, null, 2), 'utf8');
  78. assert(hasLiveProof(findOutputEvidence(tempRoot)), 'status audit should detect closable live proof outside a recent-directory window');
  79. }
  80. function assert(condition, message) {
  81. if (!condition) throw new Error(message);
  82. }
  83. if (require.main === module) main();