export interface AuditSessionLike { run(query: string, params?: Record): Promise<{ records: Array<{ get(key: string): unknown; }>; }>; } /** One passive dispatch as fetched from the ledger, joined to whether a backing * :Task exists. `dispatchedAtMs` is the epoch-ms parse of the ledger row's * `dispatchedAt` ISO string; `backed` is (backing-task-count > 0). */ export interface DispatchRow { accountId: string; dispatchedAtMs: number; backed: boolean; } export interface PassiveIntakeFinding { accountId: string; /** Eligible dispatches under this account with no backing :Task. */ unbacked: number; } /** The turn window applied to the ledger rows. A dispatch is eligible only when * it has settled (`age >= graceMs`, so a still-running turn does not * false-alarm) and is still in the alarm horizon (`age <= windowMs`, so an old * dispatch is not re-alarmed forever). */ export interface AuditWindow { now: number; graceMs: number; windowMs: number; } /** Pure reconcile: group eligible, unbacked dispatches per account and return a * finding (unbacked > 0) for each. Deterministic in `now` so the grace and * horizon boundaries are unit-testable. Accounts are returned in first-seen * order so the emitted lines are stable across a pass. */ export declare function reconcilePassiveIntake(rows: DispatchRow[], { now, graceMs, windowMs }: AuditWindow): PassiveIntakeFinding[]; /** The audit-gap line. The full account is logged (not truncated) so it * correlates directly with the `op=dispatch account=` lines in the window; * `unbacked>0` is the alarm. */ export declare function formatAuditLine(f: PassiveIntakeFinding): string; /** Fetch every ledger row within the scan horizon, joined to whether a backing * :Task exists. The `>= $windowStart` bound only limits the scan; the pure * reconcile OWNS the semantic window — it enforces the grace floor (which the * scan cannot, since no `now` is passed to Cypher for it) and re-checks the * horizon under the same `now`, so an over-fetch of rows younger than grace is * harmless. */ export declare function fetchDispatchRows(session: AuditSessionLike, windowStartIso: string): Promise; export interface PassiveIntakeAuditDeps { neo4jUri: string; neo4jUser: string; neo4jPassword: string; logger: (line: string) => void; /** Turn-settle floor: a dispatch younger than this is still in flight. */ graceMs: number; /** Alarm horizon: a dispatch older than this has aged out of the window. */ windowMs: number; } /** Run one audit pass and log an `op=audit-gap` line per flagged account. * Best-effort Neo4j — absent env or an unreachable/erroring read logs * `op=unavailable` and never throws (Neo4j may not be up at boot). A clean pass * logs a single `op=ok unbacked=0` line so the audit's own liveness is visible. */ export declare function emitPassiveIntakeAudit(deps: PassiveIntakeAuditDeps): Promise; export interface PassiveIntakeAudit { start(): void; stop(): void; } /** Standing periodic audit. Unref'd interval so it never holds the process open; * each tick re-emits best-effort. */ export declare function createPassiveIntakeAudit(deps: PassiveIntakeAuditDeps & { intervalMs: number; }): PassiveIntakeAudit; //# sourceMappingURL=passive-intake-audit.d.ts.map