import type { DaemonSession } from './types.js'; export declare const SESSION_OWNER_REMINDER_STATES: readonly ["idle", "dormant", "pending_repo", "tui_prompt", "agent_attention", "limited"]; export type SessionOwnerReminderState = typeof SESSION_OWNER_REMINDER_STATES[number]; export interface SessionOwnerReminderConfig { enabled: boolean; intervalMinutes: number; text: string; states: SessionOwnerReminderState[]; } export interface SessionOwnerReminderRecord { sessionId: string; stateFingerprint: string; actionableSince: number; lastObservedActivityAt: number; lastRemindedAt?: number; retryAfterAt?: number; } export type SessionOwnerReminderRecords = Record; export declare const DEFAULT_SESSION_OWNER_REMINDER: SessionOwnerReminderConfig; /** Strict normalizer shared by config loading and write validation. */ export declare function normalizeSessionOwnerReminderConfig(raw: unknown): SessionOwnerReminderConfig | undefined; export declare function deriveSessionOwnerReminderStates(ds: DaemonSession): SessionOwnerReminderState[]; /** * Observation fingerprint used both to detect a state transition (reset the * quiet period) and to seed the per-cycle delivery UUID. It must capture not * only WHICH runtime signals are present but also their INSTANCE identity for * the signals that get replaced in place while the label stays constant: * * - `agent_attention` → a fresh `{kind, reason, at}` is written on every new * attention raise, so key on `agentAttention.at`. * - `tui_prompt` → an old TUI prompt card is cleared and a new * `tuiPromptCardId` set between scans, so key on that id. * * Without the instance component, the old signal being resolved and a brand-new * same-category signal appearing (e.g. a second, unrelated attention request) * would inherit the previous signal's elapsed quiet time and could @ the owner * almost immediately — undercutting the "give N minutes to handle THIS" promise. * * The remaining states (idle / dormant / pending_repo / limited) have no * distinct replaceable instance, so their label alone is a faithful key. * * INVARIANT: for a fixed instance the fingerprint is stable across scans, so a * within-cycle failed-send retry recomputes the SAME fingerprint → the same * delivery UUID → the existing Lark dedupe window still suppresses duplicates. * A new instance changes the fingerprint, which resets the record and thereby * starts a fresh cycle whose eventual UUID is legitimately different. */ export declare function sessionOwnerReminderObservationFingerprint(ds: DaemonSession, states: SessionOwnerReminderState[]): string; export interface SessionOwnerReminderControllerDeps { load(): SessionOwnerReminderRecords; save(records: SessionOwnerReminderRecords): void; send(ds: DaemonSession, text: string, uuid: string): Promise; canSend(ds: DaemonSession): boolean; onError?(ds: DaemonSession, error: unknown): void; } export declare function sessionOwnerReminderDeliveryUuid(sessionId: string, stateFingerprint: string, dueBase: number): string; /** Durable, deterministic scan engine. Scheduling and Lark IO are injected. */ export declare class SessionOwnerReminderController { private readonly deps; constructor(deps: SessionOwnerReminderControllerDeps); scan(sessions: Iterable, config: SessionOwnerReminderConfig, now?: number): Promise; } //# sourceMappingURL=session-owner-reminder.d.ts.map