long-run-readiness-smoke.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #!/usr/bin/env node
  2. const { buildReadiness } = require('./long-run-readiness-audit');
  3. function main() {
  4. const passingPreflight = {
  5. readyForLiveAcceptance: true,
  6. readyForVideoAb: true,
  7. live: { tokenPresent: true, companyResolved: true, parseUserResolved: true },
  8. providers: { videoModel: 'doubao-seed-2-0-pro' }
  9. };
  10. const passingHistory = {
  11. acceptance: {
  12. readyForLongRun: true,
  13. readyForCustomerEffectProof: true,
  14. minBriefsMet: true,
  15. allHaveCustomerDecision: true,
  16. allHaveFeedbackReason: true,
  17. allHaveManualSupplementBaseline: true
  18. }
  19. };
  20. const passingVideoReadiness = {
  21. acceptance: { readyForVideoAbPreflight: true },
  22. counts: { realReferenceRows: 1, realCandidateRows: 1, videoUrlRows: 2 }
  23. };
  24. const passingIntakeReadiness = {
  25. acceptance: { overallReady: true, historyReady: true, videoReady: true, reviewMetricsReady: true, customerEffectReady: true },
  26. failureCount: 0
  27. };
  28. const failingIntakeReadiness = {
  29. acceptance: { overallReady: false, historyReady: false, videoReady: false, reviewMetricsReady: false, customerEffectReady: false },
  30. failureCount: 9
  31. };
  32. const noProofGaps = { unresolvedCount: 0 };
  33. const unresolvedProofGaps = { unresolvedCount: 5 };
  34. const closedProofGapClosure = { complete: true, openCount: 0 };
  35. const openProofGapClosure = { complete: false, openCount: 5 };
  36. const fullMatrix = buildReadiness({
  37. mode: 'full-matrix',
  38. preflight: passingPreflight,
  39. history: passingHistory,
  40. intakeReadiness: passingIntakeReadiness,
  41. proofGap: noProofGaps,
  42. proofGapClosure: closedProofGapClosure
  43. });
  44. assert(fullMatrix.ready, 'full matrix should be ready with passing preflight/history and no unresolved proof gaps');
  45. assert(fullMatrix.nextCommands.some(item => item.includes('proof-gap:closure')), 'full matrix next commands should include proof-gap closure audit');
  46. const fullMatrixWithBadIntake = buildReadiness({
  47. mode: 'full-matrix',
  48. preflight: passingPreflight,
  49. history: passingHistory,
  50. intakeReadiness: failingIntakeReadiness,
  51. proofGap: noProofGaps,
  52. proofGapClosure: closedProofGapClosure
  53. });
  54. assert(!fullMatrixWithBadIntake.ready, 'failing intake readiness should block full matrix readiness when provided');
  55. assert(fullMatrixWithBadIntake.checks.some(item => item.name === 'intake-readiness-overall-ready' && item.status === 'fail'), 'intake readiness failure should be explicit');
  56. const fullMatrixWithGaps = buildReadiness({
  57. mode: 'full-matrix',
  58. preflight: passingPreflight,
  59. history: passingHistory,
  60. proofGap: unresolvedProofGaps,
  61. proofGapClosure: null
  62. });
  63. assert(!fullMatrixWithGaps.ready, 'unresolved proof gaps should block full matrix readiness');
  64. assert(fullMatrixWithGaps.checks.some(item => item.name === 'proof-gap-unresolved-zero' && item.status === 'fail'), 'proof gap check should fail when unresolved gaps remain');
  65. const fullMatrixWithStaleRequestButClosedClosure = buildReadiness({
  66. mode: 'full-matrix',
  67. preflight: passingPreflight,
  68. history: passingHistory,
  69. intakeReadiness: passingIntakeReadiness,
  70. proofGap: unresolvedProofGaps,
  71. proofGapClosure: closedProofGapClosure
  72. });
  73. assert(fullMatrixWithStaleRequestButClosedClosure.ready, 'current proof-gap closure should supersede stale proof-gap request unresolved count');
  74. const fullMatrixWithOpenClosure = buildReadiness({
  75. mode: 'full-matrix',
  76. preflight: passingPreflight,
  77. history: passingHistory,
  78. intakeReadiness: passingIntakeReadiness,
  79. proofGap: noProofGaps,
  80. proofGapClosure: openProofGapClosure
  81. });
  82. assert(!fullMatrixWithOpenClosure.ready, 'open proof-gap closure should block full matrix readiness even when proof-gap request has no unresolved items');
  83. assert(fullMatrixWithOpenClosure.checks.some(item => item.name === 'proof-gap-closure-complete' && item.status === 'fail'), 'open proof-gap closure should fail explicitly');
  84. assert(fullMatrixWithOpenClosure.boundaries.some(item => item.includes('proof-gap:closure')), 'open proof-gap closure should add an explicit boundary');
  85. const videoAb = buildReadiness({
  86. mode: 'video-ab',
  87. preflight: passingPreflight,
  88. history: null,
  89. intakeReadiness: passingIntakeReadiness,
  90. videoReadiness: passingVideoReadiness
  91. });
  92. assert(videoAb.ready, 'video A/B should be ready with passing video preflight and video resource readiness');
  93. const missingVideoReadiness = buildReadiness({
  94. mode: 'video-ab',
  95. preflight: passingPreflight,
  96. history: null,
  97. videoReadiness: null
  98. });
  99. assert(!missingVideoReadiness.ready, 'video A/B should require video resource readiness summary');
  100. assert(missingVideoReadiness.checks.some(item => item.name === 'video-resource-readiness-present' && item.status === 'fail'), 'missing video readiness should fail');
  101. const missingCandidateVideo = buildReadiness({
  102. mode: 'video-ab',
  103. preflight: passingPreflight,
  104. history: null,
  105. videoReadiness: {
  106. acceptance: { readyForVideoAbPreflight: false },
  107. counts: { realReferenceRows: 1, realCandidateRows: 0, videoUrlRows: 1 }
  108. }
  109. });
  110. assert(!missingCandidateVideo.ready, 'missing real candidate video should block video A/B readiness');
  111. assert(missingCandidateVideo.checks.some(item => item.name === 'video-real-candidate-present' && item.status === 'fail'), 'missing real candidate video should be explicit');
  112. const currentVideoReadinessShape = buildReadiness({
  113. mode: 'video-ab',
  114. preflight: passingPreflight,
  115. history: null,
  116. videoReadiness: {
  117. readyForVideoAbPreflight: true,
  118. counts: { realReferenceRows: 1, realCandidateRows: 1, videoUrlRows: 2 }
  119. }
  120. });
  121. assert(currentVideoReadinessShape.ready, 'video A/B readiness should accept current top-level readyForVideoAbPreflight summary shape');
  122. const missingHistory = buildReadiness({
  123. mode: 'customer-effect',
  124. preflight: passingPreflight,
  125. history: null,
  126. proofGap: noProofGaps,
  127. proofGapClosure: closedProofGapClosure
  128. });
  129. assert(!missingHistory.ready, 'customer effect proof should require history audit');
  130. assert(missingHistory.checks.some(item => item.name === 'history-audit-present' && item.status === 'fail'), 'missing history should fail');
  131. const badVideo = buildReadiness({
  132. mode: 'video-ab',
  133. preflight: { ...passingPreflight, readyForVideoAb: false, providers: { videoModel: 'other-model' } },
  134. history: null,
  135. videoReadiness: passingVideoReadiness
  136. });
  137. assert(!badVideo.ready, 'bad video model should block video A/B readiness');
  138. console.log(JSON.stringify({ ok: true }, null, 2));
  139. }
  140. function assert(condition, message) {
  141. if (!condition) throw new Error(message);
  142. }
  143. if (require.main === module) main();