"use strict";
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 });
/**
 * Phase 3 — SUB-06 (Org/teams lifecycle) + SUB-07 (State persistence) round-trip tests.
 *
 * Uses snapshot-and-restore to leave .artifacts/ and .openlife/ byte-identical to the pre-test state.
 * All entities use a TEST_PREFIX so they cannot collide with real data.
 */
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const OrgStructure_1 = require("./orchestrator/OrgStructure");
const TeammateBoard_1 = require("./orchestrator/TeammateBoard");
const CadenceEngine_1 = require("./orchestrator/CadenceEngine");
const ExecutionBoard_1 = require("./orchestrator/ExecutionBoard");
const RoleHandoff_1 = require("./orchestrator/RoleHandoff");
const JobLifecycle_1 = require("./orchestrator/JobLifecycle");
const MissionState_1 = require("./orchestrator/MissionState");
const ServiceState_1 = require("./orchestrator/ServiceState");
const RuntimeRegistry_1 = require("./orchestrator/RuntimeRegistry");
const SubagentLifecycle_1 = require("./orchestrator/SubagentLifecycle");
const ExecutionState_1 = require("./orchestrator/ExecutionState");
const ROOT = process.cwd();
const TEST_PREFIX = `test-p3-${process.pid}-${Date.now()}`;
const TEST_WS = `${TEST_PREFIX}-ws`;
function assert(condition, message) {
    if (!condition)
        throw new Error(message);
}
function snap(filePath) {
    const existed = fs.existsSync(filePath);
    return {
        filePath,
        existed,
        content: existed ? fs.readFileSync(filePath, 'utf-8') : null
    };
}
function restore(s) {
    if (s.existed && s.content !== null) {
        fs.writeFileSync(s.filePath, s.content, 'utf-8');
    }
    else if (!s.existed && fs.existsSync(s.filePath)) {
        fs.unlinkSync(s.filePath);
    }
}
function removeIfMine(filePath) {
    // Only remove if our prefix appears in the path itself.
    if (filePath.includes(TEST_PREFIX) && fs.existsSync(filePath)) {
        try {
            const stat = fs.statSync(filePath);
            if (stat.isDirectory()) {
                fs.rmSync(filePath, { recursive: true, force: true });
            }
            else {
                fs.unlinkSync(filePath);
            }
        }
        catch {
            /* ignore */
        }
    }
}
async function main() {
    // Files we will mutate via shared registries (must snapshot+restore).
    const sharedFiles = [
        path.join(ROOT, '.artifacts', 'cadence-events.json'),
        path.join(ROOT, '.artifacts', 'execution-board.json'),
        path.join(ROOT, '.artifacts', 'role-handoffs.json'),
        path.join(ROOT, '.openlife', 'org-structure.json')
    ];
    const snapshots = sharedFiles.map(snap);
    // Per-workspace test dirs we create — fully removable.
    const wsDir = path.join(ROOT, '.artifacts', 'workspaces', TEST_WS);
    // Subagent lifecycle file (unique per test, env-overridable).
    const subagentFile = path.join(ROOT, '.artifacts', `${TEST_PREFIX}-cloud-subagents.json`);
    process.env.OPENLIFE_CLOUD_SUBAGENTS_FILE = subagentFile;
    // Mission ids (unique to our prefix).
    const missionId = `${TEST_PREFIX}-mission`;
    const missionFile = path.join(ROOT, '.artifacts', 'missions', `${missionId}.json`);
    try {
        let cases = 0;
        // ============ SUB-06 ============
        // 1. OrgStructure — fetch defaults; assert non-empty.
        const org = new OrgStructure_1.OrgStructure();
        const roles = org.all();
        assert(Array.isArray(roles) && roles.length > 0, 'OrgStructure.all should return non-empty list');
        const cto = org.get('cto');
        assert(cto?.id === 'cto', 'OrgStructure.get(cto) should return cto role');
        cases++;
        // 2. TeammateBoard — upsert + list.
        const teammate = new TeammateBoard_1.TeammateBoardStore(TEST_WS);
        const card = {
            id: `${TEST_PREFIX}-card-1`,
            workspaceId: TEST_WS,
            owner: 'cto',
            status: 'in_progress',
            title: 'Test teammate card',
            blockers: [],
            comments: ['initial'],
            updatedAt: new Date().toISOString()
        };
        teammate.upsert(card);
        const teammateList = teammate.list();
        assert(teammateList.some((c) => c.id === card.id && c.title === card.title), 'TeammateBoard.upsert should make the card discoverable in list()');
        cases++;
        // 3. CadenceEngine — schedule + getAll.
        const cadence = new CadenceEngine_1.CadenceEngine();
        const cadenceTitle = `${TEST_PREFIX}-review`;
        const event = cadence.schedule('review', cadenceTitle, 'cto', `${TEST_PREFIX}-mission-ops`);
        assert(event.id && event.status === 'scheduled', 'CadenceEngine.schedule should return scheduled event');
        const cadenceList = cadence.getAll();
        assert(cadenceList.some((e) => e.title === cadenceTitle), 'CadenceEngine.getAll should include the scheduled event');
        cases++;
        // 4. ExecutionBoard — add + getAll.
        const board = new ExecutionBoard_1.ExecutionBoard();
        const boardId = `${TEST_PREFIX}-board-1`;
        board.add({
            id: boardId,
            title: 'Test board item',
            ownerRole: 'cto',
            status: 'queued',
            priority: 'medium',
            dependencies: [],
            slaHours: 24,
            notes: 'phase3 test'
        });
        const boardList = board.getAll();
        assert(boardList.some((b) => b.id === boardId && b.status === 'queued'), 'ExecutionBoard.add should persist the item visible in getAll');
        cases++;
        // 5. RoleHandoff — create + getAll.
        const handoff = new RoleHandoff_1.RoleHandoff();
        const handoffId = `${TEST_PREFIX}-handoff-1`;
        handoff.create({
            id: handoffId,
            fromRole: 'cpo',
            toRole: 'cto',
            missionId: boardId,
            summary: 'Test handoff',
            status: 'queued'
        });
        const handoffList = handoff.getAll();
        assert(handoffList.some((h) => h.id === handoffId && h.summary === 'Test handoff'), 'RoleHandoff.create should persist record visible in getAll');
        cases++;
        // ============ SUB-07 ============
        // 6. JobLifecycle — enqueue → transition → get/events round-trip.
        const jobs = new JobLifecycle_1.JobLifecycleStore(TEST_WS);
        const job = jobs.enqueue('phase3-state-test', TEST_WS);
        jobs.transition(job.jobId, TEST_WS, 'started', 'started by test', 'agent-test');
        const jobRead = jobs.get(job.jobId);
        assert(jobRead !== null, 'JobLifecycleStore.get should round-trip the job');
        assert(jobRead.jobId === job.jobId, 'jobId should round-trip');
        assert(jobRead.goal === 'phase3-state-test', 'goal should round-trip');
        assert(jobRead.status === 'started', 'transition should be persisted');
        const evts = jobs.events(job.jobId);
        assert(evts.length >= 2, 'JobLifecycleStore.events should record enqueue+transition');
        cases++;
        // 7. MissionState — persist + read raw JSON round-trip.
        const missionStore = new MissionState_1.MissionStateStore();
        const exec = (0, ExecutionState_1.createExecutionState)(missionId, 'phase3 mission goal', 'test-user');
        const mission = {
            ...exec,
            workspaceId: TEST_WS,
            mode: 'task',
            chosenAgents: [],
            chosenSquads: [],
            chosenSkills: [],
            routeMode: 'single',
            memoryCandidates: []
        };
        const persistPath = missionStore.persist(mission);
        assert(fs.existsSync(persistPath), 'MissionStateStore.persist should write a file');
        const reread = JSON.parse(fs.readFileSync(persistPath, 'utf-8'));
        assert(reread.taskId === mission.taskId, 'MissionState.taskId round-trip');
        assert(reread.goal === mission.goal, 'MissionState.goal round-trip');
        assert(reread.mode === 'task', 'MissionState.mode round-trip');
        cases++;
        // 8. ServiceState — promoteTaskToService + getById round-trip.
        const services = new ServiceState_1.ServiceStateStore(TEST_WS);
        const serviceId = `${TEST_PREFIX}-svc`;
        const svc = services.promoteTaskToService(mission, serviceId, 'phase3 service objective', {
            actor: 'phase3-test',
            consentScope: 'task_promotion',
            reason: 'subsystems regression test',
        });
        assert(svc.serviceId === serviceId, 'ServiceState.promoteTaskToService returns matching serviceId');
        const svcRead = services.getById(serviceId);
        assert(svcRead !== null, 'ServiceState.getById should round-trip');
        assert(svcRead.objective === 'phase3 service objective', 'ServiceState.objective round-trip');
        assert(svcRead.missionIds.includes(mission.taskId), 'ServiceState.missionIds should include promoted mission');
        cases++;
        // 9. RuntimeRegistry — probe + list round-trip.
        const runtime = new RuntimeRegistry_1.RuntimeRegistry(TEST_WS);
        const probed = runtime.probe();
        assert(probed.length >= 1, 'RuntimeRegistry.probe should return at least one entry');
        assert(probed.some((e) => e.id === 'local-shell' && e.available === true), 'local-shell should be available');
        const listed = runtime.list();
        assert(listed.length === probed.length, 'RuntimeRegistry.list should round-trip probe result');
        assert(listed.every((e, i) => e.id === probed[i].id && e.kind === probed[i].kind), 'RuntimeRegistry list entries should deep-equal probe (id+kind)');
        cases++;
        // 10. SubagentLifecycle — create + transition + list round-trip.
        const subagents = new SubagentLifecycle_1.SubagentLifecycle(subagentFile);
        const sub = subagents.create(`${TEST_PREFIX}-sub`, ['cap-a', 'cap-b']);
        assert(sub.state === 'proposed', 'New subagent should be in proposed state');
        const transitioned = subagents.transition(sub.id, 'trial');
        assert(transitioned?.state === 'trial', 'SubagentLifecycle.transition proposed→trial should succeed');
        const subList = subagents.list();
        const found = subList.find((s) => s.id === sub.id);
        assert(found !== undefined, 'SubagentLifecycle.list should round-trip created subagent');
        assert(found.name === sub.name, 'subagent.name round-trip');
        assert(JSON.stringify(found.capabilities) === JSON.stringify(sub.capabilities), 'capabilities round-trip');
        assert(found.state === 'trial', 'persisted state reflects transition');
        cases++;
        // 11. ExecutionState — factory round-trip (in-memory; no persistence of its own).
        const es = (0, ExecutionState_1.createExecutionState)(`${TEST_PREFIX}-exec`, 'goal-x', 'user-x');
        assert(es.taskId === `${TEST_PREFIX}-exec`, 'createExecutionState.taskId');
        assert(es.status === 'running', 'createExecutionState.status default running');
        assert(Array.isArray(es.attempts) && es.attempts.length === 0, 'attempts initially empty');
        assert(Array.isArray(es.governanceEvents), 'governanceEvents initialised');
        cases++;
        console.log(`TEST_SUBSYSTEMS_ORG_STATE cases=${cases}`);
        console.log('TEST_SUBSYSTEMS_ORG_STATE_OK');
    }
    finally {
        // === Cleanup hygiene ===
        // 1. Restore shared snapshots so any test-prefixed entries we appended are wiped.
        for (const s of snapshots) {
            restore(s);
        }
        // 2. Remove per-test artefacts.
        removeIfMine(wsDir);
        removeIfMine(subagentFile);
        removeIfMine(missionFile);
        delete process.env.OPENLIFE_CLOUD_SUBAGENTS_FILE;
    }
}
main().catch((err) => {
    console.error('TEST_SUBSYSTEMS_ORG_STATE_FAIL:', err?.message || err);
    process.exit(1);
});
