real-gap-material-audit-smoke.js 3.0 KB

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