import { CliExitCode } from "../core/exit-codes.js"; import type { ScheduledRunRecord, ScheduledSourceOutcome, StoredSourceState } from "../core/state-store.js"; /** * What a scheduled collection runs against, and how to tell when an * installed job has drifted from it. * * A scheduler starts the job with none of the creating shell's environment. * A plist written from a shell with `VANA_HOME` set once took its log path * from that home while the job itself ran against the default ~/.vana, so it * collected into one state and logged into another (a /tmp test home the OS * wiped), and every failing night went unseen. The job therefore carries the * selection env it was created with, and its log always sits inside the home * it runs against. */ /** The job id launchd knows the scheduled collection by. */ export declare const LAUNCHD_LABEL = "com.vana.collect"; /** Marks the cron line as ours, so add and remove find it again. */ export declare const CRONTAB_MARKER = "# vana-scheduled-collection"; /** Set on the scheduled job so `collect --all` records its outcome. */ export declare const SCHEDULED_RUN_ENV = "VANA_SCHEDULED_RUN"; /** * Env that decides which state, network and server a run uses, copied from * the creating shell into the job. Secrets (VANA_PS_TOKEN, * VANA_SESSION_TOKEN, VANA_PRIVATE_KEY) are deliberately absent: a plist and * a crontab are readable files, and the job reads its credentials from the * state it is pinned to. */ export declare const SCHEDULE_PINNED_ENV_KEYS: readonly ["VANA_NETWORK", "VANA_ENV", "VANA_ACCOUNT_URL", "VANA_ACCOUNT_CLIENT_ID", "VANA_OAUTH_CLIENT_ID", "VANA_PERSONAL_SERVER_URL", "VANA_PS_URL"]; /** The state a scheduled job runs against, and where it logs. */ export interface ScheduleTarget { /** Absolute CLI home the job reads and writes. */ home: string; /** Absolute log path, always inside `home`. */ logPath: string; /** Env the job is started with; always includes VANA_HOME. */ env: Record; } /** The CLI home an env selects, as `getVanaHome` would resolve it. */ export declare function vanaHomeForEnv(env: Record, homeDir?: string): string; /** The log a scheduled job writes for a given CLI home. */ export declare function scheduleLogPathFor(home: string): string; /** * The target for a job created from `env`. * * @param network - an explicit `--network`, which wins over VANA_NETWORK. */ export declare function resolveScheduleTarget(env: Record, network?: string, homeDir?: string): ScheduleTarget; /** The arguments every scheduled job passes after the program. */ export declare const SCHEDULED_COLLECT_ARGS: readonly ["collect", "--all", "--quiet", "--no-input"]; export declare function generateLaunchdPlist(vanaCommand: string[], intervalSeconds: number, target: ScheduleTarget): string; /** What an installed job actually does, read back from its definition. */ export interface InstalledSchedule { intervalSeconds: number | null; logPath: string | null; /** Env the job is started with; empty for jobs written before pinning. */ env: Record; } /** Read the parts of a launchd plist that decide where the job runs. */ export declare function parseLaunchdPlist(content: string): InstalledSchedule; /** * A crontab line for the job. cron, like launchd, starts the command with * almost no env, so the pinned env goes in front of the command itself. */ export declare function generateCrontabEntry(vanaCommand: string[], intervalHours: number, target: ScheduleTarget): string; /** Read a crontab line back the way {@link parseLaunchdPlist} reads a plist. */ export declare function parseCrontabEntry(line: string): InstalledSchedule; /** One way an installed job no longer matches what `schedule add` writes. */ export type ScheduleDrift = { kind: "log_outside_home"; logPath: string | null; home: string; } | { kind: "home_not_pinned"; home: string; } | { kind: "other_home"; home: string; currentHome: string; }; /** * Compare an installed job with the state of the shell asking about it. * * `log_outside_home` and `home_not_pinned` mean the job itself is outdated * and `vana schedule add` repairs it. `other_home` only says the job serves * a different state than this shell; running add here would move it. */ export declare function diagnoseSchedule(installed: InstalledSchedule, currentHome: string, homeDir?: string): { jobHome: string; drift: ScheduleDrift[]; }; /** * The `vana status` line for the last scheduled run: one short clause when * it went fine, the failure count and the log when it did not. */ export declare function describeScheduledRun(record: ScheduledRunRecord, formatTime: (iso: string) => string, formatPath?: (filePath: string) => string): { text: string; failed: boolean; }; /** One source's result in a `collect --all` run. */ export interface CollectAllSourceResult { source: string; outcome: ScheduledSourceOutcome; error?: string; } /** * How a source collected by `collect --all` ended, read from the state its * run left behind. A run whose sync failed still exits 0 from `runConnect` * (the data is safe locally), which is how a week of 401s went unreported. */ export declare function classifyCollectedSource(source: string, exitCode: number, stored: StoredSourceState | undefined): CollectAllSourceResult; /** * The exit code for a whole `collect --all`: OK only when every source it * touched collected and synced. When the only problem is sync pending because * no usable Personal Server answered, that is * {@link CliExitCode.SERVER_UNAVAILABLE}; anything else is * {@link CliExitCode.FAILURE}. */ export declare function collectAllExitCode(results: readonly CollectAllSourceResult[]): CliExitCode; /** Lines for stderr when a `collect --all` did not fully succeed. */ export declare function describeCollectAllFailures(results: readonly CollectAllSourceResult[]): string[]; //# sourceMappingURL=schedule.d.ts.map