/**
 * Worker Daemon Service
 * Node.js-based background worker system that auto-runs like shell daemons
 *
 * Workers:
 * - map: Codebase mapping (5 min interval)
 * - audit: Security analysis (10 min interval)
 * - optimize: Performance optimization (15 min interval)
 * - consolidate: Memory consolidation (30 min interval)
 * - testgaps: Test coverage analysis (20 min interval)
 */
import { EventEmitter } from 'events';
import { HeadlessWorkerExecutor } from './headless-worker-executor.js';
export type WorkerType = 'ultralearn' | 'optimize' | 'consolidate' | 'predict' | 'audit' | 'map' | 'preload' | 'deepdive' | 'document' | 'refactor' | 'benchmark' | 'testgaps';
interface WorkerConfig {
    type: WorkerType;
    intervalMs: number;
    priority: 'low' | 'normal' | 'high' | 'critical';
    description: string;
    enabled: boolean;
}
interface WorkerState {
    lastRun?: Date;
    nextRun?: Date;
    runCount: number;
    successCount: number;
    failureCount: number;
    averageDurationMs: number;
    isRunning: boolean;
    lastStartedAt?: Date;
}
interface WorkerResult {
    workerId: string;
    type: WorkerType;
    success: boolean;
    durationMs: number;
    output?: unknown;
    error?: string;
    timestamp: Date;
}
interface DaemonStatus {
    running: boolean;
    pid: number;
    startedAt?: Date;
    workers: Map<WorkerType, WorkerState>;
    config: DaemonConfig;
}
export interface DaemonConfig {
    autoStart: boolean;
    logDir: string;
    stateFile: string;
    maxConcurrent: number;
    workerTimeoutMs: number;
    resourceThresholds: {
        maxCpuLoad: number;
        minFreeMemoryPercent: number;
    };
    workers: WorkerConfig[];
}
/**
 * Worker Daemon - Manages background workers with Node.js
 */
