| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- #!/usr/bin/env node
- const fs = require('fs');
- const os = require('os');
- const path = require('path');
- const {
- buildCompletionSummary,
- renderReport,
- bestHistoryAudit,
- bestCustomerEffectSummary
- } = require('./optimization-completion-audit');
- function main() {
- const historyAuditPath = path.join('outputs', 'history-audit-latest', 'historical-dataset-audit.json');
- const staleHistoryAuditPath = path.join('outputs', 'stale-history-audit', 'historical-dataset-audit.json');
- const sourceFiles = { history: historyAuditPath };
- const passingHistory = passingHistoryAudit();
- const open = buildCompletionSummary({
- root: process.cwd(),
- outputsDir: 'outputs',
- intakeReadiness: { acceptance: { overallReady: false }, failureCount: 9 },
- videoReadiness: { acceptance: { readyForVideoAbPreflight: false }, failureCount: 1, counts: { realCandidateRows: 0 } },
- proofGapClosure: { complete: false, openCount: 5, closedCount: 0 },
- handoff: { complete: false, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [{ id: 'video-ab-proof' }], externalBlockers: [{ id: 'customer-effect-proof' }] },
- businessProgress: { complete: false, counts: { pass: 3, fail: 2, pending: 3, blocked_by_external_data: 7 } },
- longRunReadiness: { ready: false, counts: { pass: 6, fail: 7 } },
- videoAb: { acceptance: { passed: true }, enhanced: { provider: { evidence: { providerStatus: 'ok' } } } },
- overnight: { manifest: { liveEnabled: false }, acceptance: { overallPass: false, failedGateCount: 0 }, failureCount: 0 },
- customerEffect: null,
- optimizationPipeline: null
- });
- assert(open.complete === false, 'open fixture should not be complete');
- assert(open.readyForClaim === false, 'open fixture should not be ready for claim');
- assert(open.proofGapOpenCount === 5, `proof gap open count should be 5, got ${open.proofGapOpenCount}`);
- assert(open.intakeFailureCount === 9, 'should expose intake failure count');
- assert(open.videoResourceFailureCount === 1, 'should expose video resource failure count');
- assert(open.realCandidateRows === 0, 'should expose zero real candidate rows');
- assert(open.materialType === 'optimization_completion_audit', 'should expose completion audit material type');
- assert(open.directCustomerProof === false, 'completion audit itself should not be direct customer proof');
- assert(open.proofLevel === 'not_business_proof', 'open fixture should stay not_business_proof');
- assert(open.blockingReasons.length >= 5, 'open fixture should expose blocking reasons');
- assert(open.blockingReasonCount === open.blockingReasons.length, 'should expose top-level blocking reason count');
- assert(open.blockingReasonsWithMissingProofRequirements === open.blockingReasons.length, 'each open blocker should carry missing proof requirements');
- assert(open.missingProofRequirementCount >= open.blockingReasonCount, 'should expose unique missing proof requirement count');
- assert(open.canClaim.tihaoRateImproved === false, 'should not allow tihao-rate claim');
- assert(open.canClaim.customerEffectAchieved === false, 'should not allow customer-effect claim');
- assert(open.canClaim.manualSupplementReduced === false, 'should not allow manual-supplement claim');
- assert(open.forbiddenClaimsWhenIncomplete.includes('提号率已经提升'), 'should list forbidden tihao claim');
- assert(open.guardrails.some(item => item.includes('不是业务证明')), 'should keep proof boundary guardrail');
- const blockedGates = open.gates.filter(item => item.status === 'blocked');
- assert(blockedGates.length === open.blockingReasons.length, 'blocked gates should match blocking reasons');
- assert(blockedGates.every(item => Array.isArray(item.missingProofRequirements) && item.missingProofRequirements.length >= 1), 'every blocked gate should explain missing proof requirements');
- assert(open.blockingReasons.every(item => Array.isArray(item.missingProofRequirements) && item.missingProofRequirements.length >= 1), 'every blocking reason should carry missing proof requirements');
- const proofGapGate = open.gates.find(item => item.id === 'proof-gap-closure');
- assert(proofGapGate.missingProofRequirements.includes('proofGapClosure.complete=true'), 'proof-gap gate should require complete=true');
- assert(proofGapGate.missingProofRequirements.includes('proofGapClosure.openCount=0'), 'proof-gap gate should require openCount=0');
- const fakeVideoGate = open.gates.find(item => item.id === 'video-ab-live-proof');
- assert(fakeVideoGate.status === 'blocked', 'video A/B without proof context should stay blocked');
- assert(fakeVideoGate.missingProofRequirements.includes('proofContext.mode=live'), 'should explain missing live mode');
- const preflightVideo = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- videoAb: { acceptance: { passed: true }, enhanced: { provider: { evidence: { providerStatus: 'ok' } } } },
- videoAbPreflight: failedVideoAbPreflight()
- });
- assert(preflightVideo.complete === false, 'video A/B preflight failure context should keep completion blocked until live proof exists');
- assert(preflightVideo.videoAbPreflightReadyForVideoAb === false, 'completion should expose video A/B preflight readiness');
- assert(preflightVideo.videoAbPreflightFailureCount === 4, 'completion should expose video A/B preflight failure count');
- const preflightVideoGate = preflightVideo.gates.find(item => item.id === 'video-ab-live-proof');
- assert(preflightVideoGate.status === 'blocked', 'video A/B gate should remain blocked with preflight failure only');
- assert(preflightVideoGate.evidence.includes('preflight.readyForVideoAb=false'), 'video A/B gate should show preflight readiness');
- assert(preflightVideoGate.evidence.includes('runtimeCredentialPresent=false'), 'video A/B gate should show credential presence only');
- assert(preflightVideoGate.missingProofRequirements.includes('videoAbPreflight.readyForVideoAb=true'), 'video A/B gate should require preflight readiness before live proof can run');
- assert(preflightVideoGate.missingProofRequirements.includes('videoAbPreflight.company resolved for live run'), 'video A/B gate should include preflight missing company context');
- const liveVideoWithStalePreflight = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- videoAb: passingVideoAb(),
- videoAbPreflight: failedVideoAbPreflight()
- });
- assert(liveVideoWithStalePreflight.complete === true, 'passing live video A/B proof should not be blocked by an older preflight failure');
- const liveVideoGate = liveVideoWithStalePreflight.gates.find(item => item.id === 'video-ab-live-proof');
- assert(liveVideoGate.status === 'pass', 'passing live video A/B proof should pass');
- assert(!liveVideoGate.evidence.includes('preflight.readyForVideoAb=false'), 'passing live video proof should not foreground stale preflight failure context');
- const tokenLeakOvernight = buildCompletionSummary({
- root: process.cwd(),
- outputsDir: 'outputs',
- sourceFiles,
- history: passingHistory,
- intakeReadiness: { acceptance: { overallReady: true, historyReady: true, videoReady: true, reviewMetricsReady: true, customerEffectReady: true }, failureCount: 0 },
- videoReadiness: { acceptance: { readyForVideoAbPreflight: true }, failureCount: 0, counts: { realReferenceRows: 1, realCandidateRows: 2, videoUrlRows: 2 } },
- proofGapClosure: passingProofGapClosure(),
- handoff: { complete: true, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [], externalBlockers: [] },
- businessProgress: passingBusinessProgress(),
- longRunReadiness: { ready: true, counts: { pass: 13, fail: 0 } },
- videoAb: {
- acceptance: { passed: true },
- proofContext: {
- mode: 'live',
- collectionMode: 'live',
- generatedBy: 'acceptance:video-ab',
- requiresRuntimeCredential: true,
- requiresVocSocialProvider: true,
- requiresVideoAnalysisProvider: true
- },
- enhanced: { provider: { evidence: { providerStatus: 'ok' } } }
- },
- overnight: { manifest: { liveEnabled: true }, acceptance: { overallPass: true, failedGateCount: 0, tokenLeak: true }, failureCount: 0 },
- customerEffect: passingCustomerEffect(historyAuditPath),
- optimizationPipeline: passingOptimizationPipeline()
- });
- const tokenLeakGate = tokenLeakOvernight.gates.find(item => item.id === 'live-provider-overnight-proof');
- assert(tokenLeakOvernight.complete === false, 'token leak overnight fixture should not be complete');
- assert(tokenLeakOvernight.readyForClaim === false, 'token leak overnight fixture should not be ready for claim');
- assert(tokenLeakGate.status === 'blocked', 'token leak overnight gate should be blocked');
- assert(tokenLeakGate.missingProofRequirements.includes('acceptance.tokenLeak=false'), 'token leak overnight gate should explain missing tokenLeak=false');
- const stalePipeline = buildCompletionSummary({
- root: process.cwd(),
- outputsDir: 'outputs',
- intakeReadiness: { generatedAt: '2026-06-11T02:48:47.000Z', acceptance: { overallReady: false }, failureCount: 6 },
- videoReadiness: { generatedAt: '2026-06-11T02:48:47.000Z', acceptance: { readyForVideoAbPreflight: true }, failureCount: 0, counts: { realReferenceRows: 1, realCandidateRows: 1, videoUrlRows: 2 } },
- proofGapClosure: { generatedAt: '2026-06-11T02:48:47.000Z', complete: false, openCount: 3, closedCount: 2 },
- handoff: { complete: false, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [{ id: 'video-ab-proof' }], externalBlockers: [{ id: 'customer-effect-proof' }] },
- businessProgress: { complete: false, counts: { pass: 5, fail: 2, pending: 3, blocked_by_external_data: 5 } },
- longRunReadiness: { ready: false, counts: { pass: 3, fail: 6 } },
- videoAb: { acceptance: { passed: true }, enhanced: { provider: { evidence: { providerStatus: 'ok' } } } },
- overnight: { manifest: { liveEnabled: true }, acceptance: { overallPass: true, failedGateCount: 0 }, failureCount: 0 },
- customerEffect: null,
- optimizationPipeline: {
- generatedAt: '2026-06-07T08:59:39.000Z',
- readyForClaim: false,
- proofGapClosure: { complete: false, openCount: 5 },
- results: [{ id: 'history-audit', status: 'fail' }]
- }
- });
- const stalePipelineGate = stalePipeline.gates.find(item => item.id === 'optimization-pipeline');
- assert(stalePipelineGate.status === 'blocked', 'stale optimization pipeline should stay blocked');
- assert(stalePipelineGate.evidence.includes('stale=true'), 'stale optimization pipeline should be visible in evidence');
- assert(stalePipelineGate.missingProofRequirements.includes('optimizationPipeline.generatedAt>=currentProofSources'), 'stale optimization pipeline should require rerun after current proof sources');
- const thinIntake = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- intakeReadiness: { acceptance: { overallReady: true, historyReady: false, videoReady: true, reviewMetricsReady: true, customerEffectReady: true }, failureCount: 0 }
- });
- const thinIntakeGate = thinIntake.gates.find(item => item.id === 'intake-readiness');
- assert(thinIntake.complete === false, 'thin intake summary should keep completion blocked');
- assert(thinIntakeGate.missingProofRequirements.includes('acceptance.historyReady=true'), 'thin intake should require history readiness');
- const thinTopLevelHistory = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- history: { generatedAt: '2026-06-11T02:48:48.000Z', briefCount: 5, acceptance: { readyForCustomerEffectProof: true } }
- });
- const thinTopLevelHistoryGate = thinTopLevelHistory.gates.find(item => item.id === 'customer-effect-proof');
- assert(thinTopLevelHistory.complete === false, 'history audit with only top-level ready flag should keep completion blocked');
- assert(thinTopLevelHistoryGate.missingProofRequirements.includes('currentHistoryAudit.acceptance.allHaveManualFinalList=true'), 'thin history should require manual final-list coverage');
- assert(thinTopLevelHistoryGate.missingProofRequirements.includes('currentHistoryAudit.items.length>=5'), 'thin history should include auditable item details');
- const thinVideoResource = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- videoReadiness: { acceptance: { readyForVideoAbPreflight: true }, failureCount: 0, counts: { realCandidateRows: 1 } }
- });
- const thinVideoResourceGate = thinVideoResource.gates.find(item => item.id === 'video-resource-readiness');
- assert(thinVideoResource.complete === false, 'thin video resource summary should keep completion blocked');
- assert(thinVideoResourceGate.missingProofRequirements.includes('counts.realReferenceRows>=1'), 'thin video resource should require real reference rows');
- assert(thinVideoResourceGate.missingProofRequirements.includes('counts.videoUrlRows>=1'), 'thin video resource should require video URL rows');
- const thinProofGapClosure = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- proofGapClosure: { complete: true, openCount: 0, closedCount: 3 }
- });
- const thinProofGapClosureGate = thinProofGapClosure.gates.find(item => item.id === 'proof-gap-closure');
- assert(thinProofGapClosure.complete === false, 'thin proof-gap closure summary should keep completion blocked');
- assert(thinProofGapClosureGate.missingProofRequirements.includes('proofGapClosure.closedCount>=5'), 'thin proof-gap closure should require all 5 business gaps closed');
- const thinProofGapRows = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- proofGapClosure: { complete: true, openCount: 0, closedCount: 5, businessGapCount: 5 }
- });
- const thinProofGapRowsGate = thinProofGapRows.gates.find(item => item.id === 'proof-gap-closure');
- assert(thinProofGapRows.complete === false, 'proof-gap closure without business rows should keep completion blocked');
- assert(thinProofGapRowsGate.missingProofRequirements.includes('proofGapClosure.businessRows.length>=5'), 'proof-gap closure should include business row details');
- const looseHandoff = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- handoff: { complete: true, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [{ id: 'video-ab-proof' }], externalBlockers: [] }
- });
- const looseHandoffGate = looseHandoff.gates.find(item => item.id === 'handoff-complete');
- assert(looseHandoff.complete === false, 'handoff with ready-not-proven items should keep completion blocked');
- assert(looseHandoffGate.missingProofRequirements.includes('handoff.readyNotProven.length=0'), 'handoff should require zero ready-not-proven rows');
- const looseBusinessProgress = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- businessProgress: { complete: true, counts: { pass: 14, fail: 0, pending: 0, blocked_by_external_data: 1 } }
- });
- const looseBusinessProgressGate = looseBusinessProgress.gates.find(item => item.id === 'business-proof-progress');
- assert(looseBusinessProgress.complete === false, 'business progress with blocked rows should keep completion blocked');
- assert(looseBusinessProgressGate.missingProofRequirements.includes('businessProofProgress.counts.blocked_by_external_data=0'), 'business progress should require zero blocked rows');
- const thinBusinessProgressRows = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- businessProgress: { complete: true, counts: { pass: 15, fail: 0, pending: 0, blocked_by_external_data: 0 } }
- });
- const thinBusinessProgressRowsGate = thinBusinessProgressRows.gates.find(item => item.id === 'business-proof-progress');
- assert(thinBusinessProgressRows.complete === false, 'business progress without 15 rows should keep completion blocked');
- assert(thinBusinessProgressRowsGate.missingProofRequirements.includes('businessProofProgress.rows.length>=15'), 'business progress should include 15 step rows');
- const thinOptimizationPipelineProofGap = buildCompletionSummary({
- ...passingCompletionBase({ historyAuditPath, sourceFiles, history: passingHistory }),
- optimizationPipeline: { readyForClaim: true, generatedAt: '2026-06-11T02:48:49.000Z', proofGapClosure: { complete: true, openCount: 0 } }
- });
- const thinOptimizationPipelineGate = thinOptimizationPipelineProofGap.gates.find(item => item.id === 'optimization-pipeline');
- assert(thinOptimizationPipelineProofGap.complete === false, 'pipeline with thin proof-gap closure should keep completion blocked');
- assert(thinOptimizationPipelineGate.missingProofRequirements.includes('optimizationPipeline.proofGapClosure.closedCount>=5'), 'pipeline should require closedCount>=5 from proof-gap closure');
- const thinCustomerEffect = buildCompletionSummary({
- root: process.cwd(),
- outputsDir: 'outputs',
- sourceFiles,
- history: passingHistory,
- intakeReadiness: { acceptance: { overallReady: true, historyReady: true, videoReady: true, reviewMetricsReady: true, customerEffectReady: true }, failureCount: 0 },
- videoReadiness: { acceptance: { readyForVideoAbPreflight: true }, failureCount: 0, counts: { realReferenceRows: 1, realCandidateRows: 2, videoUrlRows: 2 } },
- proofGapClosure: passingProofGapClosure(),
- handoff: { complete: true, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [], externalBlockers: [] },
- businessProgress: passingBusinessProgress(),
- longRunReadiness: { ready: true, counts: { pass: 13, fail: 0 } },
- videoAb: passingVideoAb(),
- overnight: { manifest: { liveEnabled: true }, acceptance: { overallPass: true, failedGateCount: 0 }, failureCount: 0 },
- customerEffect: { acceptance: { overallPass: true }, customerSelectedRate: 0.5, manualSupplementReductionRate: 0.5, historyAuditPath },
- optimizationPipeline: passingOptimizationPipeline()
- });
- const thinCustomerEffectGate = thinCustomerEffect.gates.find(item => item.id === 'customer-effect-proof');
- assert(thinCustomerEffect.complete === false, 'thin customer-effect summary should keep completion blocked');
- assert(thinCustomerEffect.readyForClaim === false, 'thin customer-effect summary should not be ready for claim');
- assert(thinCustomerEffectGate.missingProofRequirements.includes('acceptance.reviewMetricsOverallUsable=true'), 'thin customer-effect summary should require review metrics usability');
- const mismatchedCustomerEffect = buildCompletionSummary({
- root: process.cwd(),
- outputsDir: 'outputs',
- sourceFiles,
- history: passingHistory,
- intakeReadiness: { acceptance: { overallReady: true }, failureCount: 0 },
- videoReadiness: { acceptance: { readyForVideoAbPreflight: true }, failureCount: 0, counts: { realReferenceRows: 1, realCandidateRows: 2, videoUrlRows: 2 } },
- proofGapClosure: passingProofGapClosure(),
- handoff: { complete: true, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [], externalBlockers: [] },
- businessProgress: passingBusinessProgress(),
- longRunReadiness: { ready: true, counts: { pass: 13, fail: 0 } },
- videoAb: passingVideoAb(),
- overnight: { manifest: { liveEnabled: true }, acceptance: { overallPass: true, failedGateCount: 0 }, failureCount: 0 },
- customerEffect: passingCustomerEffect(staleHistoryAuditPath),
- optimizationPipeline: passingOptimizationPipeline()
- });
- const mismatchedCustomerEffectGate = mismatchedCustomerEffect.gates.find(item => item.id === 'customer-effect-proof');
- assert(mismatchedCustomerEffect.complete === false, 'customer-effect summary bound to stale history should keep completion blocked');
- assert(mismatchedCustomerEffectGate.missingProofRequirements.includes('historyAuditPath=current-history-audit'), 'customer-effect summary should bind to current history audit path');
- const report = renderReport(open);
- assert(report.includes('是否完成:否'), 'report should render incomplete status');
- assert(report.includes('是否可声明业务效果:否'), 'report should render claim status');
- assert(report.includes('证明等级:not_business_proof'), 'report should render proof level');
- assert(report.includes('直接客户证明:否'), 'report should render direct customer proof boundary');
- assert(report.includes('缺失证明要求唯一计数'), 'report should render missing proof count');
- assert(report.includes('提号率提升:不可声明'), 'report should render forbidden tihao claim');
- assert(report.includes('客户效果达标:不可声明'), 'report should render forbidden customer claim');
- assert(report.includes('人工补号量下降:不可声明'), 'report should render forbidden supplement claim');
- assert(!/sk-[A-Za-z0-9_-]{8,}/.test(report), 'report should not include model token patterns');
- assert(!/r:[A-Za-z0-9]{20,}/.test(report), 'report should not include session token patterns');
- assert(!/Authorization\s*[:=]\s*Bearer/i.test(report), 'report should not expose authorization values');
- const closed = buildCompletionSummary({
- root: process.cwd(),
- outputsDir: 'outputs',
- sourceFiles,
- history: passingHistory,
- intakeReadiness: { acceptance: { overallReady: true, historyReady: true, videoReady: true, reviewMetricsReady: true, customerEffectReady: true }, failureCount: 0 },
- videoReadiness: { acceptance: { readyForVideoAbPreflight: true }, failureCount: 0, counts: { realReferenceRows: 1, realCandidateRows: 2, videoUrlRows: 2 } },
- proofGapClosure: passingProofGapClosure(),
- handoff: { complete: true, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [], externalBlockers: [] },
- businessProgress: passingBusinessProgress(),
- longRunReadiness: { ready: true, counts: { pass: 13, fail: 0 } },
- videoAb: {
- acceptance: { passed: true },
- proofContext: {
- mode: 'live',
- collectionMode: 'live',
- generatedBy: 'acceptance:video-ab',
- requiresRuntimeCredential: true,
- requiresVocSocialProvider: true,
- requiresVideoAnalysisProvider: true
- },
- enhanced: { provider: { evidence: { providerStatus: 'ok' } } }
- },
- overnight: { manifest: { liveEnabled: true }, acceptance: { overallPass: true, failedGateCount: 0 }, failureCount: 0 },
- customerEffect: passingCustomerEffect(historyAuditPath),
- optimizationPipeline: passingOptimizationPipeline()
- });
- assert(closed.complete === true, 'closed fixture should be complete');
- assert(closed.readyForClaim === true, 'closed fixture should be ready for claim');
- assert(closed.proofLevel === 'real_evidence', 'closed fixture should be evidence-level claimable');
- assert(closed.directCustomerProof === false, 'completion audit remains an audit artifact');
- assert(closed.blockingReasons.length === 0, 'closed fixture should have no blockers');
- assert(closed.blockingReasonCount === 0, 'closed fixture should expose zero blocker count');
- assert(closed.blockingReasonsWithMissingProofRequirements === 0, 'closed fixture should expose zero blockers with missing proof');
- assert(closed.missingProofRequirementCount === 0, 'closed fixture should expose zero missing proof requirements');
- assert(closed.gates.every(item => Array.isArray(item.missingProofRequirements) && item.missingProofRequirements.length === 0), 'closed gates should not keep stale missing proof requirements');
- assert(closed.canClaim.tihaoRateImproved === true, 'closed fixture should allow tihao claim');
- assert(closed.canClaim.customerEffectAchieved === true, 'closed fixture should allow customer claim');
- assert(closed.canClaim.manualSupplementReduced === true, 'closed fixture should allow supplement claim');
- const proofTmp = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-completion-discovery-'));
- try {
- const realHistoryDir = path.join(proofTmp, 'pipeline-run', 'history-audit');
- const smokeHistoryDir = path.join(proofTmp, 'pipeline-smoke-run', 'history-audit');
- const newerFailingHistoryDir = path.join(proofTmp, 'latest-real-run', 'history-audit');
- fs.mkdirSync(realHistoryDir, { recursive: true });
- fs.mkdirSync(smokeHistoryDir, { recursive: true });
- fs.mkdirSync(newerFailingHistoryDir, { recursive: true });
- const passingHistoryFile = path.join(realHistoryDir, 'historical-dataset-audit.json');
- const smokeHistoryFile = path.join(smokeHistoryDir, 'historical-dataset-audit.json');
- const failingHistoryFile = path.join(newerFailingHistoryDir, 'historical-dataset-audit.json');
- fs.writeFileSync(passingHistoryFile, JSON.stringify(passingHistoryAudit(), null, 2), 'utf8');
- fs.writeFileSync(smokeHistoryFile, JSON.stringify(passingHistoryAudit(), null, 2), 'utf8');
- fs.writeFileSync(failingHistoryFile, JSON.stringify({ briefCount: 1, acceptance: { readyForCustomerEffectProof: false }, items: [] }, null, 2), 'utf8');
- fs.utimesSync(passingHistoryFile, new Date(Date.now() - 20000), new Date(Date.now() - 20000));
- fs.utimesSync(smokeHistoryFile, new Date(), new Date());
- fs.utimesSync(failingHistoryFile, new Date(Date.now() - 10000), new Date(Date.now() - 10000));
- const discoveredHistory = bestHistoryAudit(proofTmp);
- assert(path.resolve(discoveredHistory) === path.resolve(passingHistoryFile), 'completion history discovery should recurse and prefer a claimable non-smoke audit');
- const currentCustomerDir = path.join(proofTmp, 'latest-real-run', 'customer-effect-audit');
- const staleCustomerDir = path.join(proofTmp, 'other-real-run', 'customer-effect-audit');
- fs.mkdirSync(currentCustomerDir, { recursive: true });
- fs.mkdirSync(staleCustomerDir, { recursive: true });
- const currentCustomerFile = path.join(currentCustomerDir, 'customer-effect-summary.json');
- const staleCustomerFile = path.join(staleCustomerDir, 'customer-effect-summary.json');
- fs.writeFileSync(currentCustomerFile, JSON.stringify({
- ...passingCustomerEffect(failingHistoryFile),
- acceptance: { overallPass: false, historyReadyForCustomerEffectProof: false },
- customerSelectedRate: 0
- }, null, 2), 'utf8');
- fs.writeFileSync(staleCustomerFile, JSON.stringify(passingCustomerEffect(path.join('outputs', 'stale-history-audit', 'historical-dataset-audit.json')), null, 2), 'utf8');
- fs.utimesSync(currentCustomerFile, new Date(Date.now() - 10000), new Date(Date.now() - 10000));
- fs.utimesSync(staleCustomerFile, new Date(), new Date());
- const discoveredCustomerEffect = bestCustomerEffectSummary(proofTmp, failingHistoryFile, process.cwd());
- assert(path.resolve(discoveredCustomerEffect) === path.resolve(currentCustomerFile), 'completion customer-effect discovery should prefer summaries bound to the selected history audit');
- } finally {
- fs.rmSync(proofTmp, { recursive: true, force: true });
- }
- console.log(JSON.stringify({
- ok: true,
- openComplete: open.complete,
- openReadyForClaim: open.readyForClaim,
- openProofGapOpenCount: open.proofGapOpenCount,
- closedComplete: closed.complete
- }, null, 2));
- }
- function assert(condition, message) {
- if (!condition) throw new Error(message);
- }
- function passingHistoryAudit() {
- return {
- generatedAt: '2026-06-11T02:48:48.000Z',
- minBriefs: 5,
- briefCount: 5,
- categoryCount: 3,
- categories: ['skincare', 'mom-baby', 'home'],
- withReference: 5,
- withManualFinalList: 5,
- withCustomerDecision: 5,
- withRejectionReason: 2,
- withManualSupplementBaseline: 5,
- missingCriticalCount: 0,
- acceptance: {
- parseOk: true,
- minBriefsMet: true,
- allHaveBriefText: true,
- allHaveManualFinalList: true,
- allHaveCustomerDecision: true,
- allHaveFeedbackReason: true,
- allHaveManualSupplementBaseline: true,
- categoryCoverageMet: true,
- referenceCoverageMeasured: true,
- readyForLongRun: true,
- readyForCustomerEffectProof: true
- },
- items: Array.from({ length: 5 }, (_, index) => ({
- id: `brief-${index + 1}`,
- parseOk: true,
- hasBriefText: true,
- hasManualFinalList: true,
- hasCustomerDecision: true,
- hasRejectionReason: index < 2,
- hasManualSupplementBaseline: true,
- manualSupplementBaseline: 2,
- missingCritical: []
- }))
- };
- }
- function passingProofGapClosure() {
- const businessRows = [
- 'historical-dataset',
- 'video-real-candidate',
- 'video-ab-live-proof',
- 'live-provider-overnight-proof',
- 'manual-review-and-customer-effect'
- ].map(id => ({
- id,
- title: id,
- status: 'closed',
- evidence: 'verified',
- missingProofRequirements: [],
- required: 'verified',
- command: 'npm run proof-gap:closure',
- expectedArtifact: 'outputs/proof-gap-closure-latest/proof-gap-closure-summary.json'
- }));
- return {
- generatedAt: '2026-06-11T02:48:48.500Z',
- complete: true,
- intakeReady: true,
- openCount: 0,
- closedCount: 5,
- totalRows: 6,
- businessGapCount: 5,
- rows: [
- {
- id: 'intake-readiness',
- title: 'intake-readiness',
- status: 'closed',
- evidence: 'verified',
- missingProofRequirements: [],
- required: 'verified',
- command: 'npm run intake:readiness',
- expectedArtifact: 'outputs/intake-readiness-latest/intake-readiness-summary.json'
- },
- ...businessRows
- ]
- };
- }
- function passingBusinessProgress() {
- return {
- generatedAt: '2026-06-11T02:48:48.750Z',
- complete: true,
- counts: { pass: 15, fail: 0, pending: 0, blocked_by_external_data: 0 },
- rows: Array.from({ length: 15 }, (_, index) => ({
- order: index + 1,
- owner: index < 5 ? 'business' : 'tech-ai',
- title: `step-${index + 1}`,
- status: 'pass',
- evidence: 'verified',
- next: 'keep evidence current'
- }))
- };
- }
- function passingOptimizationPipeline() {
- return {
- readyForClaim: true,
- generatedAt: '2026-06-11T02:48:49.000Z',
- proofGapClosure: {
- complete: true,
- openCount: 0,
- closedCount: 5,
- businessGapCount: 5,
- claimable: true
- },
- results: [
- { id: 'history-audit', status: 'pass' },
- { id: 'video-resource-readiness', status: 'pass' },
- { id: 'customer-effect-audit', status: 'pass' },
- { id: 'proof-gap-closure', status: 'pass' }
- ]
- };
- }
- function passingVideoAb() {
- return {
- acceptance: { passed: true },
- proofContext: {
- mode: 'live',
- collectionMode: 'live',
- generatedBy: 'acceptance:video-ab',
- requiresRuntimeCredential: true,
- requiresVocSocialProvider: true,
- requiresVideoAnalysisProvider: true
- },
- enhanced: { provider: { evidence: { providerStatus: 'ok' } } }
- };
- }
- function failedVideoAbPreflight() {
- return {
- materialType: 'video_ab_runtime_preflight',
- directCustomerProof: false,
- proofLevel: 'not_business_proof',
- canCloseProofGap: false,
- readyForVideoAb: false,
- failureCount: 4,
- proofContext: {
- mode: 'not_run',
- collectionMode: 'not_run',
- generatedBy: 'acceptance:video-ab-preflight',
- requiresRuntimeCredential: true,
- requiresVocSocialProvider: true,
- requiresVideoAnalysisProvider: true
- },
- runtime: {
- runtimeCredentialPresent: false,
- companyResolved: false,
- vocSocialProviderTokenPresent: false,
- videoAnalysisTokenPresent: false
- },
- missingProofRequirements: [
- 'proofContext.requiresRuntimeCredential=true',
- 'company resolved for live run',
- 'proofContext.requiresVocSocialProvider=true',
- 'proofContext.requiresVideoAnalysisProvider=true'
- ]
- };
- }
- function passingCustomerEffect(historyAuditPath) {
- return {
- reviewPath: path.join('outputs', 'review-metrics-latest', 'reviewed.csv'),
- historyAuditPath,
- customerSelectedRate: 0.5,
- referenceCustomerSelectedRate: 0.5,
- manualSupplementBaseline: { available: true, source: 'history-audit', total: 10, byBrief: [{ briefId: 'brief-a', count: 10 }] },
- currentManualSupplement: { available: true, source: 'cli-arg', total: 5, byBrief: [] },
- manualSupplementReductionRate: 0.5,
- acceptance: {
- overallPass: true,
- reviewMetricsOverallUsable: true,
- customerSelectedRateMeasured: true,
- customerSelectedRate30Pass: true,
- referenceCustomerSelectedRateMeasured: true,
- referenceCustomerSelectedRate40Pass: true,
- historyReadyForCustomerEffectProof: true,
- manualSupplementBaselineAvailable: true,
- currentManualSupplementAvailable: true,
- manualSupplementReduction50Pass: true
- },
- missingEvidence: []
- };
- }
- function passingCompletionBase({ historyAuditPath, sourceFiles, history }) {
- return {
- root: process.cwd(),
- outputsDir: 'outputs',
- sourceFiles,
- history,
- intakeReadiness: { acceptance: { overallReady: true, historyReady: true, videoReady: true, reviewMetricsReady: true, customerEffectReady: true }, failureCount: 0 },
- videoReadiness: { acceptance: { readyForVideoAbPreflight: true }, failureCount: 0, counts: { realReferenceRows: 1, realCandidateRows: 2, videoUrlRows: 2 } },
- proofGapClosure: passingProofGapClosure(),
- handoff: { complete: true, readyCapabilities: [{ id: 'release-chain' }], readyNotProven: [], externalBlockers: [] },
- businessProgress: passingBusinessProgress(),
- longRunReadiness: { ready: true, counts: { pass: 13, fail: 0 } },
- videoAb: passingVideoAb(),
- overnight: { manifest: { liveEnabled: true }, acceptance: { overallPass: true, failedGateCount: 0 }, failureCount: 0 },
- customerEffect: passingCustomerEffect(historyAuditPath),
- optimizationPipeline: passingOptimizationPipeline()
- };
- }
- main();
|