"use strict";
// test_status_command — verifies the shape and overall-derivation logic of
// `openlife status`. Uses a temp .openlife/ scratch dir so we don't rely on
// (or pollute) the maintainer's local runtime state.
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"));
const StatusCommand_1 = require("./cli/StatusCommand");
function assert(cond, msg) {
    if (!cond) {
        console.error(`❌ ASSERT FAILED: ${msg}`);
        process.exit(1);
    }
}
function tempRoot() {
    const root = fs.mkdtempSync(path.join(os.tmpdir(), 'openlife-status-'));
    fs.mkdirSync(path.join(root, '.openlife'), { recursive: true });
    return root;
}
function cleanup(root) {
    try {
        fs.rmSync(root, { recursive: true, force: true });
    }
    catch {
        // best-effort
    }
}
function writeJson(root, filename, payload) {
    fs.writeFileSync(path.join(root, '.openlife', filename), JSON.stringify(payload, null, 2), 'utf-8');
}
function writeJsonl(root, filename, entries) {
    fs.writeFileSync(path.join(root, '.openlife', filename), entries.map((e) => JSON.stringify(e)).join('\n') + '\n', 'utf-8');
}
function scenarioEmpty() {
    const root = tempRoot();
    try {
        const report = (0, StatusCommand_1.buildStatusReport)(root);
        assert(report.overall === 'down', 'empty state should be down (no heartbeat, no executors)');
        assert(report.heartbeat.present === false, 'no heartbeat in empty state');
        assert(report.governance.ledgerPresent === false, 'no governance ledger in empty state');
        assert(report.executors.length === 0, 'no executors in empty state');
        assert(report.notes.includes('no_heartbeat'), 'should note no_heartbeat');
        console.log('✅ scenario 1: empty state → overall=down with no_heartbeat note');
    }
    finally {
        cleanup(root);
    }
}
function scenarioHealthy() {
    const root = tempRoot();
    try {
        const now = Date.now();
        writeJson(root, 'heartbeat.json', { pid: 12345, host: 'test-host', ts: now, uptime_s: 100, startedAt: now - 100_000 });
        writeJson(root, 'runtime-policy-status.json', {
            executors: {
                openai: { executor: 'openai', available: true, reason: 'ok', updatedAt: new Date(now).toISOString() },
                anthropic: { executor: 'anthropic', available: true, reason: 'ok', updatedAt: new Date(now).toISOString() },
            },
        });
        writeJsonl(root, 'governance-ledger.jsonl', [
            { index: 1, ts: new Date(now).toISOString(), entryHash: 'aaa' },
            { index: 2, ts: new Date(now).toISOString(), entryHash: 'bbb' },
        ]);
        const report = (0, StatusCommand_1.buildStatusReport)(root);
        assert(report.overall === 'healthy', `expected healthy, got ${report.overall} (notes: ${report.notes.join(',')})`);
        assert(report.heartbeat.fresh === true, 'fresh heartbeat expected');
        assert(report.executors.length === 2, 'two executors expected');
        assert(report.executors.every((e) => e.available), 'all executors available');
        assert(report.governance.entryCount === 2, 'two ledger entries expected');
        assert(report.governance.lastEntryHash === 'bbb', 'last entry hash is bbb');
        console.log('✅ scenario 2: healthy heartbeat + all executors + ledger → overall=healthy');
    }
    finally {
        cleanup(root);
    }
}
function scenarioDegradedOneExecutorDown() {
    const root = tempRoot();
    try {
        const now = Date.now();
        writeJson(root, 'heartbeat.json', { pid: 1, host: 'h', ts: now, uptime_s: 1, startedAt: now });
        writeJson(root, 'runtime-policy-status.json', {
            executors: {
                openai: { executor: 'openai', available: true, reason: 'ok' },
                anthropic: { executor: 'anthropic', available: false, reason: 'auth expired', category: 'auth' },
            },
        });
        const report = (0, StatusCommand_1.buildStatusReport)(root);
        assert(report.overall === 'degraded', `expected degraded, got ${report.overall}`);
        assert(report.notes.some((n) => n.startsWith('executors_down:')), 'should note specific executors down');
        console.log('✅ scenario 3: one executor down → overall=degraded');
    }
    finally {
        cleanup(root);
    }
}
function scenarioDownAllExecutorsDown() {
    const root = tempRoot();
    try {
        const now = Date.now();
        writeJson(root, 'heartbeat.json', { pid: 1, host: 'h', ts: now, uptime_s: 1, startedAt: now });
        writeJson(root, 'runtime-policy-status.json', {
            executors: {
                openai: { executor: 'openai', available: false, reason: 'rate limit' },
                anthropic: { executor: 'anthropic', available: false, reason: 'auth expired' },
            },
        });
        const report = (0, StatusCommand_1.buildStatusReport)(root);
        assert(report.overall === 'down', `expected down, got ${report.overall}`);
        assert(report.notes.includes('all_executors_down'), 'should note all_executors_down');
        console.log('✅ scenario 4: all executors down → overall=down');
    }
    finally {
        cleanup(root);
    }
}
function scenarioStaleHeartbeat() {
    const root = tempRoot();
    try {
        const staleTs = Date.now() - (StatusCommand_1.HEARTBEAT_FRESH_S + 30) * 1000;
        writeJson(root, 'heartbeat.json', { pid: 1, host: 'h', ts: staleTs, uptime_s: 9999, startedAt: staleTs - 1000 });
        writeJson(root, 'runtime-policy-status.json', {
            executors: { openai: { executor: 'openai', available: true, reason: 'ok' } },
        });
        const report = (0, StatusCommand_1.buildStatusReport)(root);
        assert(report.overall === 'degraded', `expected degraded for stale beat, got ${report.overall}`);
        assert(report.heartbeat.fresh === false, 'stale heartbeat is not fresh');
        assert(report.notes.some((n) => n.startsWith('heartbeat_warning_')), 'should warn about stale heartbeat');
        console.log('✅ scenario 5: stale heartbeat → overall=degraded with heartbeat_warning note');
    }
    finally {
        cleanup(root);
    }
}
function scenarioDeadHeartbeat() {
    const root = tempRoot();
    try {
        const deadTs = Date.now() - (StatusCommand_1.HEARTBEAT_STALE_S + 60) * 1000;
        writeJson(root, 'heartbeat.json', { pid: 1, host: 'h', ts: deadTs, uptime_s: 9999, startedAt: deadTs - 1000 });
        writeJson(root, 'runtime-policy-status.json', {
            executors: { openai: { executor: 'openai', available: true, reason: 'ok' } },
        });
        const report = (0, StatusCommand_1.buildStatusReport)(root);
        assert(report.overall === 'down', `expected down for dead beat, got ${report.overall}`);
        assert(report.notes.some((n) => n.startsWith('heartbeat_stale_')), 'should note heartbeat_stale_<age>s');
        console.log('✅ scenario 6: dead heartbeat → overall=down');
    }
    finally {
        cleanup(root);
    }
}
function scenarioCorruptLedgerHandled() {
    const root = tempRoot();
    try {
        const now = Date.now();
        writeJson(root, 'heartbeat.json', { pid: 1, host: 'h', ts: now, uptime_s: 1, startedAt: now });
        writeJson(root, 'runtime-policy-status.json', {
            executors: { openai: { executor: 'openai', available: true, reason: 'ok' } },
        });
        // Write a corrupt last line — must not throw.
        fs.writeFileSync(path.join(root, '.openlife', 'governance-ledger.jsonl'), '{"index":1,"entryHash":"good","ts":"' + new Date(now).toISOString() + '"}\n{not-valid-json\n', 'utf-8');
        const report = (0, StatusCommand_1.buildStatusReport)(root);
        assert(report.governance.entryCount === 2, 'should count both lines (parseability separate from count)');
        // Last entry was corrupt → lastEntryHash undefined; gracefully degraded, doesn't throw.
        assert(report.governance.lastEntryHash === undefined, 'corrupt last line yields no entryHash');
        console.log('✅ scenario 7: corrupt ledger line handled gracefully');
    }
    finally {
        cleanup(root);
    }
}
function main() {
    console.log('🧪 test_status_command — runtime state aggregator');
    scenarioEmpty();
    scenarioHealthy();
    scenarioDegradedOneExecutorDown();
    scenarioDownAllExecutorsDown();
    scenarioStaleHeartbeat();
    scenarioDeadHeartbeat();
    scenarioCorruptLedgerHandled();
    console.log('');
    console.log('TEST_STATUS_COMMAND_OK');
}
main();
