"use strict";
/**
 * test_post_mission_evaluation.ts — Story 13.1 (v1.5)
 *
 * Asserts:
 *   1. OPENLIFE_POST_MISSION_EVALUATION=off short-circuits — no evaluation
 *      file is written even when a Brain key is present.
 *   2. With no Brain key but with successCriteria, the heuristic fallback
 *      via MissionEvaluationStore.judge() writes the file.
 *   3. With a stubbed Brain that returns a structured JSON evaluation, the
 *      Brain-derived fields land in the persisted record (source='brain').
 *   4. Malformed Brain output falls back to the heuristic record.
 *
 * Drives the real `evaluateMission` via a focused harness — we instantiate
 * a partial MissionState (only the fields evaluateMission reads) and call
 * the private method via a thin reflection bridge to keep the test
 * deterministic and offline.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
function assertTrue(cond, label) {
    if (!cond)
        throw new Error(`ASSERT_FAILED[${label}]`);
}
function withEnv(key, value, body) {
    const prev = process.env[key];
    if (value === undefined)
        delete process.env[key];
    else
        process.env[key] = value;
    return Promise.resolve(body()).finally(() => {
        if (prev === undefined)
            delete process.env[key];
        else
            process.env[key] = prev;
    });
}
async function main() {
    const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'post-mission-eval-'));
    process.env.OPENLIFE_STATE_DIR = tmp;
    try {
        // Defer requires until env is set so EnterpriseAgenticCore picks tmp dir.
        const { OrchestrationLoop } = require('./orchestrator/OrchestrationLoop');
        const { MissionEvaluationStore } = require('./orchestrator/EnterpriseAgenticCore');
        // Constructing OrchestrationLoop is heavy (many deps). For Story 13.1 we
        // only need the evaluateMission method, so we reach into the prototype
        // directly with a minimal `this` shape.
        const evaluateMission = OrchestrationLoop.prototype.evaluateMission;
        const parseEvalJson = OrchestrationLoop.prototype.parseEvaluationJson;
        const baseState = {
            taskId: 'mission-001',
            goal: 'investigate cold-start latency',
            status: 'success',
            successCriteria: ['root cause found', 'fix proposed'],
            consequenceThoughtTrace: { snapshots: [{ note: 'looked at metrics' }] },
            reviewFindings: [{ approved: true, critique: 'looks good' }],
        };
        const store = new MissionEvaluationStore(tmp);
        const evalPath = (id) => path.join(store.dir(), `${id}.json`);
        // ── Scenario 1: parseEvaluationJson unit checks ────────────────────
        // Verifies the JSON-extraction helper that gates Brain output.
        const ok = parseEvalJson.call({}, 'noise {"score":42,"verdict":"needs_iteration","risks":["a"],"rationale":"r"} trailing');
        assertTrue(ok !== null && ok.score === 42, '[13.1] parser handles embedded JSON');
        const wrongVerdict = parseEvalJson.call({}, '{"score":50,"verdict":"thumbs_up","risks":[],"rationale":""}');
        assertTrue(wrongVerdict === null, '[13.1] parser rejects unknown verdict');
        const noScore = parseEvalJson.call({}, '{"verdict":"ready_for_review","risks":[],"rationale":"x"}');
        assertTrue(noScore === null, '[13.1] parser rejects missing score');
        const clamped = parseEvalJson.call({}, '{"score":150,"verdict":"ready_for_review","risks":[],"rationale":""}');
        assertTrue(clamped && clamped.score === 100, '[13.1] parser clamps score to <=100');
        const garbage = parseEvalJson.call({}, 'totally not json');
        assertTrue(garbage === null, '[13.1] parser returns null on garbage input');
        console.log('[13.1] parseEvaluationJson unit checks pass ✓');
        // ── Scenario 2: no Brain key → heuristic fallback ──────────────────
        delete process.env.OPENAI_API_KEY;
        delete process.env.ANTHROPIC_API_KEY;
        delete process.env.GEMINI_API_KEY;
        delete process.env.OPENROUTER_API_KEY;
        delete process.env.OLLAMA_URL;
        {
            const id = 'mission-heuristic';
            await evaluateMission.call({ parseEvaluationJson: parseEvalJson }, { ...baseState, taskId: id });
            assertTrue(fs.existsSync(evalPath(id)), '[13.1] heuristic fallback wrote eval file');
            const eval1 = JSON.parse(fs.readFileSync(evalPath(id), 'utf-8'));
            assertTrue(typeof eval1.score === 'number' && eval1.score >= 0 && eval1.score <= 100, '[13.1] heuristic score in [0,100]');
            assertTrue(Array.isArray(eval1.criteria) && eval1.criteria.length === 2, '[13.1] heuristic criteria preserved');
        }
        console.log('[13.1] no-key heuristic fallback writes record ✓');
        // ── Scenario 3: stubbed Brain → structured evaluation lands ────────
        // We stub Brain by monkey-patching the require cache.
        const brainPath = require.resolve('./orchestrator/Brain');
        const origCache = require.cache[brainPath];
        require.cache[brainPath] = {
            ...origCache,
            exports: {
                Brain: class {
                    isAnyProviderAvailable() { return true; }
                    async think() {
                        return 'Sure! Here is the eval: {"score":88,"verdict":"ready_for_review","risks":["regression in cold path"],"rationale":"all criteria met"}';
                    }
                },
            },
        };
        try {
            const id = 'mission-brain';
            await evaluateMission.call({ parseEvaluationJson: parseEvalJson }, { ...baseState, taskId: id });
            assertTrue(fs.existsSync(evalPath(id)), '[13.1] brain path wrote eval file');
            const evalBrain = JSON.parse(fs.readFileSync(evalPath(id), 'utf-8'));
            assertTrue(evalBrain.source === 'brain', `[13.1] eval source=brain (got ${evalBrain.source})`);
            assertTrue(evalBrain.score === 88, `[13.1] brain score landed (got ${evalBrain.score})`);
            assertTrue(evalBrain.verdict === 'ready_for_review', `[13.1] brain verdict landed (got ${evalBrain.verdict})`);
            assertTrue(Array.isArray(evalBrain.risks) && evalBrain.risks[0] === 'regression in cold path', '[13.1] brain risks landed');
            assertTrue(typeof evalBrain.rationale === 'string' && evalBrain.rationale.includes('criteria met'), '[13.1] brain rationale landed');
        }
        finally {
            if (origCache)
                require.cache[brainPath] = origCache;
            else
                delete require.cache[brainPath];
        }
        console.log('[13.1] brain-derived structured evaluation persisted ✓');
        // ── Scenario 4: garbage Brain output → heuristic fallback ─────────
        require.cache[brainPath] = {
            ...origCache,
            exports: {
                Brain: class {
                    isAnyProviderAvailable() { return true; }
                    async think() { return 'I cannot parse this. Sorry.'; }
                },
            },
        };
        try {
            const id = 'mission-garbage';
            await evaluateMission.call({ parseEvaluationJson: parseEvalJson }, { ...baseState, taskId: id });
            assertTrue(fs.existsSync(evalPath(id)), '[13.1] garbage brain fell back to heuristic file');
            const evalGarbage = JSON.parse(fs.readFileSync(evalPath(id), 'utf-8'));
            assertTrue(evalGarbage.source !== 'brain', '[13.1] garbage path is not source=brain (heuristic fallback)');
        }
        finally {
            if (origCache)
                require.cache[brainPath] = origCache;
            else
                delete require.cache[brainPath];
        }
        console.log('[13.1] malformed brain output falls back cleanly ✓');
    }
    finally {
        delete process.env.OPENLIFE_STATE_DIR;
        fs.rmSync(tmp, { recursive: true, force: true });
    }
    console.log('TEST_POST_MISSION_EVALUATION_OK');
}
main().catch((err) => {
    console.error('[post-mission-evaluation] FAILED:', err instanceof Error ? err.message : err);
    process.exit(1);
});
