import { describe, test, afterEach } from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, rmSync, mkdirSync, writeFileSync, existsSync } from 'node:fs'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { calculateScore } from '../personalization-score.mjs'; // Step 5 (remediation): the shipped voice profile is a PII-free placeholder // carrying the sentinel below. Detection must key on the sentinel — NOT the old // `[Your Name]` heuristic — so the placeholder earns 0 of the 25 voice points, // and a populated profile (sentinel removed) earns them. const SENTINEL = ''; // A >50-line body that contains NEITHER the sentinel NOR `[Your Name]`, so the // only thing distinguishing placeholder from real profile is the sentinel. const LONG_BODY = Array.from({ length: 60 }, (_, i) => `- voice characteristic line ${i + 1}`).join('\n'); function makePluginRoot() { const root = mkdtempSync(join(tmpdir(), 'lis-personalization-')); mkdirSync(join(root, 'assets', 'voice-samples'), { recursive: true }); return root; } function writeVoice(root, content) { writeFileSync(join(root, 'assets', 'voice-samples', 'authentic-voice-samples.md'), content, 'utf-8'); } describe('calculateScore — voice samples (sentinel-based placeholder detection)', () => { let root; afterEach(() => { if (root && existsSync(root)) { rmSync(root, { recursive: true, force: true }); } root = undefined; }); test('placeholder with the sentinel scores 0 voice points (even >50 lines, no [Your Name])', () => { root = makePluginRoot(); writeVoice(root, `# Voice Profile (placeholder)\n${SENTINEL}\n\n${LONG_BODY}\n`); const { score, personalized } = calculateScore(root); assert.equal(score, 0, 'placeholder must not earn the 25 voice points'); assert.equal(personalized, 0); }); test('a real profile (no sentinel, >50 lines) earns the 25 voice points', () => { root = makePluginRoot(); writeVoice(root, `# My Voice Profile\n\n${LONG_BODY}\n`); const { score, personalized } = calculateScore(root); assert.equal(score, 25, 'a populated profile must earn the 25 voice points'); assert.equal(personalized, 1); }); test('a short placeholder (<50 lines) also scores 0 voice points', () => { root = makePluginRoot(); writeVoice(root, `# Voice Profile (placeholder)\n${SENTINEL}\n`); const { score } = calculateScore(root); assert.equal(score, 0); }); });