| 123456789101112131415161718192021222324252627282930313233343536373839404142 |
- #!/usr/bin/env node
- const assert = require('assert');
- const path = require('path');
- const { buildRealGapMaterialAudit, extractCandidateVideoNotes, findTranscriptHits } = require('./real-gap-material-audit');
- const root = path.resolve(__dirname, '..');
- const workspaceRoot = path.resolve(root, '..');
- const outputsDir = path.join(root, 'outputs');
- const transcriptsDir = path.join(workspaceRoot, 'docs', '提号经验');
- const summary = buildRealGapMaterialAudit({ root, workspaceRoot, outputsDir, transcriptsDir });
- assert.strictEqual(summary.materialType, 'three_real_gap_material_audit');
- assert.strictEqual(summary.proofLevel, 'not_business_proof');
- assert.strictEqual(summary.directCustomerProof, false);
- assert.strictEqual(summary.canCloseProofGap, false);
- assert.strictEqual(summary.gapCount, 3);
- assert.strictEqual(summary.gaps.length, 3);
- assert(summary.gaps.every(gap => gap.projectMaterialFound), 'all three real gaps should have project material connected');
- assert(summary.gaps.every(gap => gap.canCloseNow === false), 'material audit must not close business proof gaps');
- const byId = Object.fromEntries(summary.gaps.map(gap => [gap.id, gap]));
- assert(byId['historical-dataset'], 'historical-dataset gap should be present');
- assert(byId['video-ab-live-proof'], 'video-ab-live-proof gap should be present');
- assert(byId['manual-review-and-customer-effect'], 'manual-review-and-customer-effect gap should be present');
- assert(byId['historical-dataset'].blockingRequirements.some(item => /briefCount|Brief|客户|补号/.test(item)), 'historical gap should keep real proof blockers');
- assert.strictEqual(byId['video-ab-live-proof'].materialSignals.videoResourceReady, true, 'video resources should be connected before live A/B');
- assert.strictEqual(byId['video-ab-live-proof'].materialSignals.preflightReadyForVideoAb, false, 'preflight should still require runtime/provider proof');
- assert(byId['manual-review-and-customer-effect'].materialSignals.reviewDraftRows >= 1, 'manual review draft rows should be connected');
- const candidateVideoNotes = extractCandidateVideoNotes(path.join(workspaceRoot, 'output', 'dha-tihao-poc', 'candidate_details_top18.json'));
- assert(candidateVideoNotes.length >= 1, 'candidate video notes should be discovered from project material');
- assert(candidateVideoNotes.every(item => /^https:\/\/www\.xiaohongshu\.com\/discovery\/item\//.test(item.videoUrl)), 'candidate video urls should be sanitized public note urls');
- const transcriptHits = findTranscriptHits(transcriptsDir, [/选中率/, /没有给我反馈/]);
- assert(transcriptHits.length >= 1, 'experience transcript evidence should be discoverable');
- const serialized = JSON.stringify(summary);
- assert(!/npm_[A-Za-z0-9]{10,}/.test(serialized), 'summary must not include npm tokens');
- assert(!/sk-[A-Za-z0-9_-]{10,}/.test(serialized), 'summary must not include model tokens');
- assert(!/sessionToken\s*[:=]/i.test(serialized), 'summary must not include session tokens');
- console.log('real-gap-material-audit smoke ok');
|