"use strict";
/**
 * CHAPTER 4 — HOSTILE VERIFICATION
 *
 * Three tests the founder specifically demanded:
 *
 * Test 1: Not just language filter — outcome-driven differentiation
 * Test 2: Cold start — new developer with no history
 * Test 3: Behavior change — same dev, different outcomes
 */
Object.defineProperty(exports, "__esModule", { value: true });
const developer_profile_1 = require("../../walls/03-knowledge/decisions/developer-profile");
const recommendation_engine_1 = require("../../walls/03-knowledge/decisions/recommendation-engine");
let hvPass = 0;
let hvFail = 0;
const hvErrors = [];
function check(cond, msg) {
    if (cond) {
        hvPass++;
        console.log(`  ✅ ${msg}`);
    }
    else {
        hvFail++;
        const m = `  ❌ FAIL: ${msg}`;
        console.log(m);
        hvErrors.push(m);
    }
}
function eq(a, b, msg) {
    if (a === b) {
        hvPass++;
        console.log(`  ✅ ${msg} (${JSON.stringify(a)})`);
    }
    else {
        hvFail++;
        const m = `  ❌ FAIL: ${msg} — expected ${JSON.stringify(b)}, got ${JSON.stringify(a)}`;
        console.log(m);
        hvErrors.push(m);
    }
}
function gt(a, b, msg) {
    if (a > b) {
        hvPass++;
        console.log(`  ✅ ${msg} (${a} > ${b})`);
    }
    else {
        hvFail++;
        const m = `  ❌ FAIL: ${msg} — ${a} not > ${b}`;
        console.log(m);
        hvErrors.push(m);
    }
}
function makePattern(id, category, language) {
    return {
        patternId: id, category, description: `Pattern ${id}`, from: 'old', to: 'new',
        conditions: [{ type: 'language', value: language, matchScore: 1 }],
        confidence: { distribution: 'beta', alpha: 5, beta: 2, mean: 0.7, ci95: [0.4, 0.9] },
        signals: { positive: 10, negative: 2, total: 12, lastSignal: Date.now() },
        attribution: { primaryCondition: '', conditionConfidence: 0, sourceFiles: [], note: '' },
        scope: 'global', survivedDays: 30,
        meta: { language, subcategory: 'general', complexity: 'low', risk: 'low', source: 'manual' },
        lifecycle: { firstSeen: Date.now() - 86400000, lastSeen: Date.now(), version: 1, history: [] },
        quality: { score: 80, reuseRate: 0.5, successRate: 0.8, failureRate: 0.2, acceptanceRate: 0.8, daysSinceLastSignal: 1, age: 30 },
        relationships: { related: [], conflicting: [], complementary: [], dependencies: [] },
        ranking: { score: 80, rank: 1, factors: { confidence: 70, quality: 80, usage: 60, recency: 90, acceptance: 80 } },
    };
}
function makeOutcome(pid, sr, usage = 10) {
    const sc = Math.round(usage * sr);
    return {
        patternId: pid, usageCount: usage, successCount: sc, failureCount: usage - sc,
        acceptanceCount: Math.round(usage * 0.8), rejectionCount: Math.round(usage * 0.2),
        lastOutcome: sr > 0.5 ? 'PATTERN_SUCCESS' : 'PATTERN_FAILURE',
        lastSuccessTimestamp: sr > 0.5 ? Date.now() : null,
        lastFailureTimestamp: sr <= 0.5 ? Date.now() : null,
        successRate: sr, failureRate: 1 - sr, acceptanceRate: 0.8,
        confidence: 0.5 + sr * 0.4,
        trend: sr > 0.7 ? 'rising' : 'declining',
        health: Math.round(sr * 100),
        firstSeen: Date.now() - 86400000, lastSeen: Date.now(),
    };
}
describe('CHAPTER 4 — HOSTILE VERIFICATION', () => {
    afterAll(() => {
        console.log('\n' + '='.repeat(60));
        console.log('HOSTILE VERDICT');
        console.log('='.repeat(60));
        console.log(`  Passed: ${hvPass}`);
        console.log(`  Failed: ${hvFail}`);
        console.log(`  Total:  ${hvPass + hvFail}\n`);
        if (hvFail === 0) {
            console.log('  🔒 CHAPTER 4 — PASSED');
        }
        else {
            console.log(`  ❌ ${hvFail} FAILURES:`);
            for (const e of hvErrors)
                console.log(`    ${e}`);
        }
    });
    // ======================================================================
    // TEST 1: Not just language filter — outcome-driven differentiation
    // ======================================================================
    // 
    // Create 2 developers who BOTH use TypeScript AND Python.
    // Difference: Dev A succeeds at TypeScript, fails at Python.
    //            Dev B succeeds at Python, fails at TypeScript.
    //
    // If recs are based on outcomes (not language filter):
    //   Dev A should get TypeScript patterns recommended
    //   Dev B should get Python patterns recommended
    //
    // If recs are based on language filter ONLY:
    //   Both would get same recommendations
    test('HV1: Outcome-driven, not language-filter-only', () => {
        console.log('\n--- TEST 1: Outcome-driven (not language filter) ---\n');
        // All 4 patterns — same 2 languages, same 2 categories
        const patterns = [
            makePattern('ts_test_a', 'testing', 'typescript'),
            makePattern('ts_test_b', 'testing', 'typescript'),
            makePattern('py_data_a', 'data', 'python'),
            makePattern('py_data_b', 'data', 'python'),
        ];
        // Dev A: TypeScript succeeds, Python fails
        const outcomesA = new Map();
        outcomesA.set('ts_test_a', makeOutcome('ts_test_a', 0.9, 20));
        outcomesA.set('ts_test_b', makeOutcome('ts_test_b', 0.85, 15));
        outcomesA.set('py_data_a', makeOutcome('py_data_a', 0.2, 10));
        outcomesA.set('py_data_b', makeOutcome('py_data_b', 0.3, 12));
        // Dev B: Python succeeds, TypeScript fails
        const outcomesB = new Map();
        outcomesB.set('ts_test_a', makeOutcome('ts_test_a', 0.2, 10));
        outcomesB.set('ts_test_b', makeOutcome('ts_test_b', 0.3, 12));
        outcomesB.set('py_data_a', makeOutcome('py_data_a', 0.9, 20));
        outcomesB.set('py_data_b', makeOutcome('py_data_b', 0.85, 15));
        const profileA = (0, developer_profile_1.buildProfile)('dev_A', patterns, outcomesA);
        const profileB = (0, developer_profile_1.buildProfile)('dev_B', patterns, outcomesB);
        console.log(`  Dev A: TS success=${outcomesA.get('ts_test_a').successRate}, PY success=${outcomesA.get('py_data_a').successRate}`);
        console.log(`  Dev B: TS success=${outcomesB.get('ts_test_a').successRate}, PY success=${outcomesB.get('py_data_a').successRate}`);
        const allProfiles = new Map();
        allProfiles.set('dev_A', profileA);
        allProfiles.set('dev_B', profileB);
        const resultA = (0, recommendation_engine_1.recommendPatterns)('dev_A', patterns, outcomesA, allProfiles);
        const resultB = (0, recommendation_engine_1.recommendPatterns)('dev_B', patterns, outcomesB, allProfiles);
        console.log(`\n  Dev A recommendations:`);
        for (const r of resultA.recommendations) {
            console.log(`    ${r.patternId} score=${r.score} reasons=${r.reasons.map(x => x.type).join(', ')}`);
        }
        console.log(`\n  Dev B recommendations:`);
        for (const r of resultB.recommendations) {
            console.log(`    ${r.patternId} score=${r.score} reasons=${r.reasons.map(x => x.type).join(', ')}`);
        }
        // Dev A should have TypeScript patterns
        const aTS = resultA.recommendations.filter(r => r.patternId.startsWith('ts_'));
        const aPY = resultA.recommendations.filter(r => r.patternId.startsWith('py_'));
        console.log(`\n  Dev A: TS recommendations=${aTS.length}, PY recommendations=${aPY.length}`);
        gt(aTS.length, aPY.length, 'Dev A gets more TypeScript than Python (outcome-driven)');
        // Dev B should have Python patterns  
        const bTS = resultB.recommendations.filter(r => r.patternId.startsWith('ts_'));
        const bPY = resultB.recommendations.filter(r => r.patternId.startsWith('py_'));
        console.log(`  Dev B: TS recommendations=${bTS.length}, PY recommendations=${bPY.length}`);
        gt(bPY.length, bTS.length, 'Dev B gets more Python than TypeScript (outcome-driven)');
        // The two result sets must differ
        const idsA = new Set(resultA.recommendations.map(r => r.patternId));
        const idsB = new Set(resultB.recommendations.map(r => r.patternId));
        const same = [...idsA].every(id => idsB.has(id));
        check(!same, 'Dev A and Dev B get different recommendation sets');
        // Each recommendation has an outcome_evidence reason
        for (const r of resultA.recommendations) {
            const hasOutcomeReason = r.reasons.some(x => x.type === 'outcome_evidence');
            check(hasOutcomeReason, `${r.patternId} has outcome_evidence reason`);
        }
    });
    // ======================================================================
    // TEST 2: Cold start — new developer with no history
    // ======================================================================
    test('HV2: Cold start', () => {
        console.log('\n--- TEST 2: Cold Start — new dev, no history ---\n');
        const patterns = [
            makePattern('cold_ts_test', 'testing', 'typescript'),
            makePattern('cold_py_data', 'data', 'python'),
            makePattern('cold_go_ops', 'devops', 'go'),
            makePattern('cold_ts_perf', 'performance', 'typescript'),
            makePattern('cold_py_sec', 'security', 'python'),
        ];
        const outcomes = new Map();
        for (const p of patterns) {
            outcomes.set(p.patternId, makeOutcome(p.patternId, 0.85, 10));
        }
        // Existing developers with profiles
        const existingProfiles = new Map();
        const ex1 = (0, developer_profile_1.buildProfile)('existing_1', patterns.filter(p => p.meta.language === 'typescript'), outcomes);
        const ex2 = (0, developer_profile_1.buildProfile)('existing_2', patterns.filter(p => p.meta.language === 'python'), outcomes);
        existingProfiles.set('existing_1', ex1);
        existingProfiles.set('existing_2', ex2);
        // NEW developer — NO patterns, NO outcomes, entirely cold
        console.log(`  Creating new developer 'new_dev' with ZERO patterns...`);
        let result;
        try {
            result = (0, recommendation_engine_1.recommendPatterns)('new_dev', patterns, outcomes, existingProfiles);
            console.log(`  Recommendations generated: ${result.recommendations.length}`);
            console.log(`  Candidates evaluated: ${result.totalCandidates}`);
            console.log(`  Latency: ${result.latencyMs}ms`);
            check(true, 'cold start does not crash');
        }
        catch (e) {
            check(false, `cold start throws: ${e.message}`);
            return;
        }
        // Should return SOME recommendations
        check(result.recommendations.length > 0, `cold start returns ${result.recommendations.length} recommendations`);
        // All recs should have explanations
        for (const r of result.recommendations) {
            check(r.reasons.length >= 1, `${r.patternId} has reasons (cold start)`);
        }
        // Should span multiple categories
        const cats = new Set(result.recommendations.map(r => r.category));
        check(cats.size >= 1, `cold start recs span ${cats.size} categories`);
        console.log(`  Categories: ${[...cats].join(', ')}`);
    });
    // ======================================================================
    // TEST 3: Behavior change — same dev, different outcomes
    // ======================================================================
    test('HV3: Behavior change', () => {
        console.log('\n--- TEST 3: Behavior Change — same dev, changed outcomes ---\n');
        const patterns = [
            makePattern('bc_a', 'testing', 'typescript'),
            makePattern('bc_b', 'data', 'python'),
            makePattern('bc_c', 'devops', 'go'),
        ];
        // Phase 1: All patterns successful
        const outcomesPhase1 = new Map();
        outcomesPhase1.set('bc_a', makeOutcome('bc_a', 0.9, 20));
        outcomesPhase1.set('bc_b', makeOutcome('bc_b', 0.85, 15));
        outcomesPhase1.set('bc_c', makeOutcome('bc_c', 0.8, 12));
        const profile1 = (0, developer_profile_1.buildProfile)('bc_dev', patterns, outcomesPhase1);
        const profiles1 = new Map();
        profiles1.set('bc_dev', profile1);
        const phase1 = (0, recommendation_engine_1.recommendPatterns)('bc_dev', patterns, outcomesPhase1, profiles1);
        const p1Ids = phase1.recommendations.map(r => r.patternId);
        const p1Scores = phase1.recommendations.map(r => `${r.patternId}=${r.score}`);
        console.log(`  Phase 1 (all successful): ${p1Scores.join(', ')}`);
        // Phase 2: bc_a now has terrible outcomes
        const outcomesPhase2 = new Map();
        outcomesPhase2.set('bc_a', makeOutcome('bc_a', 0.1, 20)); // was 0.9 → now 0.1
        outcomesPhase2.set('bc_b', makeOutcome('bc_b', 0.85, 15)); // same
        outcomesPhase2.set('bc_c', makeOutcome('bc_c', 0.8, 12)); // same
        const profile2 = (0, developer_profile_1.buildProfile)('bc_dev', patterns, outcomesPhase2);
        const profiles2 = new Map();
        profiles2.set('bc_dev', profile2);
        const phase2 = (0, recommendation_engine_1.recommendPatterns)('bc_dev', patterns, outcomesPhase2, profiles2);
        const p2Ids = phase2.recommendations.map(r => r.patternId);
        const p2Scores = phase2.recommendations.map(r => `${r.patternId}=${r.score}`);
        console.log(`  Phase 2 (bc_a failed): ${p2Scores.join(', ')}`);
        // Phase 1 ranked bc_a first or second (was 0.9 success)
        // Phase 2 should drop bc_a (0.1 success → filtered by successRate <= 0.5)
        check(p1Ids.includes('bc_a'), 'Phase 1: bc_a in recommendations (was successful)');
        check(!p2Ids.includes('bc_a'), 'Phase 2: bc_a excluded (now failing)');
        check(p1Ids.length > 0, 'Phase 1 returns recommendations');
        check(p2Ids.length > 0, 'Phase 2 returns recommendations');
        // Verify the order changed
        const p1RankA = p1Ids.indexOf('bc_a');
        const p2notFound = !p2Ids.includes('bc_a');
        check(p2notFound, 'bc_a dropped from recommendations after outcomes changed');
        // Show raw scores
        console.log(`\n  bc_a score: Phase1=${outcomesPhase1.get('bc_a').successRate}, Phase2=${outcomesPhase2.get('bc_a').successRate}`);
        console.log(`  bc_b score: Phase1=${outcomesPhase1.get('bc_b').successRate}, Phase2=${outcomesPhase2.get('bc_b').successRate}`);
    });
});
//# sourceMappingURL=chapter4-hostile.test.js.map