import { type Stats } from "node:fs"; import { type FileHandle } from "node:fs/promises"; import type { LaunchdPaths } from "./launchd.js"; export declare const LAUNCHD_LOG_MAX_BYTES: number; export declare const LAUNCHD_LOG_ROTATION_COUNT = 3; export declare const LAUNCHD_LOG_MONITOR_INTERVAL_SECONDS: number; export interface LaunchdLogPolicy { readonly maxBytes: number; readonly rotationCount: number; } export declare const DEFAULT_LAUNCHD_LOG_POLICY: LaunchdLogPolicy; /** Source-audited callers which may repair the shared directory chain. */ export declare const SHARED_LAUNCHD_LOG_MUTATION_CALLERS: readonly ["beginLaunchdLogMaintenanceIntent", "replaceMaintenanceIntentPhase", "clearLaunchdLogMaintenanceIntent", "rotateStoppedLaunchdLogs"]; export type LaunchdLogFileState = "missing" | "ok" | "repairable" | "unsafe" | "unreadable"; export interface LaunchdLogFileInspection { readonly generation: number; readonly state: LaunchdLogFileState; readonly bytes: number; readonly issue?: string; } export interface LaunchdLogStreamInspection { readonly activeBytes: number; readonly retainedBytes: number; readonly totalBytes: number; /** False when any path could not be inspected safely; numeric totals are then incomplete. */ readonly byteAccountingComplete: boolean; readonly files: readonly LaunchdLogFileInspection[]; } export interface LaunchdLogInspection { readonly stdout: LaunchdLogStreamInspection; readonly stderr: LaunchdLogStreamInspection; readonly present: boolean; /** True only when every present path is safe for stopped-writer maintenance. */ readonly canMaintain: boolean; /** Oversized files or repairable owner-only permissions require a maintenance pass. */ readonly needsMaintenance: boolean; /** Safe per-agent file reasons which alone may wake this agent's helper. */ readonly perAgentFileReasons: readonly string[]; /** Shared directory repair is owned by scheduled maintenance, never a worker wake. */ readonly sharedDirectoryNeedsMaintenance: boolean; /** A durable journal proves a stopped-writer rotation began and must resume. */ readonly pendingTransaction: boolean; /** A lifecycle marker exists; its authenticated phase decides whether rotation or restore recovery is safe. */ readonly pendingMaintenance: boolean; /** Incomplete next/stage artifacts are helper recovery state, never a worker wake. */ readonly pendingPreparation: boolean; readonly issues: readonly string[]; } export interface LaunchdLogMaintenanceIntent { readonly version: 1; readonly phase: "stopping" | "stopped" | "restoring"; readonly label: string; readonly plistFingerprint: string; } export interface LaunchdLogRotationResult { readonly changed: boolean; readonly replacedFiles: number; } export interface LaunchdLogDependencies { readonly lstat: (path: string) => Promise; readonly realpath: (path: string) => Promise; readonly open: (path: string, flags: number, mode?: number) => Promise; readonly rename: (from: string, to: string) => Promise; readonly rm: (path: string) => Promise; readonly currentUid: () => number | undefined; readonly syncHandle: (handle: FileHandle) => Promise; readonly readTail: (handle: FileHandle, size: number, maxBytes: number) => Promise; /** Deterministic adversarial seam immediately before a destination identity check. */ readonly beforeCommit?: (path: string) => Promise; } export declare function defaultLaunchdLogDependencies(): LaunchdLogDependencies; /** * Derive the same per-config launchd paths as the background controller without * following a final-component symlink. Doctor and the private maintenance * command use this read-only helper; neither accepts a caller-supplied log path. */ export declare function launchdLogPathsForConfig(configPath: string, home?: string): Promise; /** Read and authenticate the durable lifecycle intent without changing it. */ export declare function readLaunchdLogMaintenanceIntent(paths: Pick, deps?: LaunchdLogDependencies): Promise; /** Publish pre-stop intent atomically before bootout; an unproven unloaded phase fails closed. */ export declare function beginLaunchdLogMaintenanceIntent(paths: Pick, intent: LaunchdLogMaintenanceIntent, deps?: LaunchdLogDependencies): Promise; /** Durably record that launchd is unloaded and every writer PID observed by this maintainer is dead. */ export declare function markLaunchdLogMaintenanceStopped(paths: Pick, expected: LaunchdLogMaintenanceIntent, deps?: LaunchdLogDependencies): Promise; /** Invalidate stopped-writer proof before bootstrap can create a replacement writer. */ export declare function markLaunchdLogMaintenanceRestoring(paths: Pick, expected: LaunchdLogMaintenanceIntent, deps?: LaunchdLogDependencies): Promise; /** Invalidate old stopped-writer proof before booting out any newly loaded writer. */ export declare function markLaunchdLogMaintenanceStopping(paths: Pick, expected: LaunchdLogMaintenanceIntent, deps?: LaunchdLogDependencies): Promise; /** Remove only the exact authenticated intent after recovery or explicit stop. */ export declare function clearLaunchdLogMaintenanceIntent(paths: Pick, expected?: LaunchdLogMaintenanceIntent, deps?: LaunchdLogDependencies): Promise; /** Read only: opens and stats metadata but never chmods, creates, or reads bytes. */ export declare function inspectLaunchdLogs(paths: Pick, policy?: LaunchdLogPolicy, deps?: LaunchdLogDependencies): Promise; /** * Rotate only after the caller has proven every possible writer dead. All * source bytes are read through validated handles, all replacements are capped, * fsynced owner-only temporaries, and each destination identity is rechecked * immediately before its atomic replacement. */ export declare function rotateStoppedLaunchdLogs(paths: Pick, policy?: LaunchdLogPolicy, deps?: LaunchdLogDependencies): Promise; //# sourceMappingURL=launchd-logs.d.ts.map