export declare class WorkerDaemon extends EventEmitter {
    private config;
    private workers;
    private timers;
    private queuePollTimer?;
    private running;
    private startedAt?;
    private projectRoot;
    private runningWorkers;
    private pendingWorkers;
    private headlessExecutor;
    private headlessAvailable;
    private originalConfig?;
    constructor(projectRoot: string, config?: Partial<DaemonConfig>);
    /**
     * Initialize headless executor if Claude Code is available
     */
    private initHeadlessExecutor;
    /**
     * Check if headless execution is available
     */
    isHeadlessAvailable(): boolean;
    /**
     * Get headless executor instance
     */
    getHeadlessExecutor(): HeadlessWorkerExecutor | null;
    /**
     * Detect effective CPU count for the current environment.
     *
     * Inside Docker / K8s containers, os.cpus().length reports the HOST cpu
     * count, not the container limit (Node.js #28762 — wontfix).  We read
     * cgroup v2 / v1 quota files first so the maxCpuLoad threshold stays
     * meaningful under resource-limited containers.
     */
    /**
     * #2110 — detect WSL2 / WSL1 so the CPU-load gate can use a sane
     * default. `/proc/loadavg` on WSL maps in Windows-side process counts
     * and routinely reports values 100-1000x larger than real Linux load.
     *
     * Detection order:
     *   1. `WSL_DISTRO_NAME` env var (set by Microsoft's WSL launcher)
     *   2. `WSL_INTEROP` env var (set by recent WSL2)
     *   3. `/proc/sys/kernel/osrelease` contains "microsoft" or "WSL"
     *      (kernel build marker; survives env stripping)
     */
    static isWslEnvironment(): boolean;
    static getEffectiveCpuCount(): number;
    /**
     * Read daemon-specific config from .claude-flow/config.{json,yaml,yml}.
     * Supports dot-notation keys like 'daemon.resourceThresholds.maxCpuLoad'.
     * #1844: prefer JSON when both exist (existing behavior) but fall back
     * to YAML so operators using the v3 canonical YAML format aren't silently
     * ignored. The chosen path is logged at info level.
     */
    private readDaemonConfigFromFile;
    /**
     * Setup graceful shutdown handlers
     */
    private setupShutdownHandlers;
    /**
     * #1855: install crash handlers for uncaught exceptions and unhandled
     * rejections. Without these, a thrown error from any timer callback,
     * worker logic path, or transitive import crashes the daemon process
     * silently — the PID file leaks and any in-flight child processes
     * orphan. With these, we log a structured crash record, run stop()
     * to clean up, then exit 1 so the process actually dies (otherwise
     * Node would crash anyway after the handler returns).
     */
    private installCrashHandlers;
    /**
     * Append a structured crash record to .claude-flow/logs/crash.log.
     * Inspectable by hand or via `ruflo daemon status` follow-ups.
     */
    private writeCrashRecord;
    /**
     * Path to the on-disk children registry — list of headless worker
     * child PIDs the daemon currently owns. #1855: written on every
     * execution:start / :complete / :error transition; read by the next
     * lifetime to reap orphans after a hard crash.
     */
    private get childrenFile();
    /**
     * #1856: detect workers that were mid-flight when the previous daemon
     * lifetime ended. A mid-flight worker has `lastStartedAt > lastRun`
     * (started after the last successful completion). On crash recovery
     * we count these as failures so the run-counter math stays consistent
     * (`runCount === successCount + failureCount`). Workers naturally
     * retry at their next scheduled interval; we deliberately don't
     * immediately re-run because the failure may have been deterministic.
     */
    private detectMidFlightFailures;
    /**
     * Snapshot the currently-active headless worker child PIDs to disk.
     * Best-effort; failures don't propagate.
     */
    private writeChildrenSnapshot;
    /**
     * #1855: reap orphan headless worker children left behind by a
     * previous crashed lifetime. Reads `.claude-flow/daemon-children.json`,
     * SIGTERMs any PID still alive that doesn't belong to the current
     * daemon, then truncates the file. Called at the top of `start()`
     * so the next lifetime starts with a clean process tree.
     */
    private reapOrphanedChildren;
    /**
     * Check if system resources allow worker execution
     */
    private canRunWorker;
    /**
     * Process pending workers queue
     *
     * When executeWorkerWithConcurrencyControl defers a worker (returns null),
     * we break immediately to avoid a busy-wait loop — the deferred worker is
     * already back on the pendingWorkers queue by that point. If no workers are
     * currently running when we break, we schedule a backoff retry so the queue
     * does not get permanently stuck.
     */
    private processPendingWorkers;
    private initializeWorkerStates;
    /**
     * Get the PID file path for singleton enforcement (#1395 Bug 3).
     */
    private get pidFile();
    /**
     * Check if another daemon instance is already running.
     * Returns the existing PID if alive, or null if no daemon is running.
     *
     * #1853: ignore self-PID matches. The detached-spawn path in
     * `commands/daemon.ts` writes the child's PID into the file as a
     * fallback after a 500ms wait. If the child reaches `start()` slower
     * than the parent's 500ms wait (observed on Node 25 / macOS 26), the
     * child reads its own PID back from the file and concludes "another
     * daemon is already running" — so it exits before scheduling workers
     * and `daemon status` reports STOPPED forever. A daemon process is
     * never "another instance" of itself; treat self-match as absence.
     */
    private checkExistingDaemon;
    /**
     * Write PID file for singleton enforcement.
     */
    private writePidFile;
    /**
     * Remove PID file on shutdown.
     */
    private removePidFile;
    /**
     * Start the daemon and all enabled workers
     */
    start(): Promise<void>;
    /**
     * #1845: ingest queue entries written by mcp__hooks_worker-dispatch.
     * Each entry is a JSON file at `.claude-flow/daemon-queue/<id>.json`
     * with `{ workerId, trigger, context, enqueuedAt }`. We move processed
     * files to `.claude-flow/daemon-queue/.processed/` so the daemon never
     * re-runs the same dispatch and operators can inspect history.
     */
    private processDispatchQueue;
    /**
     * Stop the daemon and all workers
     */
    stop(): Promise<void>;
    /**
     * Get daemon status
     */
    getStatus(): DaemonStatus;
    /**
     * Schedule a worker to run at intervals with staggered start
     */
    private scheduleWorker;
    /**
     * Execute a worker with concurrency control (P0 fix)
     */
    private executeWorkerWithConcurrencyControl;
    /**
     * Execute a worker with timeout protection
     */
    private executeWorker;
    /**
     * Run a function with timeout (P1 fix)
     * @param fn - The async function to execute
     * @param timeoutMs - Timeout in milliseconds
     * @param timeoutMessage - Error message on timeout
     * @param onTimeout - Optional cleanup callback invoked when timeout fires (#1117: kills orphan processes)
     */
    private runWithTimeout;
    /**
     * Run the actual worker logic
     */
    private runWorkerLogic;
    /**
     * #1793: persist a headless worker result to the same metrics file the
     * local fallback writes to. Without this, AI-mode workers produced rich
     * structured output (audit findings, perf signals, test-gap analysis)
     * that lived only in `.claude-flow/logs/headless/*_result.log` and was
     * invisible to `npx ruflo memory stats` or the metrics consumers.
     *
     * The mapping mirrors the `*Local` worker implementations below so a
     * single consumer path works regardless of execution mode.
     */
    private persistHeadlessResult;
    private runMapWorker;
    /**
     * Local audit worker (fallback when headless unavailable)
     */
    private runAuditWorkerLocal;
    /**
     * Local optimize worker (fallback when headless unavailable)
     */
    private runOptimizeWorkerLocal;
    private runConsolidateWorker;
    /**
     * Local testgaps worker (fallback when headless unavailable)
     */
    private runTestGapsWorkerLocal;
    /**
     * Local predict worker (fallback when headless unavailable)
     */
    private runPredictWorkerLocal;
    /**
     * Local document worker (fallback when headless unavailable)
     */
    private runDocumentWorkerLocal;
    /**
     * Local ultralearn worker (fallback when headless unavailable)
     */
    private runUltralearnWorkerLocal;
    /**
     * Local refactor worker (fallback when headless unavailable)
     */
    private runRefactorWorkerLocal;
    /**
     * Local deepdive worker (fallback when headless unavailable)
     */
    private runDeepdiveWorkerLocal;
    /**
     * Local benchmark worker
     */
    private runBenchmarkWorkerLocal;
    /**
     * Local preload worker
     */
    private runPreloadWorkerLocal;
    /**
     * Manually trigger a worker
     */
    triggerWorker(type: WorkerType): Promise<WorkerResult>;
    /**
     * Enable/disable a worker
     */
    setWorkerEnabled(type: WorkerType, enabled: boolean): void;
    /**
     * Save daemon state to file
     */
    private saveState;
    /**
     * Log message
     */
    private log;
}
/**
 * Get or create daemon instance
 */
export declare function getDaemon(projectRoot?: string, config?: Partial<DaemonConfig>): WorkerDaemon;
/**
 * Start daemon (for use in session-start hook)
 */
export declare function startDaemon(projectRoot: string, config?: Partial<DaemonConfig>): Promise<WorkerDaemon>;
/**
 * Stop daemon
 */
export declare function stopDaemon(): Promise<void>;
export default WorkerDaemon;
//# sourceMappingURL=worker-daemon.d.ts.map