openclaw-aegis 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/config/schema.ts","../src/config/loader.ts","../src/config/detector.ts","../src/platform/systemd.ts","../src/platform/launchd.ts","../src/health/probes/resolve-pid.ts","../src/health/probes/process.ts","../src/health/probes/port.ts","../src/health/probes/http.ts","../src/health/probes/config.ts","../src/health/probes/tun.ts","../src/health/probes/memory.ts","../src/health/probes/cpu.ts","../src/health/probes/disk.ts","../src/health/probes/log-tail.ts","../src/health/probes/websocket.ts","../src/health/scoring.ts","../src/health/monitor.ts","../src/incidents/logger.ts","../src/incidents/statistics.ts","../src/alerts/dispatcher.ts","../src/backup/manager.ts","../src/recovery/circuit-breaker.ts","../src/recovery/orchestrator.ts","../src/config-guardian/guardian.ts","../src/config-guardian/dead-man-switch.ts","../src/diagnosis/engine.ts","../src/diagnosis/doctor-wrapper.ts"],"sourcesContent":["export * from \"./types/index.js\";\nexport * from \"./config/schema.js\";\nexport * from \"./config/loader.js\";\nexport * from \"./config/detector.js\";\nexport * from \"./platform/systemd.js\";\nexport * from \"./platform/launchd.js\";\nexport * from \"./health/probes/index.js\";\nexport * from \"./health/scoring.js\";\nexport * from \"./health/monitor.js\";\nexport * from \"./incidents/logger.js\";\nexport * from \"./incidents/statistics.js\";\nexport * from \"./alerts/dispatcher.js\";\nexport * from \"./backup/manager.js\";\nexport * from \"./recovery/circuit-breaker.js\";\nexport * from \"./recovery/orchestrator.js\";\nexport * from \"./config-guardian/guardian.js\";\nexport * from \"./config-guardian/dead-man-switch.js\";\nexport * from \"./diagnosis/engine.js\";\nexport * from \"./diagnosis/doctor-wrapper.js\";\n","export interface HealthProbeResult {\n name: string;\n healthy: boolean;\n score: number;\n message?: string;\n latencyMs: number;\n}\n\nexport type ProbeTarget = { type: \"local\" } | { type: \"remote\"; host: string; port: number };\n\nexport interface RecoveryAction {\n level: \"L1\" | \"L2\" | \"L4\";\n action: string;\n result: \"success\" | \"failure\" | \"skipped\";\n durationMs: number;\n}\n\nexport interface IncidentEvent {\n timestamp: string;\n type: string;\n data: Record<string, unknown>;\n checksum: string;\n}\n\nexport type HealthBand = \"healthy\" | \"degraded\" | \"critical\";\n\nexport interface HealthScore {\n total: number;\n band: HealthBand;\n probeResults: HealthProbeResult[];\n}\n\nexport interface BackupEntry {\n path: string;\n timestamp: string;\n checksum: string;\n}\n\nexport interface KnownGoodEntry extends BackupEntry {\n promotedAt: string;\n}\n\nexport interface AlertPayload {\n severity: \"info\" | \"warning\" | \"critical\";\n title: string;\n body: string;\n timestamp: string;\n incidentId?: string;\n recoveryActions?: RecoveryAction[];\n healthScore?: HealthScore;\n}\n\nexport interface AlertResult {\n provider: string;\n success: boolean;\n error?: string;\n durationMs: number;\n}\n\nexport interface AlertProvider {\n name: string;\n send(alert: AlertPayload): Promise<AlertResult>;\n test(): Promise<boolean>;\n}\n\nexport interface PlatformAdapter {\n name: string;\n install(config: PlatformInstallConfig): Promise<void>;\n start(): Promise<void>;\n stop(): Promise<void>;\n restart(): Promise<void>;\n status(): Promise<PlatformServiceStatus>;\n notifyWatchdog(): Promise<void>;\n}\n\nexport interface PlatformInstallConfig {\n serviceName: string;\n execPath: string;\n workingDirectory: string;\n user: string;\n watchdogSec: number;\n readWritePaths: string[];\n}\n\nexport type PlatformServiceStatus = \"running\" | \"stopped\" | \"failed\" | \"unknown\";\n\nexport interface FailurePattern {\n id: number;\n name: string;\n detect(context: DiagnosisContext): Promise<boolean>;\n fix(context: DiagnosisContext): Promise<RecoveryAction>;\n}\n\nexport interface DiagnosisContext {\n configPath: string;\n pidFile: string;\n gatewayPort: number;\n logPath: string;\n knownGoodPath?: string;\n currentConfig: Record<string, unknown> | null;\n}\n\nexport const PROBE_WEIGHTS: Record<string, number> = {\n process: 2,\n port: 2,\n http: 2,\n config: 2,\n websocket: 1,\n tun: 1,\n memory: 1,\n cpu: 1,\n disk: 1,\n logTail: 1,\n};\n\nexport const MAX_HEALTH_SCORE = Object.values(PROBE_WEIGHTS).reduce((a, b) => a + b, 0) * 2;\n\nexport const PROTECTED_CONFIG_KEYS = [\n \"allowFrom\",\n \"groupAllowFrom\",\n \"authToken\",\n \"token\",\n \"webhookUrl\",\n \"apiKey\",\n] as const;\n\nexport const CRITICAL_CONFIG_KEYS = [\n \"gateway.port\",\n \"authToken\",\n \"token\",\n \"autoAck\",\n \"autoAckMessage\",\n \"allowFrom\",\n \"groupAllowFrom\",\n] as const;\n","import { z } from \"zod\";\n\nconst alertChannelSchema = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"ntfy\"),\n url: z.string().url().default(\"https://ntfy.sh\"),\n topic: z.string().min(1),\n priority: z.number().int().min(1).max(5).default(4),\n }),\n z.object({\n type: z.literal(\"webhook\"),\n url: z.string().url(),\n secret: z.string().min(1).optional(),\n }),\n z.object({\n type: z.literal(\"telegram\"),\n botToken: z.string().min(1),\n chatId: z.string().min(1),\n }),\n z.object({\n type: z.literal(\"whatsapp\"),\n phoneNumberId: z.string().min(1),\n accessToken: z.string().min(1),\n recipientNumber: z.string().min(1),\n }),\n z.object({\n type: z.literal(\"slack\"),\n webhookUrl: z.string().url(),\n channel: z.string().optional(),\n }),\n z.object({\n type: z.literal(\"discord\"),\n webhookUrl: z.string().url(),\n username: z.string().optional(),\n }),\n z.object({\n type: z.literal(\"email\"),\n host: z.string().min(1),\n port: z.number().int().min(1).max(65535).default(587),\n secure: z.boolean().default(false),\n username: z.string().min(1),\n password: z.string().min(1),\n from: z.string().min(1),\n to: z.string().min(1),\n }),\n z.object({\n type: z.literal(\"pushover\"),\n apiToken: z.string().min(1),\n userKey: z.string().min(1),\n device: z.string().optional(),\n }),\n]);\n\nexport type AlertChannelConfig = z.infer<typeof alertChannelSchema>;\n\nexport const aegisConfigSchema = z.object({\n gateway: z\n .object({\n configPath: z.string().default(\"~/.openclaw/openclaw.json\"),\n pidFile: z.string().default(\"openclaw-gateway.service\"),\n port: z.number().int().min(1).max(65535).default(18789),\n logPath: z.string().default(\"~/.openclaw/logs/gateway.log\"),\n healthEndpoint: z.string().default(\"/health\"),\n })\n .default({}),\n\n monitoring: z\n .object({\n intervalMs: z.number().int().min(1000).default(10000),\n probeTimeoutMs: z.number().int().min(500).default(5000),\n configPollIntervalMs: z.number().int().min(500).default(2000),\n degradedConfirmationCount: z.number().int().min(1).default(2),\n })\n .default({}),\n\n health: z\n .object({\n healthyMin: z.number().int().min(0).default(7),\n degradedMin: z.number().int().min(0).default(4),\n memoryThresholdMb: z.number().int().min(0).default(512),\n cpuThresholdPercent: z.number().int().min(0).max(100).default(90),\n diskThresholdMb: z.number().int().min(0).default(100),\n })\n .default({}),\n\n recovery: z\n .object({\n l1MaxAttempts: z.number().int().min(1).default(3),\n l1BackoffBaseMs: z.number().int().min(1000).default(5000),\n l1BackoffMultiplier: z.number().min(1).default(3),\n l2MaxAttempts: z.number().int().min(1).default(2),\n l2CooldownMs: z.number().int().min(1000).default(60000),\n circuitBreakerMaxCycles: z.number().int().min(1).default(3),\n circuitBreakerWindowMs: z.number().int().min(60000).default(3600000),\n antiFlap: z\n .object({\n maxRestarts: z.number().int().min(1).default(5),\n windowMs: z.number().int().min(60000).default(900000),\n cooldownMs: z.number().int().min(60000).default(600000),\n decayMs: z.number().int().min(60000).default(21600000),\n })\n .default({}),\n })\n .default({}),\n\n backup: z\n .object({\n maxChronological: z.number().int().min(1).default(20),\n maxKnownGood: z.number().int().min(1).default(3),\n knownGoodStabilityMs: z.number().int().min(10000).default(60000),\n basePath: z.string().default(\"~/.openclaw/aegis/backups\"),\n })\n .default({}),\n\n deadManSwitch: z\n .object({\n countdownMs: z.number().int().min(5000).default(30000),\n enabled: z.boolean().default(true),\n })\n .default({}),\n\n alerts: z\n .object({\n channels: z.array(alertChannelSchema).default([]),\n retryAttempts: z.number().int().min(0).default(3),\n retryBackoffMs: z.array(z.number().int()).default([5000, 15000, 45000]),\n })\n .default({}),\n\n platform: z\n .object({\n type: z.enum([\"systemd\", \"launchd\"]).default(\"systemd\"),\n watchdogSec: z.number().int().min(10).default(30),\n })\n .default({}),\n});\n\nexport type AegisConfig = z.infer<typeof aegisConfigSchema>;\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport TOML from \"@iarna/toml\";\nimport { aegisConfigSchema, type AegisConfig } from \"./schema.js\";\n\nexport function expandHome(filepath: string): string {\n if (filepath.startsWith(\"~/\")) {\n return path.join(os.homedir(), filepath.slice(2));\n }\n return filepath;\n}\n\nexport function resolveConfigPaths(config: AegisConfig): AegisConfig {\n return {\n ...config,\n gateway: {\n ...config.gateway,\n configPath: expandHome(config.gateway.configPath),\n pidFile: expandHome(config.gateway.pidFile),\n logPath: expandHome(config.gateway.logPath),\n },\n backup: {\n ...config.backup,\n basePath: expandHome(config.backup.basePath),\n },\n };\n}\n\nexport function loadConfig(configPath: string): AegisConfig {\n const resolvedPath = expandHome(configPath);\n\n if (!fs.existsSync(resolvedPath)) {\n const defaults = aegisConfigSchema.parse({});\n return resolveConfigPaths(defaults);\n }\n\n const raw = fs.readFileSync(resolvedPath, \"utf-8\");\n const parsed: unknown = TOML.parse(raw);\n const validated = aegisConfigSchema.parse(parsed);\n return resolveConfigPaths(validated);\n}\n\nexport const DEFAULT_CONFIG_PATH = \"~/.openclaw/aegis/config.toml\";\n\nexport function getConfigDir(): string {\n return expandHome(\"~/.openclaw/aegis\");\n}\n\nexport function ensureConfigDir(): void {\n const dir = getConfigDir();\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n}\n","import * as fs from \"node:fs\";\nimport { EventEmitter } from \"node:events\";\n\nexport interface ConfigChangeEvent {\n path: string;\n timestamp: number;\n source: \"polling\" | \"fswatch\";\n}\n\nexport class ConfigChangeDetector extends EventEmitter {\n private pollInterval: NodeJS.Timeout | null = null;\n private watcher: fs.FSWatcher | null = null;\n private lastMtime: number = 0;\n private changeTimestamps: number[] = [];\n private readonly stormThreshold: number;\n private readonly stormWindowMs: number;\n\n constructor(\n private readonly configPath: string,\n private readonly pollIntervalMs: number = 2000,\n stormThreshold: number = 5,\n stormWindowMs: number = 60000,\n ) {\n super();\n this.stormThreshold = stormThreshold;\n this.stormWindowMs = stormWindowMs;\n }\n\n start(): void {\n this.initMtime();\n this.startPolling();\n this.startFsWatch();\n }\n\n stop(): void {\n if (this.pollInterval) {\n clearInterval(this.pollInterval);\n this.pollInterval = null;\n }\n if (this.watcher) {\n this.watcher.close();\n this.watcher = null;\n }\n }\n\n private initMtime(): void {\n try {\n const stat = fs.statSync(this.configPath);\n this.lastMtime = stat.mtimeMs;\n } catch {\n this.lastMtime = 0;\n }\n }\n\n private startPolling(): void {\n this.pollInterval = setInterval(() => {\n this.checkMtime(\"polling\");\n }, this.pollIntervalMs);\n }\n\n private startFsWatch(): void {\n try {\n this.watcher = fs.watch(this.configPath, () => {\n this.checkMtime(\"fswatch\");\n });\n this.watcher.on(\"error\", () => {\n this.watcher?.close();\n this.watcher = null;\n });\n } catch {\n // fs.watch unavailable — polling is the primary mechanism\n }\n }\n\n private checkMtime(source: \"polling\" | \"fswatch\"): void {\n try {\n const stat = fs.statSync(this.configPath);\n if (stat.mtimeMs > this.lastMtime) {\n this.lastMtime = stat.mtimeMs;\n const event: ConfigChangeEvent = {\n path: this.configPath,\n timestamp: Date.now(),\n source,\n };\n this.recordChange(event.timestamp);\n this.emit(\"change\", event);\n }\n } catch {\n // File may not exist yet\n }\n }\n\n private recordChange(timestamp: number): void {\n this.changeTimestamps.push(timestamp);\n const cutoff = timestamp - this.stormWindowMs;\n this.changeTimestamps = this.changeTimestamps.filter((t) => t > cutoff);\n\n if (this.changeTimestamps.length > this.stormThreshold) {\n this.emit(\"storm\", {\n count: this.changeTimestamps.length,\n windowMs: this.stormWindowMs,\n });\n }\n }\n\n getRecentChangeCount(): number {\n const cutoff = Date.now() - this.stormWindowMs;\n return this.changeTimestamps.filter((t) => t > cutoff).length;\n }\n}\n","import * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport * as path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { PlatformAdapter, PlatformInstallConfig, PlatformServiceStatus } from \"../types/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport class SystemdAdapter implements PlatformAdapter {\n readonly name = \"systemd\";\n private serviceName = \"openclaw-aegis\";\n private watchdogInterval: NodeJS.Timeout | null = null;\n private watchdogSec = 30;\n\n async install(config: PlatformInstallConfig): Promise<void> {\n this.serviceName = config.serviceName;\n this.watchdogSec = config.watchdogSec;\n\n const unit = this.generateUnitFile(config);\n const unitPath = path.join(\n \"/etc/systemd/system\",\n `${config.serviceName}.service`,\n );\n\n fs.writeFileSync(unitPath, unit, { mode: 0o644 });\n await execFileAsync(\"systemctl\", [\"daemon-reload\"]);\n await execFileAsync(\"systemctl\", [\"enable\", config.serviceName]);\n }\n\n async start(): Promise<void> {\n await execFileAsync(\"systemctl\", [\"start\", this.serviceName]);\n }\n\n async stop(): Promise<void> {\n this.stopWatchdogHeartbeat();\n await execFileAsync(\"systemctl\", [\"stop\", this.serviceName]);\n }\n\n async restart(): Promise<void> {\n await execFileAsync(\"systemctl\", [\"restart\", this.serviceName]);\n }\n\n async status(): Promise<PlatformServiceStatus> {\n try {\n const { stdout } = await execFileAsync(\"systemctl\", [\n \"is-active\",\n this.serviceName,\n ]);\n const state = stdout.trim();\n if (state === \"active\") return \"running\";\n if (state === \"inactive\") return \"stopped\";\n if (state === \"failed\") return \"failed\";\n return \"unknown\";\n } catch {\n return \"unknown\";\n }\n }\n\n async notifyWatchdog(): Promise<void> {\n const socketPath = process.env[\"NOTIFY_SOCKET\"];\n if (!socketPath) return;\n\n return new Promise<void>((resolve, reject) => {\n const socket = net.createConnection(socketPath, () => {\n socket.end(\"WATCHDOG=1\", () => {\n resolve();\n });\n });\n socket.on(\"error\", reject);\n socket.setTimeout(1000);\n socket.on(\"timeout\", () => {\n socket.destroy();\n resolve();\n });\n });\n }\n\n startWatchdogHeartbeat(): void {\n const intervalMs = (this.watchdogSec / 2) * 1000;\n this.watchdogInterval = setInterval(() => {\n void this.notifyWatchdog();\n }, intervalMs);\n }\n\n stopWatchdogHeartbeat(): void {\n if (this.watchdogInterval) {\n clearInterval(this.watchdogInterval);\n this.watchdogInterval = null;\n }\n }\n\n generateUnitFile(config: PlatformInstallConfig): string {\n const rwPaths = config.readWritePaths.join(\" \");\n return `[Unit]\nDescription=OpenClaw Aegis Self-Healing Daemon\nAfter=network.target\nDocumentation=https://github.com/Canary-Builds/openclaw-aegis\n\n[Service]\nType=notify\nExecStart=/usr/bin/node ${config.execPath}\nExecStartPre=/usr/bin/node ${config.execPath} preflight\nWorkingDirectory=${config.workingDirectory}\nUser=${config.user}\nRestart=on-failure\nRestartSec=5\nStartLimitIntervalUSec=120s\nStartLimitBurst=5\nWatchdogSec=${config.watchdogSec}\nProtectSystem=strict\nPrivateTmp=true\nReadWritePaths=${rwPaths}\n\n[Install]\nWantedBy=multi-user.target\n`;\n }\n}\n","import type { PlatformAdapter, PlatformInstallConfig, PlatformServiceStatus } from \"../types/index.js\";\n\nexport class LaunchdAdapter implements PlatformAdapter {\n readonly name = \"launchd\";\n\n install(_config: PlatformInstallConfig): Promise<void> {\n return Promise.reject(new Error(\"LaunchdAdapter is not implemented in v1.0. See issue #373 for roadmap.\"));\n }\n\n start(): Promise<void> {\n return Promise.reject(new Error(\"LaunchdAdapter is not implemented in v1.0.\"));\n }\n\n stop(): Promise<void> {\n return Promise.reject(new Error(\"LaunchdAdapter is not implemented in v1.0.\"));\n }\n\n restart(): Promise<void> {\n return Promise.reject(new Error(\"LaunchdAdapter is not implemented in v1.0.\"));\n }\n\n status(): Promise<PlatformServiceStatus> {\n return Promise.resolve(\"unknown\");\n }\n\n notifyWatchdog(): Promise<void> {\n return Promise.resolve();\n }\n}\n","import * as fs from \"node:fs\";\nimport { execFileSync } from \"node:child_process\";\n\n/**\n * Resolve gateway PID. Tries systemd user service first, then falls back to PID file.\n * @param pidSource - systemd unit name (e.g. \"openclaw-gateway.service\") or path to PID file\n * @returns PID number, or null if unresolvable\n */\nexport function resolvePid(pidSource: string): number | null {\n // If it looks like a systemd unit name (contains \".service\" or no path separators)\n if (pidSource.endsWith(\".service\") || !pidSource.includes(\"/\")) {\n const pid = resolveFromSystemd(pidSource);\n if (pid !== null) return pid;\n }\n\n // Fall back to PID file\n return resolveFromFile(pidSource);\n}\n\nfunction resolveFromSystemd(unit: string): number | null {\n try {\n const output = execFileSync(\n \"systemctl\",\n [\"--user\", \"show\", \"-p\", \"MainPID\", \"--value\", unit],\n { encoding: \"utf-8\", timeout: 3000, stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n ).trim();\n\n const pid = parseInt(output, 10);\n if (!isNaN(pid) && pid > 0) return pid;\n return null;\n } catch {\n return null;\n }\n}\n\nfunction resolveFromFile(pidFile: string): number | null {\n try {\n if (!fs.existsSync(pidFile)) return null;\n const pidStr = fs.readFileSync(pidFile, \"utf-8\").trim();\n const pid = parseInt(pidStr, 10);\n if (!isNaN(pid) && pid > 0) return pid;\n return null;\n } catch {\n return null;\n }\n}\n","import type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\nimport { resolvePid } from \"./resolve-pid.js\";\n\nexport async function processProbe(\n _target: ProbeTarget,\n pidSource: string,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n try {\n const pid = resolvePid(pidSource);\n\n if (pid === null) {\n return {\n name: \"process\",\n healthy: false,\n score: 0,\n message: \"Gateway process not found (checked systemd unit and PID file)\",\n latencyMs: Date.now() - start,\n };\n }\n\n try {\n process.kill(pid, 0);\n return {\n name: \"process\",\n healthy: true,\n score: 2,\n latencyMs: Date.now() - start,\n };\n } catch {\n return {\n name: \"process\",\n healthy: false,\n score: 0,\n message: `Process ${pid} not running (stale PID)`,\n latencyMs: Date.now() - start,\n };\n }\n } catch (err) {\n return {\n name: \"process\",\n healthy: false,\n score: 0,\n message: `Process probe error: ${err instanceof Error ? err.message : String(err)}`,\n latencyMs: Date.now() - start,\n };\n }\n}\n","import * as net from \"node:net\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\n\nexport async function portProbe(\n target: ProbeTarget,\n port: number,\n timeoutMs: number = 5000,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n const host = target.type === \"remote\" ? target.host : \"127.0.0.1\";\n\n return new Promise<HealthProbeResult>((resolve) => {\n const socket = new net.Socket();\n let resolved = false;\n\n const finish = (result: HealthProbeResult) => {\n if (!resolved) {\n resolved = true;\n socket.destroy();\n resolve(result);\n }\n };\n\n socket.setTimeout(timeoutMs);\n\n socket.connect(port, host, () => {\n finish({\n name: \"port\",\n healthy: true,\n score: 2,\n latencyMs: Date.now() - start,\n });\n });\n\n socket.on(\"error\", (err) => {\n finish({\n name: \"port\",\n healthy: false,\n score: 0,\n message: `Port ${port} unreachable: ${err.message}`,\n latencyMs: Date.now() - start,\n });\n });\n\n socket.on(\"timeout\", () => {\n finish({\n name: \"port\",\n healthy: false,\n score: 0,\n message: `Port ${port} connection timed out after ${timeoutMs}ms`,\n latencyMs: Date.now() - start,\n });\n });\n });\n}\n","import * as http from \"node:http\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\n\nexport async function httpHealthProbe(\n target: ProbeTarget,\n port: number,\n endpoint: string = \"/health\",\n timeoutMs: number = 5000,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n const host = target.type === \"remote\" ? target.host : \"127.0.0.1\";\n\n return new Promise<HealthProbeResult>((resolve) => {\n const req = http.get(\n {\n hostname: host,\n port,\n path: endpoint,\n timeout: timeoutMs,\n },\n (res) => {\n const statusCode = res.statusCode ?? 0;\n res.resume();\n\n if (statusCode >= 200 && statusCode < 300) {\n resolve({\n name: \"http\",\n healthy: true,\n score: 2,\n latencyMs: Date.now() - start,\n });\n } else {\n resolve({\n name: \"http\",\n healthy: false,\n score: 0,\n message: `HTTP health returned status ${statusCode}`,\n latencyMs: Date.now() - start,\n });\n }\n },\n );\n\n req.on(\"error\", (err) => {\n resolve({\n name: \"http\",\n healthy: false,\n score: 0,\n message: `HTTP health probe failed: ${err.message}`,\n latencyMs: Date.now() - start,\n });\n });\n\n req.on(\"timeout\", () => {\n req.destroy();\n resolve({\n name: \"http\",\n healthy: false,\n score: 0,\n message: `HTTP health probe timed out after ${timeoutMs}ms`,\n latencyMs: Date.now() - start,\n });\n });\n });\n}\n","import * as fs from \"node:fs\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\n\nconst REQUIRED_CONFIG_PATHS: { path: string[]; label: string }[] = [\n { path: [\"gateway\", \"port\"], label: \"gateway.port\" },\n];\n\nconst POISON_KEYS = [\"autoAck\", \"autoAckMessage\"];\n\nexport async function configProbe(\n _target: ProbeTarget,\n configPath: string,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n\n try {\n if (!fs.existsSync(configPath)) {\n return {\n name: \"config\",\n healthy: false,\n score: 0,\n message: \"Gateway config file not found\",\n latencyMs: Date.now() - start,\n };\n }\n\n const raw = fs.readFileSync(configPath, \"utf-8\");\n let parsed: Record<string, unknown>;\n\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return {\n name: \"config\",\n healthy: false,\n score: 0,\n message: \"Gateway config is not valid JSON\",\n latencyMs: Date.now() - start,\n };\n }\n\n const missingPaths = REQUIRED_CONFIG_PATHS.filter(({ path }) => {\n let obj: unknown = parsed;\n for (const key of path) {\n if (obj === null || typeof obj !== \"object\" || !(key in obj)) return true;\n obj = (obj as Record<string, unknown>)[key];\n }\n return false;\n });\n if (missingPaths.length > 0) {\n return {\n name: \"config\",\n healthy: false,\n score: 0,\n message: `Missing required config keys: ${missingPaths.map((p) => p.label).join(\", \")}`,\n latencyMs: Date.now() - start,\n };\n }\n\n const foundPoison = POISON_KEYS.filter((key) => key in parsed);\n if (foundPoison.length > 0) {\n return {\n name: \"config\",\n healthy: false,\n score: 0,\n message: `Poison keys detected: ${foundPoison.join(\", \")}`,\n latencyMs: Date.now() - start,\n };\n }\n\n return {\n name: \"config\",\n healthy: true,\n score: 2,\n latencyMs: Date.now() - start,\n };\n } catch (err) {\n return {\n name: \"config\",\n healthy: false,\n score: 0,\n message: `Config probe error: ${err instanceof Error ? err.message : String(err)}`,\n latencyMs: Date.now() - start,\n };\n }\n}\n","import * as fs from \"node:fs\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport async function tunProbe(_target: ProbeTarget): Promise<HealthProbeResult> {\n const start = Date.now();\n\n try {\n // Check if any TUN device exists\n const tunDevices = fs\n .readdirSync(\"/sys/class/net\")\n .filter((dev) => {\n try {\n const type = fs.readFileSync(`/sys/class/net/${dev}/type`, \"utf-8\").trim();\n return type === \"65534\"; // ARPHRD_NONE — typical for TUN\n } catch {\n return false;\n }\n });\n\n if (tunDevices.length === 0) {\n return {\n name: \"tun\",\n healthy: true,\n score: 2,\n message: \"No TUN device configured (not required)\",\n latencyMs: Date.now() - start,\n };\n }\n\n // Check if TUN device is UP\n const tunDev = tunDevices[0];\n if (!tunDev) {\n return {\n name: \"tun\",\n healthy: true,\n score: 2,\n message: \"No TUN device configured (not required)\",\n latencyMs: Date.now() - start,\n };\n }\n const { stdout } = await execFileAsync(\"ip\", [\"link\", \"show\", tunDev]);\n const isUp = stdout.includes(\"state UP\") || stdout.includes(\",UP\");\n\n return {\n name: \"tun\",\n healthy: isUp,\n score: isUp ? 2 : 0,\n message: isUp ? undefined : `TUN device ${tunDev} is DOWN`,\n latencyMs: Date.now() - start,\n };\n } catch {\n return {\n name: \"tun\",\n healthy: true,\n score: 2,\n message: \"TUN probe skipped (not available on this platform)\",\n latencyMs: Date.now() - start,\n };\n }\n}\n","import * as fs from \"node:fs\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\nimport { resolvePid } from \"./resolve-pid.js\";\n\nexport async function memoryProbe(\n _target: ProbeTarget,\n pidSource: string,\n thresholdMb: number = 512,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n\n try {\n const pid = resolvePid(pidSource);\n\n if (pid === null) {\n return {\n name: \"memory\",\n healthy: false,\n score: 0,\n message: \"Gateway process not found — cannot check memory\",\n latencyMs: Date.now() - start,\n };\n }\n\n const statusPath = `/proc/${pid}/status`;\n\n if (!fs.existsSync(statusPath)) {\n return {\n name: \"memory\",\n healthy: false,\n score: 0,\n message: `Process ${pid} not found in /proc`,\n latencyMs: Date.now() - start,\n };\n }\n\n const status = fs.readFileSync(statusPath, \"utf-8\");\n const rssMatch = status.match(/VmRSS:\\s+(\\d+)\\s+kB/);\n\n if (!rssMatch) {\n return {\n name: \"memory\",\n healthy: true,\n score: 1,\n message: \"Could not parse RSS from /proc status\",\n latencyMs: Date.now() - start,\n };\n }\n\n const rssKb = parseInt(rssMatch[1] ?? \"0\", 10);\n const rssMb = rssKb / 1024;\n const healthy = rssMb < thresholdMb;\n\n return {\n name: \"memory\",\n healthy,\n score: healthy ? 2 : 0,\n message: healthy ? undefined : `RSS ${rssMb.toFixed(0)}MB exceeds threshold ${thresholdMb}MB`,\n latencyMs: Date.now() - start,\n };\n } catch (err) {\n return {\n name: \"memory\",\n healthy: false,\n score: 0,\n message: `Memory probe error: ${err instanceof Error ? err.message : String(err)}`,\n latencyMs: Date.now() - start,\n };\n }\n}\n","import * as fs from \"node:fs\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\nimport { resolvePid } from \"./resolve-pid.js\";\n\nexport async function cpuProbe(\n _target: ProbeTarget,\n pidSource: string,\n thresholdPercent: number = 90,\n sampleMs: number = 1000,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n\n try {\n const pid = resolvePid(pidSource);\n\n if (pid === null) {\n return {\n name: \"cpu\",\n healthy: false,\n score: 0,\n message: \"Gateway process not found — cannot check CPU\",\n latencyMs: Date.now() - start,\n };\n }\n\n const statPath = `/proc/${pid}/stat`;\n\n if (!fs.existsSync(statPath)) {\n return {\n name: \"cpu\",\n healthy: false,\n score: 0,\n message: `Process ${pid} not found in /proc`,\n latencyMs: Date.now() - start,\n };\n }\n\n const readCpuTime = (): number => {\n const stat = fs.readFileSync(statPath, \"utf-8\");\n const fields = stat.split(\" \");\n const utime = parseInt(fields[13] ?? \"0\", 10) || 0;\n const stime = parseInt(fields[14] ?? \"0\", 10) || 0;\n return utime + stime;\n };\n\n const cpuTime1 = readCpuTime();\n await new Promise((r) => setTimeout(r, sampleMs));\n const cpuTime2 = readCpuTime();\n\n const clockTicks = 100; // sysconf(_SC_CLK_TCK) — typically 100 on Linux\n const cpuDelta = (cpuTime2 - cpuTime1) / clockTicks;\n const cpuPercent = (cpuDelta / (sampleMs / 1000)) * 100;\n const healthy = cpuPercent < thresholdPercent;\n\n return {\n name: \"cpu\",\n healthy,\n score: healthy ? 2 : 0,\n message: healthy\n ? undefined\n : `CPU ${cpuPercent.toFixed(1)}% exceeds threshold ${thresholdPercent}%`,\n latencyMs: Date.now() - start,\n };\n } catch (err) {\n return {\n name: \"cpu\",\n healthy: false,\n score: 0,\n message: `CPU probe error: ${err instanceof Error ? err.message : String(err)}`,\n latencyMs: Date.now() - start,\n };\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport * as path from \"node:path\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport async function diskProbe(\n _target: ProbeTarget,\n configPath: string,\n thresholdMb: number = 100,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n\n try {\n const dir = path.dirname(configPath);\n const { stdout } = await execFileAsync(\"df\", [\"-BM\", \"--output=avail\", dir]);\n const lines = stdout.trim().split(\"\\n\");\n const lastLine = lines[lines.length - 1];\n if (!lastLine) {\n return {\n name: \"disk\",\n healthy: true,\n score: 1,\n message: \"Could not parse df output\",\n latencyMs: Date.now() - start,\n };\n }\n const availStr = lastLine.trim().replace(\"M\", \"\");\n const availMb = parseInt(availStr, 10);\n\n if (isNaN(availMb)) {\n return {\n name: \"disk\",\n healthy: true,\n score: 1,\n message: \"Could not parse disk space\",\n latencyMs: Date.now() - start,\n };\n }\n\n const healthy = availMb >= thresholdMb;\n\n return {\n name: \"disk\",\n healthy,\n score: healthy ? 2 : 0,\n message: healthy\n ? undefined\n : `Only ${availMb}MB available (threshold: ${thresholdMb}MB)`,\n latencyMs: Date.now() - start,\n };\n } catch (err) {\n return {\n name: \"disk\",\n healthy: true,\n score: 1,\n message: `Disk probe fallback: ${err instanceof Error ? err.message : String(err)}`,\n latencyMs: Date.now() - start,\n };\n }\n}\n","import * as fs from \"node:fs\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\n\nconst ERROR_PATTERNS = [\n /ECONNRESET/,\n /SIGTERM/,\n /SIGKILL/,\n /ENOMEM/,\n /fatal\\s+error/i,\n /uncaught\\s+exception/i,\n /unhandled\\s+rejection/i,\n /out\\s+of\\s+memory/i,\n /EACCES/,\n /ENOSPC/,\n];\n\nexport async function logTailProbe(\n _target: ProbeTarget,\n logPath: string,\n tailLines: number = 50,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n\n try {\n if (!fs.existsSync(logPath)) {\n return {\n name: \"logTail\",\n healthy: true,\n score: 2,\n message: \"Log file not found (may not exist yet)\",\n latencyMs: Date.now() - start,\n };\n }\n\n const content = fs.readFileSync(logPath, \"utf-8\");\n const lines = content.split(\"\\n\").slice(-tailLines);\n const recentText = lines.join(\"\\n\");\n\n const matchedPatterns = ERROR_PATTERNS.filter((p) => p.test(recentText));\n\n if (matchedPatterns.length === 0) {\n return {\n name: \"logTail\",\n healthy: true,\n score: 2,\n latencyMs: Date.now() - start,\n };\n }\n\n const score = matchedPatterns.length >= 3 ? 0 : 1;\n\n return {\n name: \"logTail\",\n healthy: false,\n score,\n message: `Error patterns in recent logs: ${matchedPatterns.map((p) => p.source).join(\", \")}`,\n latencyMs: Date.now() - start,\n };\n } catch (err) {\n return {\n name: \"logTail\",\n healthy: true,\n score: 1,\n message: `Log tail probe fallback: ${err instanceof Error ? err.message : String(err)}`,\n latencyMs: Date.now() - start,\n };\n }\n}\n","import WebSocket from \"ws\";\nimport type { HealthProbeResult, ProbeTarget } from \"../../types/index.js\";\n\nexport async function websocketProbe(\n target: ProbeTarget,\n port: number,\n timeoutMs: number = 5000,\n): Promise<HealthProbeResult> {\n const start = Date.now();\n const host = target.type === \"remote\" ? target.host : \"127.0.0.1\";\n const url = `ws://${host}:${port}`;\n\n return new Promise<HealthProbeResult>((resolve) => {\n let resolved = false;\n const finish = (result: HealthProbeResult) => {\n if (!resolved) {\n resolved = true;\n resolve(result);\n }\n };\n\n const timer = setTimeout(() => {\n ws.terminate();\n finish({\n name: \"websocket\",\n healthy: false,\n score: 0,\n message: `WebSocket handshake timed out after ${timeoutMs}ms`,\n latencyMs: Date.now() - start,\n });\n }, timeoutMs);\n\n const ws = new WebSocket(url, { handshakeTimeout: timeoutMs });\n\n ws.on(\"open\", () => {\n clearTimeout(timer);\n ws.close();\n finish({\n name: \"websocket\",\n healthy: true,\n score: 2,\n latencyMs: Date.now() - start,\n });\n });\n\n ws.on(\"error\", (err) => {\n clearTimeout(timer);\n ws.terminate();\n finish({\n name: \"websocket\",\n healthy: false,\n score: 0,\n message: `WebSocket probe failed: ${err.message}`,\n latencyMs: Date.now() - start,\n });\n });\n });\n}\n","import type { HealthProbeResult, HealthScore, HealthBand } from \"../types/index.js\";\nimport { PROBE_WEIGHTS, MAX_HEALTH_SCORE } from \"../types/index.js\";\n\nexport interface ScoringThresholds {\n healthyMin: number;\n degradedMin: number;\n}\n\nconst DEFAULT_THRESHOLDS: ScoringThresholds = {\n healthyMin: 7,\n degradedMin: 4,\n};\n\nexport function computeHealthScore(\n results: HealthProbeResult[],\n thresholds: ScoringThresholds = DEFAULT_THRESHOLDS,\n): HealthScore {\n let rawTotal = 0;\n\n for (const result of results) {\n const weight = PROBE_WEIGHTS[result.name] ?? 1;\n rawTotal += result.score * weight;\n }\n\n const normalized = MAX_HEALTH_SCORE > 0 ? Math.round((rawTotal / MAX_HEALTH_SCORE) * 10) : 0;\n const band = classifyBand(normalized, thresholds);\n\n return { total: normalized, band, probeResults: results };\n}\n\nfunction classifyBand(score: number, thresholds: ScoringThresholds): HealthBand {\n if (score >= thresholds.healthyMin) return \"healthy\";\n if (score >= thresholds.degradedMin) return \"degraded\";\n return \"critical\";\n}\n\nexport class DegradedConfirmation {\n private consecutiveDegradedCount = 0;\n private readonly requiredCount: number;\n\n constructor(requiredCount: number = 2) {\n this.requiredCount = requiredCount;\n }\n\n update(band: HealthBand): boolean {\n if (band === \"degraded\") {\n this.consecutiveDegradedCount++;\n return this.consecutiveDegradedCount >= this.requiredCount;\n }\n\n if (band === \"critical\") {\n this.consecutiveDegradedCount = 0;\n return true;\n }\n\n this.consecutiveDegradedCount = 0;\n return false;\n }\n\n reset(): void {\n this.consecutiveDegradedCount = 0;\n }\n\n getCount(): number {\n return this.consecutiveDegradedCount;\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { HealthProbeResult, HealthScore, ProbeTarget } from \"../types/index.js\";\nimport type { AegisConfig } from \"../config/schema.js\";\nimport { computeHealthScore, DegradedConfirmation } from \"./scoring.js\";\nimport { processProbe } from \"./probes/process.js\";\nimport { portProbe } from \"./probes/port.js\";\nimport { httpHealthProbe } from \"./probes/http.js\";\nimport { configProbe } from \"./probes/config.js\";\nimport { tunProbe } from \"./probes/tun.js\";\nimport { memoryProbe } from \"./probes/memory.js\";\nimport { cpuProbe } from \"./probes/cpu.js\";\nimport { diskProbe } from \"./probes/disk.js\";\nimport { logTailProbe } from \"./probes/log-tail.js\";\nimport { websocketProbe } from \"./probes/websocket.js\";\n\nexport class HealthMonitor extends EventEmitter {\n private interval: NodeJS.Timeout | null = null;\n private readonly degradedConfirmation: DegradedConfirmation;\n private lastScore: HealthScore | null = null;\n\n constructor(private readonly config: AegisConfig) {\n super();\n this.degradedConfirmation = new DegradedConfirmation(\n config.monitoring.degradedConfirmationCount,\n );\n }\n\n async runAllProbes(): Promise<HealthScore> {\n const target: ProbeTarget = { type: \"local\" };\n const timeout = this.config.monitoring.probeTimeoutMs;\n\n const withTimeout = async (\n fn: () => Promise<HealthProbeResult>,\n name: string,\n ): Promise<HealthProbeResult> => {\n try {\n return await Promise.race([\n fn(),\n new Promise<HealthProbeResult>((resolve) =>\n setTimeout(\n () =>\n resolve({\n name,\n healthy: false,\n score: 0,\n message: `Probe timed out after ${timeout}ms`,\n latencyMs: timeout,\n }),\n timeout,\n ),\n ),\n ]);\n } catch (err) {\n return {\n name,\n healthy: false,\n score: 0,\n message: `Probe error: ${err instanceof Error ? err.message : String(err)}`,\n latencyMs: 0,\n };\n }\n };\n\n const results = await Promise.allSettled([\n withTimeout(() => processProbe(target, this.config.gateway.pidFile), \"process\"),\n withTimeout(() => portProbe(target, this.config.gateway.port, timeout), \"port\"),\n withTimeout(\n () =>\n httpHealthProbe(\n target,\n this.config.gateway.port,\n this.config.gateway.healthEndpoint,\n timeout,\n ),\n \"http\",\n ),\n withTimeout(() => configProbe(target, this.config.gateway.configPath), \"config\"),\n withTimeout(() => tunProbe(target), \"tun\"),\n withTimeout(\n () => memoryProbe(target, this.config.gateway.pidFile, this.config.health.memoryThresholdMb),\n \"memory\",\n ),\n withTimeout(\n () => cpuProbe(target, this.config.gateway.pidFile, this.config.health.cpuThresholdPercent),\n \"cpu\",\n ),\n withTimeout(\n () => diskProbe(target, this.config.gateway.configPath, this.config.health.diskThresholdMb),\n \"disk\",\n ),\n withTimeout(() => logTailProbe(target, this.config.gateway.logPath), \"logTail\"),\n withTimeout(\n () => websocketProbe(target, this.config.gateway.port, timeout),\n \"websocket\",\n ),\n ]);\n\n const probeResults: HealthProbeResult[] = results.map((r, i) => {\n if (r.status === \"fulfilled\") return r.value;\n const names = [\n \"process\", \"port\", \"http\", \"config\", \"tun\",\n \"memory\", \"cpu\", \"disk\", \"logTail\", \"websocket\",\n ] as const;\n return {\n name: names[i] ?? \"unknown\",\n healthy: false,\n score: 0,\n message: `Probe rejected: ${r.reason instanceof Error ? r.reason.message : String(r.reason)}`,\n latencyMs: 0,\n };\n });\n\n const score = computeHealthScore(probeResults, {\n healthyMin: this.config.health.healthyMin,\n degradedMin: this.config.health.degradedMin,\n });\n\n this.lastScore = score;\n const shouldEscalate = this.degradedConfirmation.update(score.band);\n\n this.emit(\"check\", score);\n\n if (shouldEscalate && score.band !== \"healthy\") {\n this.emit(\"escalate\", score);\n }\n\n return score;\n }\n\n start(): void {\n this.interval = setInterval(() => {\n void this.runAllProbes();\n }, this.config.monitoring.intervalMs);\n }\n\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n\n getLastScore(): HealthScore | null {\n return this.lastScore;\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as crypto from \"node:crypto\";\nimport type { IncidentEvent } from \"../types/index.js\";\n\nexport class IncidentLogger {\n private currentIncidentId: string | null = null;\n private incidentStartTime: number | null = null;\n\n constructor(private readonly baseDir: string) {\n fs.mkdirSync(baseDir, { recursive: true, mode: 0o700 });\n }\n\n startIncident(): string {\n this.currentIncidentId = new Date().toISOString().replace(/[:.]/g, \"-\");\n this.incidentStartTime = Date.now();\n return this.currentIncidentId;\n }\n\n endIncident(): void {\n this.currentIncidentId = null;\n this.incidentStartTime = null;\n }\n\n getCurrentIncidentId(): string | null {\n return this.currentIncidentId;\n }\n\n getMttr(): number | null {\n if (!this.incidentStartTime) return null;\n return Date.now() - this.incidentStartTime;\n }\n\n log(type: string, data: Record<string, unknown>): IncidentEvent {\n const incidentId = this.currentIncidentId ?? \"no-incident\";\n const incidentDir = path.join(this.baseDir, incidentId);\n fs.mkdirSync(incidentDir, { recursive: true, mode: 0o700 });\n\n const event: IncidentEvent = {\n timestamp: new Date().toISOString(),\n type,\n data,\n checksum: \"\",\n };\n\n const payload = JSON.stringify({ timestamp: event.timestamp, type: event.type, data: event.data });\n event.checksum = crypto.createHash(\"sha256\").update(payload).digest(\"hex\");\n\n const logFile = path.join(incidentDir, \"events.jsonl\");\n fs.appendFileSync(logFile, JSON.stringify(event) + \"\\n\", { mode: 0o600 });\n\n return event;\n }\n\n getIncidents(): string[] {\n try {\n return fs\n .readdirSync(this.baseDir, { withFileTypes: true })\n .filter((d) => d.isDirectory() && d.name !== \"no-incident\")\n .map((d) => d.name)\n .sort()\n .reverse();\n } catch {\n return [];\n }\n }\n\n getIncidentEvents(incidentId: string): IncidentEvent[] {\n const logFile = path.join(this.baseDir, incidentId, \"events.jsonl\");\n if (!fs.existsSync(logFile)) return [];\n\n return fs\n .readFileSync(logFile, \"utf-8\")\n .trim()\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line) as IncidentEvent);\n }\n}\n","import type { IncidentEvent } from \"../types/index.js\";\nimport { IncidentLogger } from \"./logger.js\";\n\nexport interface MttrStats {\n totalIncidents: number;\n resolvedIncidents: number;\n averageMttrMs: number;\n byTier: Record<string, { count: number; averageMttrMs: number }>;\n byPattern: Record<string, { count: number; averageMttrMs: number }>;\n}\n\nexport function computeStatistics(logger: IncidentLogger): MttrStats {\n const incidents = logger.getIncidents();\n const stats: MttrStats = {\n totalIncidents: incidents.length,\n resolvedIncidents: 0,\n averageMttrMs: 0,\n byTier: {},\n byPattern: {},\n };\n\n const mttrs: number[] = [];\n\n for (const incidentId of incidents) {\n const events = logger.getIncidentEvents(incidentId);\n const mttr = computeIncidentMttr(events);\n\n if (mttr !== null) {\n stats.resolvedIncidents++;\n mttrs.push(mttr);\n\n const tier = findRecoveryTier(events);\n if (tier) {\n if (!stats.byTier[tier]) {\n stats.byTier[tier] = { count: 0, averageMttrMs: 0 };\n }\n stats.byTier[tier].count++;\n stats.byTier[tier].averageMttrMs += mttr;\n }\n\n const pattern = findPattern(events);\n if (pattern) {\n if (!stats.byPattern[pattern]) {\n stats.byPattern[pattern] = { count: 0, averageMttrMs: 0 };\n }\n stats.byPattern[pattern].count++;\n stats.byPattern[pattern].averageMttrMs += mttr;\n }\n }\n }\n\n if (mttrs.length > 0) {\n stats.averageMttrMs = mttrs.reduce((a, b) => a + b, 0) / mttrs.length;\n }\n\n for (const tier of Object.values(stats.byTier)) {\n if (tier.count > 0) tier.averageMttrMs /= tier.count;\n }\n for (const pattern of Object.values(stats.byPattern)) {\n if (pattern.count > 0) pattern.averageMttrMs /= pattern.count;\n }\n\n return stats;\n}\n\nfunction computeIncidentMttr(events: IncidentEvent[]): number | null {\n const start = events.find((e) => e.type === \"INCIDENT_START\");\n const end = events.find((e) => e.type === \"INCIDENT_RESOLVED\" || e.type === \"RECOVERY_SUCCESS\");\n\n if (!start || !end) return null;\n\n return new Date(end.timestamp).getTime() - new Date(start.timestamp).getTime();\n}\n\nfunction findRecoveryTier(events: IncidentEvent[]): string | null {\n const recovery = events.find(\n (e) => e.type === \"RECOVERY_SUCCESS\" || e.type === \"RECOVERY_ATTEMPT\",\n );\n return recovery ? String(recovery.data[\"level\"] ?? \"unknown\") : null;\n}\n\nfunction findPattern(events: IncidentEvent[]): string | null {\n const diagnosis = events.find((e) => e.type === \"DIAGNOSIS_MATCH\");\n return diagnosis ? String(diagnosis.data[\"pattern\"] ?? \"unknown\") : null;\n}\n","import type { AlertPayload, AlertProvider, AlertResult } from \"../types/index.js\";\n\nexport interface DispatchResult {\n sent: boolean;\n results: AlertResult[];\n allFailed: boolean;\n}\n\nexport class AlertDispatcher {\n private readonly providers: AlertProvider[] = [];\n private readonly retryBackoffMs: number[];\n private readonly retryAttempts: number;\n\n constructor(retryAttempts: number = 3, retryBackoffMs: number[] = [5000, 15000, 45000]) {\n this.retryAttempts = retryAttempts;\n this.retryBackoffMs = retryBackoffMs;\n }\n\n addProvider(provider: AlertProvider): void {\n this.providers.push(provider);\n }\n\n getProviders(): AlertProvider[] {\n return [...this.providers];\n }\n\n hasProviders(): boolean {\n return this.providers.length > 0;\n }\n\n async dispatch(alert: AlertPayload): Promise<DispatchResult> {\n if (this.providers.length === 0) {\n return { sent: false, results: [], allFailed: true };\n }\n\n const scrubbed = scrubSensitiveData(alert);\n const results: AlertResult[] = [];\n\n for (const provider of this.providers) {\n const result = await this.sendWithRetry(provider, scrubbed);\n results.push(result);\n }\n\n const anySuccess = results.some((r) => r.success);\n return { sent: anySuccess, results, allFailed: !anySuccess };\n }\n\n async testAll(): Promise<Map<string, boolean>> {\n const results = new Map<string, boolean>();\n for (const provider of this.providers) {\n try {\n const ok = await provider.test();\n results.set(provider.name, ok);\n } catch {\n results.set(provider.name, false);\n }\n }\n return results;\n }\n\n private async sendWithRetry(provider: AlertProvider, alert: AlertPayload): Promise<AlertResult> {\n let lastResult: AlertResult = {\n provider: provider.name,\n success: false,\n error: \"No attempts made\",\n durationMs: 0,\n };\n\n for (let attempt = 0; attempt <= this.retryAttempts; attempt++) {\n try {\n lastResult = await provider.send(alert);\n if (lastResult.success) return lastResult;\n } catch (err) {\n lastResult = {\n provider: provider.name,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n durationMs: 0,\n };\n }\n\n if (attempt < this.retryAttempts) {\n const delay = this.retryBackoffMs[attempt] ?? this.retryBackoffMs[this.retryBackoffMs.length - 1] ?? 5000;\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n\n return lastResult;\n }\n}\n\nexport function scrubSensitiveData(alert: AlertPayload): AlertPayload {\n return {\n ...alert,\n body: scrubString(alert.body),\n title: scrubString(alert.title),\n };\n}\n\nfunction scrubString(input: string): string {\n return input.replace(\n /(\"[^\"]*(?:key|secret|token|password|credential|auth)[^\"]*\"\\s*:\\s*)\"[^\"]*\"/gi,\n '$1\"[REDACTED]\"',\n );\n}","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as crypto from \"node:crypto\";\nimport type { BackupEntry, KnownGoodEntry } from \"../types/index.js\";\nimport type { AegisConfig } from \"../config/schema.js\";\nimport { expandHome } from \"../config/loader.js\";\n\nconst METADATA_FILE = \"metadata.json\";\n\ninterface BackupMetadata {\n chronological: BackupEntry[];\n knownGood: KnownGoodEntry[];\n}\n\nexport class BackupManager {\n private readonly basePath: string;\n private readonly maxChronological: number;\n private readonly maxKnownGood: number;\n private readonly knownGoodStabilityMs: number;\n private readonly configPath: string;\n\n constructor(config: AegisConfig) {\n this.basePath = expandHome(config.backup.basePath);\n this.maxChronological = config.backup.maxChronological;\n this.maxKnownGood = config.backup.maxKnownGood;\n this.knownGoodStabilityMs = config.backup.knownGoodStabilityMs;\n this.configPath = config.gateway.configPath;\n }\n\n init(): void {\n fs.mkdirSync(path.join(this.basePath, \"chronological\"), { recursive: true, mode: 0o700 });\n fs.mkdirSync(path.join(this.basePath, \"known-good\"), { recursive: true, mode: 0o700 });\n }\n\n backup(): BackupEntry {\n this.init();\n const content = fs.readFileSync(this.configPath, \"utf-8\");\n const checksum = sha256(content);\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const filename = `${timestamp}.json`;\n const backupPath = path.join(this.basePath, \"chronological\", filename);\n\n atomicWrite(backupPath, content);\n\n const entry: BackupEntry = { path: backupPath, timestamp: new Date().toISOString(), checksum };\n const meta = this.loadMetadata();\n meta.chronological.push(entry);\n\n while (meta.chronological.length > this.maxChronological) {\n const removed = meta.chronological.shift();\n if (removed) {\n try { fs.unlinkSync(removed.path); } catch { /* already gone */ }\n }\n }\n\n this.saveMetadata(meta);\n return entry;\n }\n\n restoreLatestKnownGood(): boolean {\n const meta = this.loadMetadata();\n const latest = meta.knownGood[meta.knownGood.length - 1];\n if (!latest) return false;\n return this.restoreFromEntry(latest);\n }\n\n restoreFromEntry(entry: BackupEntry): boolean {\n if (!fs.existsSync(entry.path)) return false;\n\n const content = fs.readFileSync(entry.path, \"utf-8\");\n const checksum = sha256(content);\n if (checksum !== entry.checksum) return false;\n\n atomicWrite(this.configPath, content);\n return true;\n }\n\n promoteToKnownGood(): KnownGoodEntry | null {\n if (!fs.existsSync(this.configPath)) return null;\n\n const content = fs.readFileSync(this.configPath, \"utf-8\");\n const checksum = sha256(content);\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const filename = `known-good-${timestamp}.json`;\n const knownGoodPath = path.join(this.basePath, \"known-good\", filename);\n\n atomicWrite(knownGoodPath, content);\n\n const entry: KnownGoodEntry = {\n path: knownGoodPath,\n timestamp: new Date().toISOString(),\n checksum,\n promotedAt: new Date().toISOString(),\n };\n\n const meta = this.loadMetadata();\n meta.knownGood.push(entry);\n\n while (meta.knownGood.length > this.maxKnownGood) {\n const removed = meta.knownGood.shift();\n if (removed) {\n try { fs.unlinkSync(removed.path); } catch { /* already gone */ }\n }\n }\n\n this.saveMetadata(meta);\n return entry;\n }\n\n getLatestKnownGood(): KnownGoodEntry | null {\n const meta = this.loadMetadata();\n return meta.knownGood[meta.knownGood.length - 1] ?? null;\n }\n\n getChronologicalBackups(): BackupEntry[] {\n return this.loadMetadata().chronological;\n }\n\n getKnownGoodEntries(): KnownGoodEntry[] {\n return this.loadMetadata().knownGood;\n }\n\n getKnownGoodStabilityMs(): number {\n return this.knownGoodStabilityMs;\n }\n\n private loadMetadata(): BackupMetadata {\n const metaPath = path.join(this.basePath, METADATA_FILE);\n try {\n const raw = fs.readFileSync(metaPath, \"utf-8\");\n return JSON.parse(raw) as BackupMetadata;\n } catch {\n return { chronological: [], knownGood: [] };\n }\n }\n\n private saveMetadata(meta: BackupMetadata): void {\n const metaPath = path.join(this.basePath, METADATA_FILE);\n atomicWrite(metaPath, JSON.stringify(meta, null, 2));\n }\n}\n\nexport function sha256(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nexport function atomicWrite(targetPath: string, content: string): void {\n const dir = path.dirname(targetPath);\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n const tmpPath = `${targetPath}.tmp.${process.pid}`;\n fs.writeFileSync(tmpPath, content, { mode: 0o600 });\n fs.renameSync(tmpPath, targetPath);\n}\n","export class CircuitBreaker {\n private failedCycles: number[] = [];\n private readonly maxCycles: number;\n private readonly windowMs: number;\n private tripped = false;\n\n constructor(maxCycles: number = 3, windowMs: number = 3600000) {\n this.maxCycles = maxCycles;\n this.windowMs = windowMs;\n }\n\n recordFailedCycle(): boolean {\n const now = Date.now();\n this.failedCycles.push(now);\n this.pruneOldCycles(now);\n\n if (this.failedCycles.length >= this.maxCycles) {\n this.tripped = true;\n }\n\n return this.tripped;\n }\n\n isTripped(): boolean {\n this.pruneOldCycles(Date.now());\n if (this.failedCycles.length < this.maxCycles) {\n this.tripped = false;\n }\n return this.tripped;\n }\n\n reset(): void {\n this.failedCycles = [];\n this.tripped = false;\n }\n\n getFailedCycleCount(): number {\n this.pruneOldCycles(Date.now());\n return this.failedCycles.length;\n }\n\n private pruneOldCycles(now: number): void {\n const cutoff = now - this.windowMs;\n this.failedCycles = this.failedCycles.filter((t) => t > cutoff);\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport * as fs from \"node:fs\";\nimport type { DiagnosisContext, HealthScore, RecoveryAction } from \"../types/index.js\";\nimport type { AegisConfig } from \"../config/schema.js\";\nimport { preflightValidation } from \"../config-guardian/guardian.js\";\nimport { DiagnosisEngine } from \"../diagnosis/engine.js\";\nimport { CircuitBreaker } from \"./circuit-breaker.js\";\nimport { BackupManager } from \"../backup/manager.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type RecoveryEvent =\n | { type: \"L1_ATTEMPT\"; attempt: number }\n | { type: \"L1_SUCCESS\" }\n | { type: \"L1_PREFLIGHT_FAILED\"; errors: string[] }\n | { type: \"L2_ATTEMPT\"; pattern: string }\n | { type: \"L2_SUCCESS\"; pattern: string }\n | { type: \"L2_FAILURE\"; pattern: string }\n | { type: \"L2_NO_MATCH\" }\n | { type: \"L4_ALERT\"; reason: string; actions: RecoveryAction[] }\n | { type: \"CIRCUIT_BREAKER_TRIPPED\" }\n | { type: \"FAST_PATH_L4\"; reason: string };\n\nexport class RecoveryOrchestrator extends EventEmitter {\n private readonly config: AegisConfig;\n private readonly diagnosisEngine: DiagnosisEngine;\n private readonly circuitBreaker: CircuitBreaker;\n private readonly backupManager: BackupManager;\n private recovering = false;\n\n constructor(\n config: AegisConfig,\n diagnosisEngine: DiagnosisEngine,\n backupManager: BackupManager,\n ) {\n super();\n this.config = config;\n this.diagnosisEngine = diagnosisEngine;\n this.backupManager = backupManager;\n this.circuitBreaker = new CircuitBreaker(\n config.recovery.circuitBreakerMaxCycles,\n config.recovery.circuitBreakerWindowMs,\n );\n }\n\n isRecovering(): boolean {\n return this.recovering;\n }\n\n getCircuitBreaker(): CircuitBreaker {\n return this.circuitBreaker;\n }\n\n async recover(_healthScore: HealthScore): Promise<RecoveryAction[]> {\n if (this.recovering) return [];\n this.recovering = true;\n\n try {\n if (this.circuitBreaker.isTripped()) {\n this.emitEvent({ type: \"CIRCUIT_BREAKER_TRIPPED\" });\n return [];\n }\n\n const actions: RecoveryAction[] = [];\n\n const l1Result = await this.attemptL1();\n actions.push(...l1Result.actions);\n if (l1Result.success) return actions;\n\n const l2Result = await this.attemptL2();\n actions.push(...l2Result.actions);\n\n if (l2Result.success) {\n const retryL1 = await this.attemptL1();\n actions.push(...retryL1.actions);\n if (retryL1.success) return actions;\n }\n\n if (!l2Result.success && l2Result.noMatch) {\n this.emitEvent({ type: \"FAST_PATH_L4\", reason: \"L1 preflight failed and L2 has no matching pattern\" });\n }\n\n this.circuitBreaker.recordFailedCycle();\n if (this.circuitBreaker.isTripped()) {\n this.emitEvent({ type: \"CIRCUIT_BREAKER_TRIPPED\" });\n }\n\n const reason = l2Result.noMatch\n ? \"No matching failure pattern — cannot auto-repair\"\n : \"Recovery exhausted — L1+L2 failed\";\n this.emitEvent({ type: \"L4_ALERT\", reason, actions });\n\n return actions;\n } finally {\n this.recovering = false;\n }\n }\n\n private async attemptL1(): Promise<{ success: boolean; actions: RecoveryAction[] }> {\n const actions: RecoveryAction[] = [];\n const maxAttempts = this.config.recovery.l1MaxAttempts;\n const baseMs = this.config.recovery.l1BackoffBaseMs;\n const multiplier = this.config.recovery.l1BackoffMultiplier;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n this.emitEvent({ type: \"L1_ATTEMPT\", attempt });\n\n const preflight = preflightValidation(this.config.gateway.configPath);\n if (!preflight.valid) {\n this.emitEvent({ type: \"L1_PREFLIGHT_FAILED\", errors: preflight.errors });\n actions.push({\n level: \"L1\",\n action: \"preflight-failed\",\n result: \"skipped\",\n durationMs: 0,\n });\n return { success: false, actions };\n }\n\n const start = Date.now();\n try {\n await execFileAsync(\"openclaw\", [\"gateway\", \"restart\"], { timeout: 30000 });\n actions.push({ level: \"L1\", action: \"restart\", result: \"success\", durationMs: Date.now() - start });\n this.emitEvent({ type: \"L1_SUCCESS\" });\n return { success: true, actions };\n } catch {\n actions.push({ level: \"L1\", action: \"restart\", result: \"failure\", durationMs: Date.now() - start });\n }\n\n if (attempt < maxAttempts) {\n const delay = baseMs * Math.pow(multiplier, attempt - 1);\n await sleep(delay);\n }\n }\n\n return { success: false, actions };\n }\n\n private async attemptL2(): Promise<{ success: boolean; actions: RecoveryAction[]; noMatch: boolean }> {\n const actions: RecoveryAction[] = [];\n\n const context: DiagnosisContext = {\n configPath: this.config.gateway.configPath,\n pidFile: this.config.gateway.pidFile,\n gatewayPort: this.config.gateway.port,\n logPath: this.config.gateway.logPath,\n knownGoodPath: this.backupManager.getLatestKnownGood()?.path,\n currentConfig: this.readCurrentConfig(),\n };\n\n for (let attempt = 0; attempt < this.config.recovery.l2MaxAttempts; attempt++) {\n const result = await this.diagnosisEngine.diagnose(context);\n\n if (!result) {\n this.emitEvent({ type: \"L2_NO_MATCH\" });\n return { success: false, actions, noMatch: true };\n }\n\n this.emitEvent({ type: \"L2_ATTEMPT\", pattern: result.pattern.name });\n actions.push(result.action);\n\n if (result.action.result === \"success\") {\n this.emitEvent({ type: \"L2_SUCCESS\", pattern: result.pattern.name });\n return { success: true, actions, noMatch: false };\n }\n\n this.emitEvent({ type: \"L2_FAILURE\", pattern: result.pattern.name });\n\n if (attempt < this.config.recovery.l2MaxAttempts - 1) {\n await sleep(this.config.recovery.l2CooldownMs);\n }\n }\n\n return { success: false, actions, noMatch: false };\n }\n\n private readCurrentConfig(): Record<string, unknown> | null {\n try {\n const raw = fs.readFileSync(this.config.gateway.configPath, \"utf-8\");\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n }\n\n private emitEvent(event: RecoveryEvent): void {\n this.emit(\"recovery\", event);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import * as fs from \"node:fs\";\nimport type { AegisConfig } from \"../config/schema.js\";\nimport { BackupManager } from \"../backup/manager.js\";\nimport { CRITICAL_CONFIG_KEYS } from \"../types/index.js\";\n\nexport interface PreflightResult {\n valid: boolean;\n errors: string[];\n}\n\nexport interface ConfigDiff {\n added: string[];\n removed: string[];\n modified: string[];\n}\n\nexport function preflightValidation(configPath: string): PreflightResult {\n const errors: string[] = [];\n\n if (!fs.existsSync(configPath)) {\n return { valid: false, errors: [\"Gateway config file not found\"] };\n }\n\n let raw: string;\n try {\n raw = fs.readFileSync(configPath, \"utf-8\");\n } catch (err) {\n return { valid: false, errors: [`Cannot read config: ${err instanceof Error ? err.message : String(err)}`] };\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return { valid: false, errors: [\"Config is not valid JSON\"] };\n }\n\n if (!(\"port\" in parsed)) {\n errors.push(\"Missing required key: port\");\n }\n\n const poisonKeys = [\"autoAck\", \"autoAckMessage\"];\n for (const key of poisonKeys) {\n if (key in parsed) {\n errors.push(`Poison key detected: ${key}`);\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\nexport function diffConfigs(\n oldConfig: Record<string, unknown>,\n newConfig: Record<string, unknown>,\n): ConfigDiff {\n const oldKeys = new Set(Object.keys(oldConfig));\n const newKeys = new Set(Object.keys(newConfig));\n\n const added: string[] = [];\n const removed: string[] = [];\n const modified: string[] = [];\n\n for (const key of newKeys) {\n if (!oldKeys.has(key)) {\n added.push(key);\n } else if (JSON.stringify(oldConfig[key]) !== JSON.stringify(newConfig[key])) {\n modified.push(key);\n }\n }\n\n for (const key of oldKeys) {\n if (!newKeys.has(key)) {\n removed.push(key);\n }\n }\n\n return { added, removed, modified };\n}\n\nexport function isCriticalChange(diff: ConfigDiff): boolean {\n const criticalSet = new Set<string>(CRITICAL_CONFIG_KEYS);\n\n for (const key of [...diff.added, ...diff.removed, ...diff.modified]) {\n if (criticalSet.has(key)) return true;\n }\n\n if (diff.added.length > 0 || diff.removed.length > 0) return true;\n\n return false;\n}\n\nexport function startupConfigValidation(config: AegisConfig, backupManager: BackupManager): boolean {\n const preflight = preflightValidation(config.gateway.configPath);\n if (preflight.valid) return true;\n\n const knownGood = backupManager.getLatestKnownGood();\n if (!knownGood) return false;\n\n return backupManager.restoreFromEntry(knownGood);\n}\n","import { EventEmitter } from \"node:events\";\nimport * as fs from \"node:fs\";\nimport type { AegisConfig } from \"../config/schema.js\";\nimport { BackupManager } from \"../backup/manager.js\";\nimport { diffConfigs, isCriticalChange, preflightValidation } from \"./guardian.js\";\n\nexport type SwitchState = \"idle\" | \"countdown\" | \"committed\" | \"rolled-back\";\n\nexport class DeadManSwitch extends EventEmitter {\n private state: SwitchState = \"idle\";\n private countdownTimer: NodeJS.Timeout | null = null;\n private readonly countdownMs: number;\n private readonly configPath: string;\n private readonly backupManager: BackupManager;\n private lastKnownConfig: Record<string, unknown> | null = null;\n\n constructor(config: AegisConfig, backupManager: BackupManager) {\n super();\n this.countdownMs = config.deadManSwitch.countdownMs;\n this.configPath = config.gateway.configPath;\n this.backupManager = backupManager;\n this.captureCurrentConfig();\n }\n\n getState(): SwitchState {\n return this.state;\n }\n\n onConfigChange(): void {\n const currentConfig = this.readConfig();\n if (!currentConfig || !this.lastKnownConfig) {\n this.startCountdown();\n return;\n }\n\n const diff = diffConfigs(this.lastKnownConfig, currentConfig);\n if (!isCriticalChange(diff)) {\n this.lastKnownConfig = currentConfig;\n this.emit(\"non-critical-change\", diff);\n return;\n }\n\n this.backupManager.backup();\n this.startCountdown();\n }\n\n commit(): void {\n this.clearCountdown();\n this.captureCurrentConfig();\n this.state = \"committed\";\n this.emit(\"committed\");\n this.state = \"idle\";\n }\n\n rollback(): boolean {\n this.clearCountdown();\n const restored = this.backupManager.restoreLatestKnownGood();\n if (restored) {\n this.captureCurrentConfig();\n this.state = \"rolled-back\";\n this.emit(\"rolled-back\");\n this.state = \"idle\";\n }\n return restored;\n }\n\n onHealthy(): void {\n if (this.state === \"countdown\") {\n this.commit();\n }\n }\n\n onUnhealthy(): void {\n if (this.state === \"countdown\") {\n this.rollback();\n }\n }\n\n destroy(): void {\n this.clearCountdown();\n }\n\n private startCountdown(): void {\n this.clearCountdown();\n this.state = \"countdown\";\n this.emit(\"countdown-started\", this.countdownMs);\n\n this.countdownTimer = setTimeout(() => {\n const preflight = preflightValidation(this.configPath);\n if (preflight.valid) {\n this.commit();\n } else {\n this.emit(\"countdown-expired-invalid\", preflight.errors);\n this.rollback();\n }\n }, this.countdownMs);\n }\n\n private clearCountdown(): void {\n if (this.countdownTimer) {\n clearTimeout(this.countdownTimer);\n this.countdownTimer = null;\n }\n }\n\n private captureCurrentConfig(): void {\n this.lastKnownConfig = this.readConfig();\n }\n\n private readConfig(): Record<string, unknown> | null {\n try {\n const raw = fs.readFileSync(this.configPath, \"utf-8\");\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n }\n}\n","import * as fs from \"node:fs\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { DiagnosisContext, FailurePattern, RecoveryAction } from \"../types/index.js\";\nimport { BackupManager } from \"../backup/manager.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport class DiagnosisEngine {\n private readonly patterns: FailurePattern[];\n\n constructor(backupManager: BackupManager) {\n this.patterns = createPatterns(backupManager);\n }\n\n async diagnose(context: DiagnosisContext): Promise<{ pattern: FailurePattern; action: RecoveryAction } | null> {\n for (const pattern of this.patterns) {\n try {\n const matched = await pattern.detect(context);\n if (matched) {\n const action = await pattern.fix(context);\n return { pattern, action };\n }\n } catch {\n // Pattern detection failed — skip to next\n }\n }\n return null;\n }\n\n getPatterns(): FailurePattern[] {\n return [...this.patterns];\n }\n}\n\nfunction createPatterns(backupManager: BackupManager): FailurePattern[] {\n return [\n {\n id: 1,\n name: \"runtime-config-injection\",\n async detect(ctx: DiagnosisContext): Promise<boolean> {\n if (!ctx.currentConfig) return false;\n const poisonKeys = [\"autoAck\", \"autoAckMessage\", \"groupAllowFrom\", \"allowlist\"];\n return poisonKeys.some((key) => key in ctx.currentConfig!);\n },\n async fix(_ctx: DiagnosisContext): Promise<RecoveryAction> {\n const start = Date.now();\n const restored = backupManager.restoreLatestKnownGood();\n return {\n level: \"L2\",\n action: \"restore-known-good-config\",\n result: restored ? \"success\" : \"failure\",\n durationMs: Date.now() - start,\n };\n },\n },\n {\n id: 2,\n name: \"stale-pid-file\",\n async detect(ctx: DiagnosisContext): Promise<boolean> {\n if (!fs.existsSync(ctx.pidFile)) return false;\n const pidStr = fs.readFileSync(ctx.pidFile, \"utf-8\").trim();\n const pid = parseInt(pidStr, 10);\n if (isNaN(pid) || pid <= 0) return true;\n try {\n process.kill(pid, 0);\n return false;\n } catch {\n return true;\n }\n },\n async fix(ctx: DiagnosisContext): Promise<RecoveryAction> {\n const start = Date.now();\n try {\n fs.unlinkSync(ctx.pidFile);\n return { level: \"L2\", action: \"delete-stale-pid\", result: \"success\", durationMs: Date.now() - start };\n } catch {\n return { level: \"L2\", action: \"delete-stale-pid\", result: \"failure\", durationMs: Date.now() - start };\n }\n },\n },\n {\n id: 3,\n name: \"port-conflict\",\n async detect(ctx: DiagnosisContext): Promise<boolean> {\n try {\n const { stdout } = await execFileAsync(\"lsof\", [\"-i\", `:${ctx.gatewayPort}`, \"-t\"]);\n const pids = stdout.trim().split(\"\\n\").filter(Boolean);\n if (pids.length === 0) return false;\n\n if (fs.existsSync(ctx.pidFile)) {\n const gatewayPid = fs.readFileSync(ctx.pidFile, \"utf-8\").trim();\n return !pids.includes(gatewayPid);\n }\n return pids.length > 0;\n } catch {\n return false;\n }\n },\n async fix(ctx: DiagnosisContext): Promise<RecoveryAction> {\n const start = Date.now();\n try {\n const { stdout } = await execFileAsync(\"lsof\", [\"-i\", `:${ctx.gatewayPort}`, \"-t\"]);\n const pids = stdout.trim().split(\"\\n\").filter(Boolean);\n return {\n level: \"L2\",\n action: `port-conflict-detected-pids:${pids.join(\",\")}`,\n result: \"skipped\",\n durationMs: Date.now() - start,\n };\n } catch {\n return { level: \"L2\", action: \"port-conflict-check\", result: \"failure\", durationMs: Date.now() - start };\n }\n },\n },\n {\n id: 4,\n name: \"file-permission-error\",\n async detect(ctx: DiagnosisContext): Promise<boolean> {\n try {\n const stat = fs.statSync(ctx.configPath);\n const mode = stat.mode & 0o777;\n return mode !== 0o600 && mode !== 0o644;\n } catch {\n return false;\n }\n },\n async fix(ctx: DiagnosisContext): Promise<RecoveryAction> {\n const start = Date.now();\n try {\n fs.chmodSync(ctx.configPath, 0o600);\n return { level: \"L2\", action: \"fix-permissions\", result: \"success\", durationMs: Date.now() - start };\n } catch {\n return { level: \"L2\", action: \"fix-permissions\", result: \"failure\", durationMs: Date.now() - start };\n }\n },\n },\n {\n id: 5,\n name: \"config-corrupted\",\n async detect(ctx: DiagnosisContext): Promise<boolean> {\n if (!fs.existsSync(ctx.configPath)) return true;\n try {\n const raw = fs.readFileSync(ctx.configPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n return !(\"port\" in parsed);\n } catch {\n return true;\n }\n },\n async fix(_ctx: DiagnosisContext): Promise<RecoveryAction> {\n const start = Date.now();\n const restored = backupManager.restoreLatestKnownGood();\n return {\n level: \"L2\",\n action: \"restore-known-good-config\",\n result: restored ? \"success\" : \"failure\",\n durationMs: Date.now() - start,\n };\n },\n },\n {\n id: 6,\n name: \"oom-kill\",\n async detect(_ctx: DiagnosisContext): Promise<boolean> {\n try {\n const { stdout } = await execFileAsync(\"dmesg\", [\"--time-format\", \"reltime\"], { timeout: 5000 });\n return /oom_kill_process|Out of memory/.test(stdout);\n } catch {\n return false;\n }\n },\n async fix(): Promise<RecoveryAction> {\n return { level: \"L4\", action: \"oom-kill-detected-escalate\", result: \"skipped\", durationMs: 0 };\n },\n },\n ];\n}\n","import * as fs from \"node:fs\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { PROTECTED_CONFIG_KEYS } from \"../types/index.js\";\nimport { atomicWrite, sha256 } from \"../backup/manager.js\";\nimport { diffConfigs } from \"../config-guardian/guardian.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface DoctorResult {\n success: boolean;\n diff: { added: string[]; removed: string[]; modified: string[] } | null;\n rejected: boolean;\n rejectedReason?: string;\n output: string;\n}\n\nexport async function safeDoctorFix(configPath: string): Promise<DoctorResult> {\n if (!fs.existsSync(configPath)) {\n return { success: false, diff: null, rejected: false, output: \"Config file not found\" };\n }\n\n const beforeContent = fs.readFileSync(configPath, \"utf-8\");\n const beforeChecksum = sha256(beforeContent);\n let beforeConfig: Record<string, unknown>;\n try {\n beforeConfig = JSON.parse(beforeContent) as Record<string, unknown>;\n } catch {\n return { success: false, diff: null, rejected: false, output: \"Config is not valid JSON before doctor\" };\n }\n\n const tmpBackup = `${configPath}.aegis-doctor-backup.${process.pid}`;\n atomicWrite(tmpBackup, beforeContent);\n\n let output: string;\n try {\n const result = await execFileAsync(\"openclaw\", [\"doctor\", \"--fix\"], { timeout: 30000 });\n output = result.stdout + result.stderr;\n } catch (err) {\n try { fs.unlinkSync(tmpBackup); } catch { /* cleanup */ }\n const msg = err instanceof Error ? err.message : String(err);\n return { success: false, diff: null, rejected: false, output: `doctor --fix failed: ${msg}` };\n }\n\n const afterContent = fs.readFileSync(configPath, \"utf-8\");\n const afterChecksum = sha256(afterContent);\n\n if (afterChecksum === beforeChecksum) {\n try { fs.unlinkSync(tmpBackup); } catch { /* cleanup */ }\n return { success: true, diff: null, rejected: false, output };\n }\n\n let afterConfig: Record<string, unknown>;\n try {\n afterConfig = JSON.parse(afterContent) as Record<string, unknown>;\n } catch {\n atomicWrite(configPath, beforeContent);\n try { fs.unlinkSync(tmpBackup); } catch { /* cleanup */ }\n return { success: false, diff: null, rejected: true, rejectedReason: \"doctor produced invalid JSON\", output };\n }\n\n const diff = diffConfigs(beforeConfig, afterConfig);\n const protectedSet = new Set<string>(PROTECTED_CONFIG_KEYS);\n const protectedRemovals = diff.removed.filter((key) => protectedSet.has(key));\n\n if (protectedRemovals.length > 0) {\n atomicWrite(configPath, beforeContent);\n try { fs.unlinkSync(tmpBackup); } catch { /* cleanup */ }\n return {\n success: false,\n diff,\n rejected: true,\n rejectedReason: `doctor removed protected keys: ${protectedRemovals.join(\", \")}`,\n output,\n };\n }\n\n try { fs.unlinkSync(tmpBackup); } catch { /* cleanup */ }\n return { success: true, diff, rejected: false, output };\n}\n"],"mappings":"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","names":["TOML","fs","fs","path","fs","import_node_child_process","net","fs","path","fs","import_node_child_process","import_node_util","execFileAsync","fs","fs","import_node_child_process","import_node_util","path","execFileAsync","fs","WebSocket","import_node_events","fs","path","fs","path","crypto","import_node_events","import_node_child_process","import_node_util","fs","fs","execFileAsync","import_node_events","fs","fs","import_node_child_process","import_node_util","execFileAsync","fs","import_node_child_process","import_node_util","execFileAsync"]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "openclaw-aegis",
3
+ "version": "1.0.0",
4
+ "description": "Self-healing sidecar daemon for the OpenClaw gateway",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "aegis": "dist/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "LICENSE",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "dev": "tsup --watch",
18
+ "test": "vitest run",
19
+ "test:watch": "vitest",
20
+ "test:coverage": "vitest run --coverage",
21
+ "lint": "eslint src/ tests/",
22
+ "format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts'",
23
+ "format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts'",
24
+ "typecheck": "tsc --noEmit",
25
+ "preflight": "node dist/cli/index.js preflight"
26
+ },
27
+ "keywords": [
28
+ "openclaw",
29
+ "self-healing",
30
+ "watchdog",
31
+ "gateway",
32
+ "monitoring",
33
+ "recovery"
34
+ ],
35
+ "license": "MIT",
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "dependencies": {
40
+ "@iarna/toml": "^2.2.5",
41
+ "commander": "^12.1.0",
42
+ "ws": "^8.18.0",
43
+ "zod": "^3.23.8"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^20.14.0",
47
+ "@types/ws": "^8.5.10",
48
+ "@typescript-eslint/eslint-plugin": "^7.13.0",
49
+ "@typescript-eslint/parser": "^7.13.0",
50
+ "@vitest/coverage-v8": "^1.6.0",
51
+ "eslint": "^8.57.0",
52
+ "prettier": "^3.3.0",
53
+ "tsup": "^8.1.0",
54
+ "typescript": "^5.5.0",
55
+ "vitest": "^1.6.0"
56
+ }
57
+ }