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