"use strict";
/**
 * test_task_executor_sandbox_optin.ts — Story 18.2 (v1.6)
 *
 * Asserts the opt-in routing of `TaskExecutor.runShellCommand` through
 * ProcessSandbox when `OPENLIFE_PROCESS_SANDBOX=on`.
 *
 * We reach into the private method via the prototype to keep the test
 * deterministic — instantiating a full TaskExecutor has side effects on
 * .artifacts. The test:
 *
 *   1. With the flag UNSET, the legacy `child_process.spawn` path runs.
 *   2. With OPENLIFE_PROCESS_SANDBOX=on, ProcessSandbox.spawn is the
 *      one that fires (verified by stubbing ProcessSandbox via the
 *      module-cache).
 *   3. The returned envelope shape is { code, signal } either way — no
 *      caller code needs to change.
 */
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}]`);
}
async function main() {
    const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'executor-sandbox-'));
    delete process.env.OPENLIFE_PROCESS_SANDBOX;
    delete process.env.OPENLIFE_TOOLSET_ENFORCEMENT;
    try {
        // Scenario 1: flag unset → legacy spawn path. We just verify the method
        // resolves with a {code, signal} envelope — using `true` (always-succeeds
        // command) so the legacy path produces code=0.
        const { TaskExecutor } = require('./orchestrator/TaskExecutor');
        const executor = new TaskExecutor();
        const runShellCommand = executor.runShellCommand.bind(executor);
        const r1 = await runShellCommand('true', tmp);
        assertTrue(typeof r1.code === 'number' || r1.code === null, '[18.2] flag unset → envelope shape');
        assertTrue(r1.code === 0, `[18.2] 'true' returns code 0 on legacy path (got ${r1.code})`);
        console.log('[18.2] flag unset → legacy spawn path ✓');
        // Scenario 2: flag ON → ProcessSandbox.spawn is invoked.
        const pbPath = require.resolve('./orchestrator/ProcessSandbox');
        const orig = require.cache[pbPath];
        let invocations = 0;
        let lastArgs = {};
        require.cache[pbPath] = {
            ...orig,
            exports: {
                ProcessSandbox: class {
                    constructor(_opts) { }
                    async spawn(command, args) {
                        invocations += 1;
                        lastArgs = { command, argv: args };
                        return { code: 0, signal: null, enforced: false, appliedFlags: [], stdout: '', stderr: '' };
                    }
                },
            },
        };
        try {
            // The TaskExecutor module is already loaded with the original
            // ProcessSandbox reference — to pick up the stub we drop the
            // TaskExecutor module cache so it re-requires.
            const teKey = require.resolve('./orchestrator/TaskExecutor');
            delete require.cache[teKey];
            const { TaskExecutor: ReloadedTE } = require('./orchestrator/TaskExecutor');
            const exec2 = new ReloadedTE();
            const runShellCommand2 = exec2.runShellCommand.bind(exec2);
            process.env.OPENLIFE_PROCESS_SANDBOX = 'on';
            const r2 = await runShellCommand2('echo hi', tmp);
            assertTrue(invocations === 1, `[18.2] ProcessSandbox.spawn invoked exactly once (got ${invocations})`);
            assertTrue(lastArgs.command === '/bin/bash', `[18.2] command is /bin/bash (got ${lastArgs.command})`);
            assertTrue(Array.isArray(lastArgs.argv) && lastArgs.argv[0] === '-lc' && lastArgs.argv[1] === 'echo hi', '[18.2] argv is -lc <cmd>');
            assertTrue(r2.code === 0 && r2.signal === null, '[18.2] envelope shape preserved');
        }
        finally {
            if (orig)
                require.cache[pbPath] = orig;
            else
                delete require.cache[pbPath];
            delete require.cache[require.resolve('./orchestrator/TaskExecutor')];
            delete process.env.OPENLIFE_PROCESS_SANDBOX;
        }
        console.log('[18.2] flag ON → routes through ProcessSandbox ✓');
    }
    finally {
        fs.rmSync(tmp, { recursive: true, force: true });
    }
    console.log('TEST_TASK_EXECUTOR_SANDBOX_OPTIN_OK');
}
main().catch((err) => {
    console.error('[task-executor-sandbox-optin] FAILED:', err instanceof Error ? err.message : err);
    process.exit(1);
});
