/**
 * Nexus Prime - Enhanced with Engines
 *
 * Local-first MCP control plane for coding agents.
 */
import { v4 as uuidv4 } from 'uuid';
import { createEvolutionEngine, createFissionProtocol } from './core/evolution.js';
import { createAttentionEconomics, createInfiniteContext } from './core/optimize.js';
import { createCoordinator } from './agents/coordinator.js';
import { createAdapter } from './agents/adapters.js';
import { AgentLearner } from './agents/learner.js';
// Import engines
import { createTokenOptimizer, createContextEngine, createMemoryEngine, createOrchestrator, } from './engines/index.js';
import { SessionDNAManager } from './engines/session-dna.js';
import { DashboardServer } from './dashboard/server.js';
import { nexusEventBus } from './engines/event-bus.js';
import { ClientRegistry } from './engines/client-registry.js';
import { podNetwork } from './engines/pod-network.js';
import { createSubAgentRuntime, summarizeExecution } from './phantom/index.js';
import { collectBootstrapManifest, ensureBootstrap } from './engines/client-bootstrap.js';
import { initSynapse } from './synapse/index.js';
import { initArchitects } from './architects/index.js';
import { createEmbedder } from './engines/embedder.js';
import { buildRuntimeHealthEnvelope, createEngineHealthStatus } from './engines/runtime-health.js';
import { resolveEngineStorageRoot, resolveWorkspaceContext } from './engines/workspace-resolver.js';
import { resolveMandatoryRuntimePlan } from './engines/runtime-supervisor.js';
import { resolveArchitectsPaths } from './architects/db/client.js';
import { resolveSynapsePaths } from './synapse/db/client.js';
import { createChannelArtifactEnvelope, mapChannelThread, } from './channels/gateway.js';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const PACKAGE_ROOT = path.join(__dirname, '..');
class EngineBackedAgentMemory {
    agentId;
    memoryEngine;
    embedder = createEmbedder();
    constructor(agentId, memoryEngine) {
        this.agentId = agentId;
        this.memoryEngine = memoryEngine;
    }
    learn(experience) {
        const summary = `Agent ${this.agentId}: ${experience.action} -> ${experience.outcome}`;
        this.memoryEngine.store(summary, Math.max(0.2, experience.value), ['#agent-experience', `#agent:${this.agentId}`]);
        const pattern = {
            id: `pattern_${uuidv4()}`,
            structure: this.embedder.embedSync(`${experience.action}\n${experience.outcome}`),
            weight: experience.value,
            confidence: Math.max(0.1, Math.min(1, experience.value)),
            origin: this.agentId,
            timestamp: experience.timestamp,
            examples: [experience.action, experience.outcome],
        };
        return experience.value > 0.9 ? pattern : undefined;
    }
}
export class NexusPrime {
    config;
    adapters = new Map();
    agents = new Map();
    memories = new Map();
    // NEW: Enhanced Engines
    tokenOptimizer;
    contextEngine;
    memoryEngine;
    orchestrator = null;
    runtime;
    learner = null;
    sessionDNA;
    clientRegistry;
    deferOrchestratorInit = false;
    inspectionStartup;
    runtimeDeferred = false;
    coordinator;
    evolution;
    fission;
    attention;
    context;
    running = false;
    runtimeHotAt = null;
    dashboardServer;
    synapse = null;
    architects = null;
    synapseInitError = null;
    workspaceContext;
    synapseHealth = createEngineHealthStatus({ name: 'synapse', available: false, ready: false, reason: 'Synapse not started yet.' });
    architectsHealth = createEngineHealthStatus({ name: 'architects', available: false, ready: false, reason: 'Architects not started yet.' });
    scheduledAutomationTicker = null;
    deferredStartupPromise = null;
    _cachedTokenStats = null;
    _cachedTokenStatsAt = 0;
    constructor(config) {
        const traceStartup = process.env.NEXUS_STARTUP_TRACE === '1';
        const startupTraceOrigin = Date.now();
        const markStartup = (label) => {
            if (traceStartup) {
                console.error(`[StartupTrace +${Date.now() - startupTraceOrigin}ms] constructor:${label}`);
            }
        };
        markStartup('workspace:resolve:start');
        this.workspaceContext = resolveWorkspaceContext({
            workspaceRoot: config?.runtime?.workspaceRoot,
        });
        markStartup('workspace:resolve:done');
        process.env.NEXUS_WORKSPACE_ROOT = this.workspaceContext.workspaceRoot;
        const memoryDbPath = config?.memory?.cortex?.path ?? process.env.NEXUS_MEMORY_DB_PATH;
        this.config = {
            network: {
                port: config?.network?.port ?? 3000,
                peers: config?.network?.peers ?? [],
                consensus: config?.network?.consensus ?? 'raft'
            },
            memory: {
                cortex: {
                    enabled: config?.memory?.cortex?.enabled ?? true,
                    storage: config?.memory?.cortex?.storage ?? 'sqlite',
                    vector: config?.memory?.cortex?.vector ?? 'hnsw',
                    path: memoryDbPath
                },
                hippocampus: {
                    window: config?.memory?.hippocampus?.window ?? '48h',
                    consolidation: config?.memory?.hippocampus?.consolidation ?? '6h'
                },
                prefrontal: {
                    items: config?.memory?.prefrontal?.items ?? 7
                }
            },
            evolution: {
                mutationRate: config?.evolution?.mutationRate ?? 0.01,
                selectionPressure: config?.evolution?.selectionPressure ?? 0.9,
                coherenceThreshold: config?.evolution?.coherenceThreshold ?? 0.8
            },
            adapters: config?.adapters ?? [],
            startupProfile: config?.startupProfile ?? 'full',
            runtime: {
                workspaceRoot: this.workspaceContext.workspaceRoot,
            },
        };
        this.inspectionStartup = this.config.startupProfile === 'inspect';
        this.deferOrchestratorInit = this.inspectionStartup || (this.config.adapters.length === 1 && this.config.adapters[0] === 'mcp');
        // Initialize legacy systems
        markStartup('legacy-systems:init:start');
        this.coordinator = createCoordinator('hierarchical', this.config.network.consensus);
        this.evolution = createEvolutionEngine(this.config.evolution);
        this.fission = createFissionProtocol();
        this.attention = createAttentionEconomics();
        this.context = createInfiniteContext();
        markStartup('legacy-systems:init:done');
        // Initialize NEW engines
        markStartup('token-context:init:start');
        this.tokenOptimizer = createTokenOptimizer(this.config.memory.cortex.enabled ? 128000 : 64000);
        this.contextEngine = createContextEngine();
        markStartup('token-context:init:done');
        markStartup('memory:init:start');
        this.memoryEngine = createMemoryEngine(memoryDbPath);
        markStartup('memory:init:done');
        markStartup('session-client:init:start');
        this.sessionDNA = new SessionDNAManager(`nexus-${Date.now()}`);
        this.clientRegistry = new ClientRegistry();
        markStartup('session-client:init:done');
        markStartup('runtime:init:start');
        if (this.deferOrchestratorInit) {
            this.runtime = this.createInspectionRuntime();
            this.runtimeDeferred = !this.inspectionStartup;
        }
        else {
            this.runtime = createSubAgentRuntime({
                repoRoot: this.workspaceContext.repoRoot,
                artifactsRoot: path.join(this.workspaceContext.stateRoot, 'runs'),
                memory: this.memoryEngine,
                sessionDNA: this.sessionDNA,
            });
        }
        markStartup('runtime:init:done');
        if (this.deferOrchestratorInit) {
            markStartup('orchestrator:init:deferred');
            markStartup('learner:init:deferred');
        }
        else {
            this.ensureOrchestrator(markStartup);
            this.ensureLearner(markStartup);
        }
        markStartup('dashboard:init:start');
        this.dashboardServer = new DashboardServer({
            runtimeProvider: () => this.runtime,
            orchestratorProvider: () => this.orchestrator ?? undefined,
            memoryProvider: () => this.memoryEngine,
            adaptersProvider: () => this.getAdapters(),
            clientRegistryProvider: () => this.clientRegistry,
            // Lazy-init Pillar 2 on first dashboard call. CLAUDE.md §3: "If someone
            // asks to fix Synapse or Architects, the answer is: wire the init path."
            // ensureSynapseInit/ensureArchitectsInit are no-ops once initialized.
            synapseProvider: () => {
                this.ensureSynapseInit();
                return this.synapse ?? undefined;
            },
            architectsProvider: () => {
                this.ensureArchitectsInit();
                return this.architects ?? undefined;
            },
            runtimeHealthProvider: () => this.getRuntimeHealthEnvelope(),
            workspaceContextProvider: () => this.getWorkspaceContext(),
            synapseInitErrorProvider: () => this.synapseInitError,
            reinitSynapseProvider: () => {
                this.synapseInitError = null;
                this.synapse = null;
                this.ensureSynapseInit();
            },
            repoRoot: this.workspaceContext.repoRoot,
        });
        markStartup('dashboard:init:done');
    }
    async start() {
        console.error('🧬 Nexus Prime (Enhanced) starting...');
        const traceStartup = process.env.NEXUS_STARTUP_TRACE === '1';
        const startupTraceOrigin = Date.now();
        const markStartup = (label) => {
            if (traceStartup) {
                console.error(`[StartupTrace +${Date.now() - startupTraceOrigin}ms] ${label}`);
            }
        };
        // Defer the (file-I/O heavy) bootstrap refresh in daemon-style modes.
        // Triggers:
        //   - MCP-only: caller is a stdio MCP server.
        //   - NEXUS_DAEMON_FAST_START=1: explicit opt-in for `nexus-prime daemon
        //     __serve` so the dashboard port listens before the file-I/O completes.
        //     Tests that pass `adapters: []` and synchronously check workspace
        //     files do NOT set this flag, so bootstrap stays sync for them.
        const deferBootstrapRefresh = process.env.NEXUS_DAEMON_FAST_START === '1'
            || (this.config.adapters.length === 1 && this.config.adapters[0] === 'mcp');
        let bootstrapManifest;
        if (this.inspectionStartup) {
            markStartup('bootstrapManifest:collect');
            bootstrapManifest = collectBootstrapManifest({
                packageRoot: PACKAGE_ROOT,
                workspaceRoot: this.workspaceContext.workspaceRoot,
            });
            const repoRoot = this.workspaceContext.repoRoot;
            const architectsStorage = resolveEngineStorageRoot(repoRoot, 'architects');
            const synapseStorage = resolveEngineStorageRoot(repoRoot, 'synapse');
            this.architectsHealth = createEngineHealthStatus({
                name: 'architects',
                available: true,
                ready: true,
                repoRoot,
                requestedStorageRoot: architectsStorage.requestedRoot,
                storageRoot: architectsStorage.storageRoot,
                dbPath: resolveArchitectsPaths(architectsStorage.storageRoot).dbPath,
                fallbackApplied: architectsStorage.fallbackApplied,
                reason: architectsStorage.fallbackReason,
            });
            this.synapseHealth = createEngineHealthStatus({
                name: 'synapse',
                available: true,
                ready: true,
                repoRoot,
                requestedStorageRoot: synapseStorage.requestedRoot,
                storageRoot: synapseStorage.storageRoot,
                dbPath: resolveSynapsePaths(synapseStorage.storageRoot).dbPath,
                fallbackApplied: synapseStorage.fallbackApplied,
                reason: synapseStorage.fallbackReason,
            });
            this.runtime.recordBootstrapManifestStatus?.(bootstrapManifest);
            this.running = true;
            console.error('✅ Nexus Prime inspection status ready!');
            return;
        }
        else if (deferBootstrapRefresh) {
            markStartup('bootstrapManifest:minimal');
            bootstrapManifest = {
                version: 1,
                generatedAt: Date.now(),
                workspaceRoot: this.workspaceContext.workspaceRoot,
                clients: [],
            };
            // Defer the bootstrap refresh to AFTER finishEngineStartup runs (chain via
            // setImmediate twice). If we queued it now, the bootstrap setImmediate would
            // sit ahead of finishEngineStartup in the FIFO queue and block dashboard
            // listen behind 3+ seconds of file I/O.
            setImmediate(() => {
                setImmediate(() => {
                    try {
                        const refreshedManifest = ensureBootstrap({
                            packageRoot: PACKAGE_ROOT,
                            workspaceRoot: this.workspaceContext.workspaceRoot,
                            phase: 'runtime',
                            silent: true,
                        });
                        this.runtime.recordBootstrapManifestStatus?.(refreshedManifest);
                    }
                    catch (error) {
                        console.error('[Bootstrap] Deferred runtime bootstrap refresh failed:', error instanceof Error ? error.message : String(error));
                    }
                });
            });
        }
        else {
            markStartup('ensureBootstrap:start');
            bootstrapManifest = ensureBootstrap({
                packageRoot: PACKAGE_ROOT,
                workspaceRoot: this.workspaceContext.workspaceRoot,
                phase: 'runtime',
                silent: true,
            });
            markStartup('ensureBootstrap:done');
        }
        this.runtime.recordBootstrapManifestStatus?.(bootstrapManifest);
        const currentClient = detectCurrentClient();
        if (currentClient) {
            markStartup(`clientHeartbeat:${currentClient.clientId}:start`);
            this.clientRegistry.recordHeartbeat(currentClient.clientId, {
                source: 'manual',
                metadata: {
                    origin: 'nexus-process-bootstrap',
                    detectedBy: currentClient.source,
                    workspaceRoot: this.workspaceContext.workspaceRoot,
                    repoRoot: this.workspaceContext.repoRoot,
                },
            });
            markStartup(`clientHeartbeat:${currentClient.clientId}:done`);
        }
        for (const adapterType of this.config.adapters) {
            markStartup(`adapter:${adapterType}:start`);
            await this.addAdapter(adapterType);
            markStartup(`adapter:${adapterType}:done`);
        }
        if (deferBootstrapRefresh) {
            // Do NOT set running=true here. finishEngineStartup sets it at the correct time.
            // Setting it early causes clients to treat a partially-initialized server as ready.
            markStartup('engineInit:deferred');
            this.deferredStartupPromise = new Promise((resolve, reject) => {
                setImmediate(() => {
                    this.finishEngineStartup(markStartup).then(resolve, reject);
                });
            }).catch((error) => {
                this.running = false;
                console.error('[Startup] Deferred engine initialization failed:', error instanceof Error ? error.message : String(error));
                throw error;
            });
            return this.deferredStartupPromise;
        }
        await this.finishEngineStartup(markStartup);
    }
    async finishEngineStartup(markStartup) {
        this.ensureFullRuntime(markStartup);
        const orchestrator = this.ensureOrchestrator(markStartup);
        const repoRoot = this.workspaceContext.repoRoot;
        markStartup('runtimePlan:resolve:start');
        const runtimePlan = resolveMandatoryRuntimePlan(this.workspaceContext);
        markStartup('runtimePlan:resolve:done');
        // In MCP-only mode, Synapse and Architects are not required by the bootstrap or orchestrate
        // hot paths. Default them to lazy (skip DB open + schema migration at startup) unless the
        // caller has explicitly opted in via NEXUS_ARCHITECTS_LAZY=0 / NEXUS_SYNAPSE_LAZY=0.
        // In full mode (adapters != ['mcp']), the existing behavior is preserved: eager by default,
        // lazy only when NEXUS_ARCHITECTS_LAZY=1 / NEXUS_SYNAPSE_LAZY=1.
        const mcpOnlyMode = this.config.adapters.length === 1 && this.config.adapters[0] === 'mcp';
        // v6: Synapse + Architects always attempt init. Lazy only when explicitly requested.
        // Lazy-init fallback via ensureSynapseInit() / ensureArchitectsInit() handles late recovery.
        // Kill-switch: `NEXUS_DISABLE_WORKFORCE=1` forces both Synapse + Architects
        // to skip eager init (and ensure*Init() becomes a no-op).  Orchestration
        // still runs — the workforce pillar is simply absent.  Intended as an
        // escape hatch when operative infra is causing runtime failures.
        const workforceDisabled = process.env.NEXUS_DISABLE_WORKFORCE === '1';
        const architectsLazy = workforceDisabled || process.env.NEXUS_ARCHITECTS_LAZY === '1';
        const synapseEnvLazy = workforceDisabled || process.env.NEXUS_SYNAPSE_LAZY === '1';
        if (workforceDisabled) {
            console.error('[NexusPrime] Workforce disabled by NEXUS_DISABLE_WORKFORCE=1. Synapse + Architects will not initialize.');
        }
        const architectsPlan = runtimePlan.engines.architects;
        if (!architectsLazy) {
            markStartup('architects:init:start');
            this.architects = initArchitects({
                repoRoot,
                requestedStorageRoot: architectsPlan.requestedStorageRoot,
                storageRoot: architectsPlan.activeStorageRoot,
            });
            markStartup('architects:init:done');
            this.architectsHealth = this.architects?.getStatus() ?? createEngineHealthStatus({
                name: 'architects',
                available: false,
                ready: false,
                repoRoot,
                requestedStorageRoot: architectsPlan.requestedStorageRoot,
                storageRoot: architectsPlan.activeStorageRoot,
                dbPath: architectsPlan.dbPath,
                fallbackApplied: architectsPlan.fallbackApplied,
                reason: `Architects failed to initialize for ${architectsPlan.dbPath}.`,
            });
            if (!this.architects) {
                console.error(`[NexusPrime] Architects engine degraded: ${this.architectsHealth.reason ?? 'unknown'}`);
            }
        }
        else {
            markStartup('architects:init:lazy-skipped');
            this.architectsHealth = createEngineHealthStatus({ name: 'architects', available: false, ready: false, deferred: true, reason: 'Architects deferred (lazy mode).' });
        }
        const coordination = this.createSynapseCoordinationBridge();
        const synapsePlan = runtimePlan.engines.synapse;
        if (!synapseEnvLazy) {
            markStartup('synapse:init:start');
            this.synapse = initSynapse({
                repoRoot,
                requestedStorageRoot: synapsePlan.requestedStorageRoot,
                storageRoot: synapsePlan.activeStorageRoot,
                orchestrator,
                memory: this.memoryEngine,
                sessionDNA: this.sessionDNA,
                coordination,
            });
            markStartup('synapse:init:done');
            this.synapseHealth = this.synapse?.getStatus() ?? createEngineHealthStatus({
                name: 'synapse',
                available: false,
                ready: false,
                repoRoot,
                requestedStorageRoot: synapsePlan.requestedStorageRoot,
                storageRoot: synapsePlan.activeStorageRoot,
                dbPath: synapsePlan.dbPath,
                fallbackApplied: synapsePlan.fallbackApplied,
                reason: `Synapse failed to initialize for ${synapsePlan.dbPath}.`,
            });
            if (!this.synapse) {
                const reason = this.synapseHealth.reason ?? 'unknown';
                console.error(`[NexusPrime] synapse-init-failed reason="${reason}"`);
                this.synapseInitError = { message: reason, stack: null, at: Date.now() };
            }
        }
        else {
            markStartup('synapse:init:lazy-skipped');
            this.synapseHealth = createEngineHealthStatus({ name: 'synapse', available: false, ready: false, deferred: true, reason: 'Synapse deferred (lazy mode).' });
        }
        // Dashboard listens synchronously so `running=true` and the port-listen happen
        // before any deferred work runs (otherwise the deferred bootstrap would block
        // the dashboard's setImmediate behind it).
        const dashboardDisabledExplicitly = process.env.NEXUS_DASHBOARD_IN_MCP === '0';
        if (!dashboardDisabledExplicitly) {
            try {
                markStartup('dashboard:start');
                this.dashboardServer.start();
            }
            catch (err) {
                console.error('[NexusPrime] dashboard start failed:', err instanceof Error ? err.message : String(err));
            }
        }
        else {
            markStartup('dashboard:skip-mcp-only');
        }
        // Event bridge must be live before start() resolves — tests + the dashboard
        // use it for cross-process events. It's a cheap fs watch registration.
        if (process.env.NEXUS_EVENT_BRIDGE_DISABLED !== '1') {
            try {
                markStartup('eventBus:startFilePolling');
                nexusEventBus.startFilePolling();
            }
            catch (err) {
                console.error('[NexusPrime] eventBus.startFilePolling failed:', err instanceof Error ? err.message : String(err));
            }
        }
        // Automation ticker + system.boot signal are observation-only — defer.
        setImmediate(() => {
            try {
                markStartup('automationTicker:start');
                this.startScheduledAutomationTicker();
            }
            catch { /* best-effort */ }
            try {
                nexusEventBus.emit('system.boot', { version: '5.0.0', toolsCount: 55 });
            }
            catch { /* best-effort */ }
        });
        this.running = true;
        this.runtimeHotAt = Date.now();
        markStartup('running:true');
        console.error('✅ Nexus Prime running with engines!');
    }
    async stop() {
        console.error('🧬 Nexus Prime stopping...');
        if (this.deferredStartupPromise) {
            try {
                await this.deferredStartupPromise;
            }
            catch {
                // Deferred startup failures are already logged; shutdown should still proceed.
            }
            finally {
                this.deferredStartupPromise = null;
            }
        }
        for (const [, adapter] of this.adapters) {
            await adapter.disconnect();
            this.clientRegistry.recordDisconnect(adapter.name, {
                source: 'adapter-heartbeat',
                metadata: { adapterType: adapter.type },
            });
        }
        this.synapse?.stop();
        this.architects?.stop();
        if (this.scheduledAutomationTicker) {
            clearInterval(this.scheduledAutomationTicker);
            this.scheduledAutomationTicker = null;
        }
        this.dashboardServer.stop();
        nexusEventBus.stopFilePolling();
        this.orchestrator?.dispose();
        this.sessionDNA.flush();
        this.running = false;
        podNetwork.destroy();
        console.error('✅ Nexus Prime stopped');
    }
    startScheduledAutomationTicker() {
        if (process.env.NEXUS_AUTOMATION_SCHEDULER_DISABLED === '1') {
            return;
        }
        const pollMs = Math.max(10_000, Number(process.env.NEXUS_AUTOMATION_POLL_MS ?? 60_000));
        const tick = () => {
            void this.runtime.dispatchScheduledAutomations({
                goal: 'Execute due scheduled automations',
                executeConnectors: true,
            }).catch((error) => {
                console.error('Scheduled automation dispatch failed:', error instanceof Error ? error.message : error);
            });
        };
        // Delay first tick by pollMs — avoid competing with startup/bootstrap/orchestrate on process start.
        this.scheduledAutomationTicker = setInterval(tick, pollMs);
        this.scheduledAutomationTicker.unref?.();
    }
    /** Flush memory engine to SQLite (call before process exit) */
    flushMemory() {
        if (this.memoryEngine && typeof this.memoryEngine.flush === 'function') {
            this.memoryEngine.flush();
        }
        if (this.memoryEngine && typeof this.memoryEngine.flushVaultSync === 'function') {
            this.memoryEngine.flushVaultSync();
        }
    }
    /** Load memory from SQLite (call on startup) */
    loadMemory() {
        if (this.memoryEngine && typeof this.memoryEngine.load === 'function') {
            this.memoryEngine.load();
        }
    }
    /** Get the memory engine instance */
    get memory() {
        return this.memoryEngine;
    }
    /** Get memory tier stats (used by nexus_memory_stats MCP tool) */
    getMemoryStats() {
        if (this.memoryEngine && typeof this.memoryEngine.getStats === 'function') {
            return this.memoryEngine.getStats();
        }
        return {
            schemaVersion: 0,
            prefrontal: 0,
            hippocampus: 0,
            cortex: 0,
            totalLinks: 0,
            oldestEntry: null,
            purgeEligible: 0,
            quarantineBacklog: 0,
            lastHygieneAt: null,
            topTags: [],
        };
    }
    async addAdapter(type, customName) {
        const adapter = createAdapter(type, customName);
        if (adapter.type === 'mcp') {
            adapter.setNexusRef(this);
        }
        await adapter.connect();
        this.adapters.set(adapter.name, adapter);
        this.clientRegistry.recordHeartbeat(adapter.name, {
            source: 'adapter-heartbeat',
            metadata: { adapterType: adapter.type, agents: adapter.agents.length },
        });
    }
    async createAgent(type, options) {
        const id = options?.id ?? `agent_${type}_${uuidv4()}`;
        const agent = {
            id,
            type,
            capabilities: options?.capabilities ?? this.getDefaultCapabilities(type),
            memory: null,
            attention: 0.1,
            state: {
                current: 'idle',
                history: []
            }
        };
        const memory = new EngineBackedAgentMemory(id, this.memoryEngine);
        this.memories.set(id, memory);
        agent.memory = memory;
        this.coordinator.register(agent);
        this.agents.set(id, agent);
        console.error(`🤖 Created agent: ${id} (${type})`);
        return agent;
    }
    getAgent(id) {
        return this.agents.get(id);
    }
    getAllAgents() {
        return Array.from(this.agents.values());
    }
    getAdapters() {
        return Array.from(this.adapters.values());
    }
    // ===== NEW ENGINE METHODS =====
    /**
     * Optimize tokens using TokenOptimizer
     */
    async optimizeTokens(task) {
        const context = this.contextEngine.getAll();
        return this.tokenOptimizer.optimize(Array.isArray(context) ? context : [context], task);
    }
    /**
     * Add to context
     */
    addContext(content) {
        this.contextEngine.add(content);
    }
    /**
     * Get relevant context
     */
    getContext(query) {
        return this.contextEngine.getContext(query);
    }
    /**
     * Store in memory
     */
    storeMemory(content, priority = 1.0, tags = [], parentId, depth, options = {}) {
        const orchestrator = this.getOrchestrator();
        const normalizedTags = [...new Set(tags.map((tag) => String(tag)))];
        if (normalizedTags.includes('#auto') || normalizedTags.includes('system-bootstrap')) {
            const existing = this.memoryEngine.searchByTagsAndContent?.(content, normalizedTags, {
                fuzzy: true,
                limit: 1,
            }) ?? [];
            if (existing[0]?.id && Number(existing[0].score ?? 0) >= 0.94) {
                return existing[0].id;
            }
        }
        const controlPlaneResult = this.memoryEngine.storeWithControlPlane?.(content, priority, tags, parentId, depth, {
            sessionId: orchestrator.getSessionState()?.sessionId,
            scope: normalizedTags.includes('#shared') || normalizedTags.includes('#worker-shared') ? 'shared' : 'session',
            source: normalizedTags.includes('#worker') ? 'worker' : 'operator',
            verbatim: options.verbatim,
            provenance: {
                source: normalizedTags.includes('#worker') ? 'worker' : 'operator',
                sessionId: orchestrator.getSessionState()?.sessionId,
                agentId: options.agentId,
                summary: 'Stored through NexusPrime storeMemory.',
                tags: normalizedTags,
            },
        });
        const id = controlPlaneResult?.storedIds?.[0] ?? this.memoryEngine.store(content, priority, tags, parentId, depth, { verbatim: options.verbatim });
        this.runtime.recordMemoryHealth?.(this.memoryEngine.getHealthSummary?.());
        this.runtime.recordMemoryScopeUsage?.(this.memoryEngine.getScopeUsageSummary?.(orchestrator.getSessionState()?.sessionId));
        this.runtime.recordMemoryReconciliationSummary?.(controlPlaneResult?.summary ?? this.memoryEngine.getLastReconciliationSummary?.());
        void this.runtime.dispatchStoredMemory(id, content, priority, tags);
        return id;
    }
    /**
     * Recall from memory
     */
    async recallMemory(query, k = 5, agentId) {
        if (agentId) {
            const filtered = await this.memoryEngine.recall(query, k, { agentId });
            // fallback to unscoped if agent has no memories yet
            if (filtered.length > 0)
                return filtered;
        }
        return this.memoryEngine.recall(query, k);
    }
    /**
     * Expose the graph memory engine for temporal queries.
     */
    getGraphMemory() {
        return this.memoryEngine.getGraphMemory?.();
    }
    /**
     * Audit evolution candidates — returns structured analysis.
     */
    async auditEvolution() {
        return this.ensureLearner().identifyEvolutionCandidates();
    }
    /**
     * Analyze result for learning
     */
    async analyzeLearning(goal, decision) {
        await this.ensureLearner().analyze(goal, decision);
    }
    /**
     * Execute via orchestrator
     */
    async orchestrate(task, options) {
        return this.getOrchestrator().orchestrate(task, options);
    }
    /**
     * Push-mode dispatch: spawn a headless coding agent child process for the given goal.
     * Returns { runId, pid, invoker } immediately; the run proceeds in the background.
     * Stream progress via nexusEventBus 'dispatch.*' events.
     */
    async pushDispatch(opts) {
        const { pushDispatch: _pushDispatch } = await import('./engines/dispatch/push-dispatch.js');
        return _pushDispatch(opts);
    }
    getMemoryHealth() {
        return this.runtime.getMemoryHealth();
    }
    /** Run the tier promotion sweep. Called at session end (nexus_session_dna generate). */
    runTierPromotion() {
        return this.memoryEngine?.runTierPromotion?.() ?? null;
    }
    getMemoryScopeUsage() {
        return this.runtime.getMemoryScopeUsage();
    }
    getSharedMemorySnapshot(limit) {
        return this.runtime.getSharedMemorySnapshot(limit);
    }
    getMemoryReconciliationSummary() {
        return this.runtime.getMemoryReconciliationSummary();
    }
    traceMemory(id) {
        return this.runtime.traceMemory(id);
    }
    updateMemory(id, patch) {
        return this.runtime.updateMemory(id, patch);
    }
    deleteMemory(id, options) {
        return this.runtime.deleteMemory(id, options);
    }
    getMemoryHistory(id, limit) {
        return this.runtime.getMemoryHistory(id, limit);
    }
    submitMemoryFeedback(id, input) {
        return this.runtime.submitMemoryFeedback(id, input);
    }
    maintainMemory() {
        return this.runtime.maintainMemory();
    }
    runMemoryHygiene(options = {}) {
        return this.runtime.runMemoryHygiene(options);
    }
    exportMemoryBundle(options) {
        return this.runtime.exportMemoryBundle(options);
    }
    backupMemoryBundle(options) {
        return this.runtime.backupMemoryBundle(options);
    }
    async importMemoryBundle(input) {
        return this.runtime.importMemoryBundle(input);
    }
    listScheduledAutomations(options) {
        return this.runtime.listScheduledAutomations(options);
    }
    dispatchScheduledAutomations(options) {
        return this.runtime.dispatchScheduledAutomations(options);
    }
    listSessionSnapshots(sessionsDir) {
        return SessionDNAManager.listSnapshots(sessionsDir);
    }
    searchSessionHistory(query, options) {
        return SessionDNAManager.searchSnapshots(query, options);
    }
    mapChannelThread(input) {
        return mapChannelThread(input);
    }
    createChannelArtifactEnvelope(input) {
        return createChannelArtifactEnvelope(input);
    }
    // ===== EXECUTE (Enhanced) =====
    async execute(agentId, task, options) {
        const agent = this.agents.get(agentId);
        if (!agent) {
            throw new Error(`Agent not found: ${agentId}`);
        }
        // Use NEW engines
        this.optimizeTokens(task);
        this.getContext(task);
        agent.state.current = 'working';
        agent.state.history.push(task);
        const execution = await this.getOrchestrator().orchestrate(task, options);
        const result = execution.result || summarizeExecution(execution);
        const value = execution.state === 'merged'
            ? 1
            : execution.state === 'rolled_back'
                ? 0.25
                : execution.state === 'failed'
                    ? 0.1
                    : 0.6;
        const experience = {
            agentId,
            action: task,
            outcome: result,
            value,
            timestamp: Date.now()
        };
        // Learn (using legacy system)
        const memory = this.memories.get(agentId);
        if (memory) {
            memory.learn(experience);
        }
        // Also store in new memory engine
        this.storeMemory(`Agent ${agentId} executed: ${task} → ${result}`, value, [agent.type, 'execution', execution.state]);
        // Check for fission
        if (value > 0.9) {
            const pattern = memory?.learn(experience);
            if (pattern) {
                const neighbors = this.coordinator.getNeighbors(agentId);
                this.fission.fission(pattern, neighbors, (id) => ({
                    receive: (p, v) => {
                        const mem = this.memories.get(id);
                        if (mem) {
                            mem.learn({
                                agentId: id,
                                action: 'fission_received',
                                outcome: p.id,
                                value: v,
                                timestamp: Date.now()
                            });
                        }
                    }
                }));
            }
        }
        agent.state.current = 'idle';
        return { result, experience, execution };
    }
    getRuntime() {
        return this.runtime;
    }
    getOrchestrator() {
        return this.ensureOrchestrator();
    }
    /**
     * Resolves when the server has finished deferred engine startup.
     * MCP adapters should await this before creating or using the orchestrator.
     */
    awaitReady() {
        if (this.running)
            return Promise.resolve();
        return this.deferredStartupPromise ?? Promise.resolve();
    }
    getClientRegistry() {
        return this.clientRegistry;
    }
    getRuntimeHotAt() {
        return this.runtimeHotAt;
    }
    getDashboardAddress() {
        return this.dashboardServer.getAddress();
    }
    getSynapse() {
        return this.synapse;
    }
    getArchitects() {
        return this.architects;
    }
    /**
     * Lazy-init Synapse if it wasn't initialized at startup (e.g. native module failed).
     * Called automatically on first nexus_synapse_* tool call.
     */
    ensureSynapseInit() {
        if (this.synapse)
            return;
        // Kill-switch: `NEXUS_DISABLE_WORKFORCE=1` skips Synapse + Architects entirely.
        // Orchestration continues without the workforce pillar when set.  Useful
        // when native-module failures make operative init flaky at runtime.
        if (process.env.NEXUS_DISABLE_WORKFORCE === '1') {
            if (!this.synapseInitError) {
                this.synapseInitError = {
                    message: 'Synapse disabled by NEXUS_DISABLE_WORKFORCE=1',
                    stack: null,
                    at: Date.now(),
                };
            }
            return;
        }
        try {
            const runtimePlan = resolveMandatoryRuntimePlan(this.workspaceContext);
            const coordination = this.createSynapseCoordinationBridge();
            const synapsePlan = runtimePlan.engines.synapse;
            this.synapse = initSynapse({
                repoRoot: this.workspaceContext.repoRoot,
                requestedStorageRoot: synapsePlan.requestedStorageRoot,
                storageRoot: synapsePlan.activeStorageRoot,
                orchestrator: this.ensureOrchestrator(() => { }),
                memory: this.memoryEngine,
                sessionDNA: this.sessionDNA,
                coordination,
                // First explicit tool call counts as opt-in even when the config gate is off.
                forceEnable: true,
            });
            if (this.synapse) {
                this.synapseHealth = this.synapse.getStatus();
                this.synapseInitError = null;
                console.error('[NexusPrime] Synapse lazy-initialized successfully.');
            }
        }
        catch (err) {
            const e = err;
            console.error(`[NexusPrime] synapse-init-failed reason="${e.message}"`);
            this.synapseInitError = { message: e.message, stack: e.stack ?? null, at: Date.now() };
        }
    }
    getSynapseInitError() {
        return this.synapseInitError;
    }
    /**
     * Lazy-init Architects if it wasn't initialized at startup.
     * Called automatically on first nexus_architects_* tool call.
     */
    ensureArchitectsInit() {
        if (this.architects)
            return;
        if (process.env.NEXUS_DISABLE_WORKFORCE === '1')
            return;
        try {
            const runtimePlan = resolveMandatoryRuntimePlan(this.workspaceContext);
            const architectsPlan = runtimePlan.engines.architects;
            this.architects = initArchitects({
                repoRoot: this.workspaceContext.repoRoot,
                requestedStorageRoot: architectsPlan.requestedStorageRoot,
                storageRoot: architectsPlan.activeStorageRoot,
                // First explicit tool call counts as opt-in even when the config gate is off.
                forceEnable: true,
            });
            if (this.architects) {
                this.architectsHealth = this.architects.getStatus();
                // Reconnect coordination bridge into existing Synapse instance
                // so the mandate pipeline can reach Architects for blueprint/worklist creation.
                this.reconnectSynapseCoordination();
                console.error('[NexusPrime] Architects lazy-initialized successfully.');
            }
        }
        catch (err) {
            console.error('[NexusPrime] Architects lazy-init failed:', err.message);
        }
    }
    /**
     * Re-wire the Synapse coordination bridge after Architects becomes available.
     * Safe to call multiple times — only updates if both Synapse and Architects are live.
     */
    reconnectSynapseCoordination() {
        if (!this.synapse || !this.architects)
            return;
        const bridge = this.createSynapseCoordinationBridge();
        if (bridge) {
            this.synapse.providers.coordination = bridge;
            this.synapse.providers.claimWorkItem = (wid, oid) => bridge.claimWorkItem(wid, oid);
            this.synapse.providers.completeWorkItem = (wid, oid, s) => bridge.completeWorkItem(wid, oid, s);
            console.error('[NexusPrime] Synapse ↔ Architects coordination bridge reconnected.');
        }
    }
    getWorkspaceContext() {
        return resolveWorkspaceContext({
            workspaceRoot: process.env.NEXUS_WORKSPACE_ROOT || this.config.runtime.workspaceRoot || this.workspaceContext.workspaceRoot,
            cwd: process.cwd(),
            env: process.env,
        });
    }
    /**
     * Promote a hinted workspace context (e.g. resolved from nexus_session_bootstrap
     * file hints) so the dashboard + downstream consumers stop showing the stdio
     * MCP fallback ("/" → "workspace"). Only accepts contexts that look like a
     * real project root — never filesystem root, never the installed-package dir.
     */
    setWorkspaceContext(next) {
        if (!next || typeof next.repoRoot !== 'string')
            return false;
        const nextRoot = next.repoRoot.trim();
        if (!nextRoot || nextRoot === '/' || nextRoot === '.')
            return false;
        if (!next.repoName || !next.repoName.trim())
            return false;
        const current = this.workspaceContext;
        // No-op if same root.
        if (current && current.repoRoot === nextRoot)
            return false;
        // Only replace if current looks broken (root/empty/package-like).
        const currentRoot = current?.repoRoot || '';
        const currentLooksBroken = !currentRoot || currentRoot === '/' ||
            currentRoot.endsWith('/nexus-prime/dist') || currentRoot.endsWith('/node_modules/nexus-prime');
        if (!currentLooksBroken)
            return false;
        this.workspaceContext = next;
        this.config.runtime.workspaceRoot = next.workspaceRoot;
        process.env.NEXUS_WORKSPACE_ROOT = next.workspaceRoot;
        try {
            nexusEventBus.emit('workspace.changed', { repoRoot: next.repoRoot, repoName: next.repoName });
        }
        catch { /* best-effort */ }
        return true;
    }
    getRuntimeHealthEnvelope() {
        const clients = this.clientRegistry.listClients(this.getAdapters());
        const primaryClient = this.clientRegistry.getPrimaryClient(this.getAdapters());
        return buildRuntimeHealthEnvelope({
            workspace: this.getWorkspaceContext(),
            runtime: this.runtime,
            memory: this.memoryEngine,
            orchestrator: this.orchestrator ?? undefined,
            clients,
            primaryClient,
            synapse: this.synapseHealth,
            architects: this.architectsHealth,
        });
    }
    ensureOrchestrator(markStartup) {
        if (!this.orchestrator) {
            // Guarantee real runtime is promoted before orchestrator is created.
            // Without this, a race in MCP-only mode causes the orchestrator to bind
            // to the stub inspection runtime, which lacks planExecution() and crashes.
            this.ensureFullRuntime(markStartup);
            markStartup?.('orchestrator:init:start');
            this.orchestrator = createOrchestrator(this.memoryEngine, this.runtime, this.clientRegistry, this.sessionDNA, this.workspaceContext.repoRoot);
            markStartup?.('orchestrator:init:done');
        }
        return this.orchestrator;
    }
    createInspectionRuntime() {
        const usageSnapshot = {};
        return {
            getRuntimeId: () => `inspection:${this.workspaceContext.repoName}`,
            getUsageSnapshot: () => usageSnapshot,
            listRuns: () => [],
            recordBootstrapManifestStatus: (manifest) => {
                usageSnapshot.bootstrapManifestStatus = manifest;
            },
        };
    }
    ensureFullRuntime(markStartup) {
        if (!this.runtimeDeferred) {
            return;
        }
        markStartup?.('runtime:promote:start');
        this.runtime = createSubAgentRuntime({
            repoRoot: this.workspaceContext.repoRoot,
            artifactsRoot: path.join(this.workspaceContext.stateRoot, 'runs'),
            memory: this.memoryEngine,
            sessionDNA: this.sessionDNA,
        });
        this.runtimeDeferred = false;
        markStartup?.('runtime:promote:done');
    }
    ensureLearner(markStartup) {
        if (!this.learner) {
            markStartup?.('learner:init:start');
            this.learner = new AgentLearner(this.memoryEngine);
            markStartup?.('learner:init:done');
        }
        return this.learner;
    }
    diagnoseRuntime() {
        const envelope = this.getRuntimeHealthEnvelope();
        const issues = [...envelope.degradedReasons];
        const bootstrapManifest = this.runtime.getUsageSnapshot().bootstrapManifestStatus;
        const driftedClients = bootstrapManifest?.clients?.filter((client) => client.state === 'drifted') ?? [];
        if (driftedClients.length) {
            issues.push(`Drifted client bootstrap detected: ${driftedClients.map((client) => client.clientId).join(', ')}.`);
        }
        if ((envelope.memory.available && envelope.runtime.available) && envelope.clients.total === 0) {
            issues.push('No coding clients are currently detected for this runtime.');
        }
        return {
            ok: issues.length === 0,
            issues,
            envelope,
            bootstrapManifest,
        };
    }
    autofixRuntime() {
        const bootstrapManifest = ensureBootstrap({
            packageRoot: PACKAGE_ROOT,
            workspaceRoot: this.getWorkspaceContext().workspaceRoot,
            phase: 'install',
            silent: true,
        });
        this.runtime.recordBootstrapManifestStatus?.(bootstrapManifest);
        return {
            bootstrapManifest,
            memoryMaintenance: this.maintainMemory(),
            diagnosis: this.diagnoseRuntime(),
        };
    }
    getSelectionLedger() {
        const snapshot = this.runtime.getUsageSnapshot();
        return {
            audit: snapshot.artifactSelectionAudit ?? null,
            outcomes: snapshot.artifactOutcome ?? null,
            workerPlan: snapshot.workerPlan ?? null,
            taskGraph: snapshot.taskGraph ?? null,
            catalogHealth: snapshot.catalogHealth ?? null,
        };
    }
    createSynapseCoordinationBridge() {
        if (!this.architects)
            return undefined;
        return {
            claimWorkItem: (workItemId, operativeId) => this.architects.claimWorkItem(workItemId, operativeId),
            completeWorkItem: (workItemId, operativeId, status) => this.architects.completeWorkItem(workItemId, operativeId, status).then(() => undefined),
            getWorklistId: (strikeTeamId) => this.architects?.getWorklistForStrikeTeam(strikeTeamId) ?? null,
            publish: (signal) => {
                const tags = [
                    '#coordination',
                    signal.phase ? `#phase:${signal.phase}` : null,
                    signal.status ? `#status:${signal.status}` : null,
                    signal.strikeTeamId ? `#team:${signal.strikeTeamId}` : null,
                    signal.worklistId ? `#worklist:${signal.worklistId}` : null,
                    signal.workItemId ? `#workitem:${signal.workItemId}` : null,
                    signal.runId ? `#run:${signal.runId}` : null,
                    signal.correlationId ? `#corr:${signal.correlationId}` : null,
                ].filter(Boolean);
                podNetwork.publish(signal.operativeId ? `synapse:${signal.operativeId}` : 'control-plane', signal.summary, signal.status === 'failed' || signal.status === 'blocked' ? 0.58 : 0.86, tags);
            },
        };
    }
    evolve() {
        const health = { coherence: 0.8, stagnation: 0.2 };
        this.evolution.govern(health);
    }
    getGrammar() {
        return this.evolution.getGrammar();
    }
    async broadcast(message) {
        const fullMessage = {
            ...message,
            id: uuidv4(),
            timestamp: Date.now()
        };
        for (const [, adapter] of this.adapters) {
            if (adapter.connected) {
                await adapter.send(fullMessage);
            }
        }
    }
    getConfig() {
        return { ...this.config };
    }
    getStats() {
        if (!this._cachedTokenStats || Date.now() - this._cachedTokenStatsAt > 30_000) {
            this._cachedTokenStats = this.optimizeTokens('status check');
            this._cachedTokenStatsAt = Date.now();
        }
        const tokens = this._cachedTokenStats;
        return {
            agents: this.agents.size,
            adapters: this.adapters.size,
            grammarRules: this.evolution.getGrammar().length,
            running: this.running,
            memory: this.getMemoryStats(),
            tokens
        };
    }
    getRuntimeStats() {
        return {
            agents: this.agents.size,
            adapters: this.adapters.size,
            grammarRules: this.evolution.getGrammar().length,
            running: this.running,
            memory: this.getMemoryStats(),
        };
    }
    getDefaultCapabilities(type) {
        const capabilities = {
            researcher: ['search', 'read', 'summarize', 'hypothesize'],
            coder: ['write', 'edit', 'refactor', 'debug'],
            reviewer: ['analyze', 'critique', 'suggest', 'approve'],
            tester: ['test', 'validate', 'verify', 'benchmark'],
            architect: ['design', 'plan', 'evaluate', 'optimize'],
            planner: ['plan', 'schedule', 'coordinate', 'prioritize'],
            executor: ['run', 'execute', 'deploy', 'monitor'],
            general: ['reason', 'learn', 'communicate', 'adapt']
        };
        return capabilities[type] ?? capabilities.general;
    }
}
export const createNexusPrime = (config) => new NexusPrime(config);
function detectCurrentClient() {
    if (process.env.CODEX_HOME || process.env.CODEX_SESSION) {
        return { clientId: 'codex', source: 'env' };
    }
    if (process.env.CURSOR_HOME || process.env.CURSOR_SESSION) {
        return { clientId: 'cursor', source: 'env' };
    }
    if (process.env.CLAUDE_CODE || process.env.CLAUDE_SESSION_ID || process.env.CLAUDE_PROJECT_DIR) {
        return { clientId: 'claude-code', source: 'env' };
    }
    if (process.env.OPENCODE_HOME) {
        return { clientId: 'opencode', source: 'env' };
    }
    if (process.env.OPENCLAW_HOME || process.env.ANTIGRAVITY_HOME) {
        return { clientId: 'antigravity', source: 'env' };
    }
    if (process.env.HERMES_HOME || process.env.HERMES_SESSION) {
        return { clientId: 'hermes', source: 'env' };
    }
    if (process.env.NANOCLAW_HOME || process.env.NANOCLAW_SESSION) {
        return { clientId: 'nanoclaw', source: 'env' };
    }
    if (process.env.PICOCLAW_HOME || process.env.PICOCLAW_SESSION) {
        return { clientId: 'picoclaw', source: 'env' };
    }
    if (process.env.WINDSURF_HOME || process.env.WINDSURF_SESSION) {
        return { clientId: 'windsurf', source: 'env' };
    }
    return null;
}
// Public API surface for sibling packages (e.g., @nexus-prime/finishit)
export { GhostPass, PhantomOrchestrator, PhantomWorker } from './phantom/index.js';
export { MemoryEngine, createMemoryEngine } from './engines/memory.js';
export { SessionDNAManager } from './engines/session-dna.js';
export { GithubBridge, getSharedGithubBridge } from './engines/github-bridge.js';
