/** * Leg cadence: every scheduled leg declares how often it runs and BEATS when * it does; an independent watchdog pages the owner when a leg goes silent. * * Placement (review D2): the watchdog lives on its OWN timer, outside the * trigger loop - a watchdog inside the thing it watches dies with it (the * trigger author was dead for two days before v0.29.2 named why). The * trigger loop itself registers as a watched leg; whole-daemon death is * launchd KeepAlive's job. * * State (review #11): most legs are bare setIntervals with no durable * last-run, so each leg's tick calls `beat()` - one line, watchdog-owned * table, no log-projection reads (state questions get live reads). * * Paging (review #12): 2x declared cadence, quiet hours honored (the * heartbeat's 23:00-08:00 window - without it a 30-minute leg pages the * owner at midnight, nightly, forever), duplicate-suppressed across * restarts, one recovery notice. An alarm, never enforcement. */ import type { SQLiteDatabase } from '../sqlite.js'; export interface LegPageEvent { name: string; declaredCadenceMs: number; silentForMs: number; } export interface LegCadenceOptions { now?: () => number; /** Local hour provider - injectable for tests. */ hourOfDay?: () => number; quietStartHour?: number; quietEndHour?: number; } export declare class LegCadence { private readonly db; private readonly legs; private readonly now; private readonly hourOfDay; private readonly quietStart; private readonly quietEnd; private readonly stmtBeat; private readonly stmtRow; private readonly stmtSetPaged; constructor(db: SQLiteDatabase, options?: LegCadenceOptions); /** * Declare a leg. BOOT COUNTS AS A BEAT, always: seeding only on first * declaration meant a restart after downtime paged every leg for the * outage the daemon just recovered from (review) - the watchdog watches * the running daemon's legs, not the graveyard shift. */ declare(name: string, declaredCadenceMs: number): void; /** One line per leg tick. Undeclared beats are recorded, not errors. */ beat(name: string): void; private isQuietHour; /** * One watchdog pass. Returns what to SAY - the caller owns delivery. * Overdue = silent past 2x declared cadence. A page is recorded so it * fires once per silence (persisted - restarts do not re-page); recovery * clears the record and reports once. */ check(): { pages: LegPageEvent[]; recoveries: string[]; }; private checkInto; } /** Gateway wiring registers the actual send; the watchdog only composes text. */ export declare function setLegPageNotifier(notifier: ((message: string) => Promise) | null): void; export declare function getLegPageNotifier(): ((message: string) => Promise) | null; /** Boot-owned singleton so any leg can beat with one line, no plumbing. */ export declare function initLegCadence(db: SQLiteDatabase, options?: LegCadenceOptions): LegCadence; export declare function getLegCadence(): LegCadence | null; //# sourceMappingURL=leg-cadence.d.ts.map