/** * checkin/service.ts * * The proactive check-in service: it reads the check-in config, gates on * enabled + quiet hours, assembles the briefing, asks the judge whether to * contact the user, delivers through the channel deliverer when the judgment * says yes, and writes a receipt for EVERY run, the loop that makes the * platform able to reach out first, accountably. * * It rides the existing automation scheduler: syncScheduledJob keeps a single * `kind: 'checkin'` automation job in step with the config, and attach() wires * the manager's check-in evaluator to this.evaluate, so when the scheduler * fires the job, this loop runs (checkin-execution.ts records the run). */ import type { AutomationManager } from '../automation/index.js'; import type { AutomationCheckinOutcome } from '../automation/index.js'; import type { CheckinReceiptStore } from './receipts.js'; import { type CheckinConfig, type CheckinDeliverer, type CheckinJudge, type CheckinReceipt, type CheckinStateReader } from './types.js'; /** * The narrow config surface the check-in reads/writes. Intentionally string- * keyed rather than typed against the ConfigKey union: the checkin.* keys live * in the config DEFAULTS tree (schema-domain-runtime.ts) and flat settings, and * the daemon binds this via a small adapter over its ConfigManager, this keeps * the (grandfathered, shrink-only) schema-types.ts ConfigKey union untouched. */ export interface CheckinConfigAccess { get(key: string): unknown; set(key: string, value: string | boolean): void; } export interface CheckinServiceDeps { readonly config: CheckinConfigAccess; readonly stateReader: CheckinStateReader; readonly judge: CheckinJudge; readonly deliverer: CheckinDeliverer; readonly receipts: CheckinReceiptStore; /** The automation manager the scheduled check-in job is synced onto (optional in tests). */ readonly automation?: Pick | undefined; /** Injectable clock for quiet-hours tests. */ readonly now?: (() => number) | undefined; } export interface SetCheckinConfigInput { readonly enabled?: boolean | undefined; readonly cadence?: string | undefined; readonly deliveryChannel?: string | undefined; readonly quietHours?: string | undefined; } export declare class CheckinService { private readonly deps; constructor(deps: CheckinServiceDeps); private now; getConfig(): CheckinConfig; setConfig(input: SetCheckinConfigInput): Promise; listReceipts(limit?: number): Promise; /** Wire this service as the automation manager's check-in evaluator, then sync the job. */ attach(): Promise; /** * Keep a single kind:'checkin' automation job in step with the config: create * it (enabled) when missing, update its cadence, and toggle enabled to match. * Best-effort, the automation subsystem must be enabled for a job to exist; * when it is off, createJob throws and we leave scheduling for when it is on. */ syncScheduledJob(): Promise; /** * Run one check-in evaluation and record its receipt. Returns the terminal * outcome the automation run records (see checkin-execution.ts). `_jobId` is * accepted for the scheduled path but the loop does not depend on it. */ evaluate(trigger: 'scheduled' | 'manual', _jobId?: string): Promise; private record; } //# sourceMappingURL=service.d.ts.map