import type { TargetStatus } from "./targets.js"; /** * Below this, a gap is timestamp granularity rather than a stale build. * * Small on purpose. The case worth catching is an edit made a moment ago * against a build made before it, which is exactly when someone is checking * whether their fix worked, so a generous window would sleep through the one * run that most needed the warning. */ export declare const STALE_SLACK_MS = 5000; export interface WalkOpts { /** Entries visited before the walk gives up. */ maxEntries?: number; /** Wall time in milliseconds before the walk gives up. */ maxMs?: number; } /** * The newest mtime among a project's source files, or null when the walk * cannot answer: the directory is unreadable, nothing under it is source, or a * cap tripped on a tree too large to scan inside a capture's patience. * * Null is "no opinion", never "fresh", so every caller falls silent instead of * asserting something it did not measure. */ export declare function newestSourceMtime(projectDir: string, opts?: WalkOpts): number | null; export interface StaleTarget { name: string; url: string; /** What the server said it served, epoch milliseconds. */ servedAt: number; /** The newest source file on disk, epoch milliseconds. */ newestSource: number; /** How far behind the served build is, in whole minutes, at least 1. */ behindMinutes: number; } /** * The targets serving something older than the source, widest gap first. * * Silent for any target that sent no `Last-Modified`, and silent when the walk * had no opinion, because one unknown on either side leaves nothing to compare. */ export declare function staleTargets(statuses: readonly TargetStatus[], newestSource: number | null, slackMs?: number): StaleTarget[]; /** * Why this run's evidence may not show the current code, or null when there is * no reason to doubt it. A value rather than a throw, so the caller decides * whether it warns or blocks. Nothing calls this and then refuses a run: * lookout never starts or rebuilds anything, and a warning the operator can act * on beats a run they cannot make happen. */ export declare function staleMessage(stale: readonly StaleTarget[]): string | null; /** The sibling of `downReason()`, from statuses rather than a computed list. */ export declare function staleReason(statuses: readonly TargetStatus[], newestSource: number | null, slackMs?: number): string | null; /** * What a suspect run records about itself, in a shape a report can print. * * Timestamps become ISO strings here because this ends up in a run's flags and * from there in an issue document, where epoch milliseconds tell a reader * nothing about whether the evidence was worth trusting. */ export interface StaleStamp { target: string; url: string; behindMinutes: number; servedAt: string; newestSource: string; } export declare function staleStamp(stale: readonly StaleTarget[]): StaleStamp[];