import type { LoopStore } from "./store/index.js"; import { type BuildHealthScanOptions, type LoopsHealthReport, type LoopsHealthScan } from "./health.js"; import { type DoctorReport } from "./doctor.js"; /** * Hosted-mode `loops health` and `loops doctor` (task e3b6f1d4). * * Before this, both verbs refused outright whenever the client was flipped to * the hosted API — the CLI's only two diagnostics were unavailable in the one * configuration this fleet runs, and therefore unavailable during a scheduler * incident. The refusal's advice (unset the HASNA_LOOPS_* variables) pointed the * diagnostic at the LOCAL runtime, which is not where the loops live, so * following it produced a confident report about the wrong runtime. * * The rule this module holds to: never print a summary without saying which * runtime produced it and what was not inspected. Every report carries * `backend` and a non-empty `unchecked` list. */ export interface HostedBackend { transport: "api"; /** Base URL of the hosted control plane. Never carries the API key. */ apiUrl?: string; } export interface UncheckedItem { id: string; reason: string; } export interface HostedHealthResult { backend: HostedBackend; report: LoopsHealthReport; executionTruth: HostedExecutionTruth[]; unchecked: UncheckedItem[]; } export interface HostedHealthScanResult { backend: HostedBackend; scan: LoopsHealthScan; unchecked: UncheckedItem[]; } export interface HostedExecutionTruth { loopId: string; state: "healthy" | "dead_cadence" | "unproven"; finishedRuns: number; acceptedRuns: number; failedRuns: number; windowLimit: number; } export interface HostedDoctorResult { backend: HostedBackend; report: DoctorReport; unchecked: UncheckedItem[]; } export declare function hostedBackend(store: LoopStore): HostedBackend; /** * Build the health report against the hosted control plane. * * Two resolution rounds: the classifier only ever reaches one level past the * loops it was given (a route-drain loop's child loop), so one follow-up fetch * converges. Whatever is still unresolved is named in `unchecked` rather than * being folded into a clean summary. */ export declare function buildHostedHealthReport(store: LoopStore, opts?: { limit?: number; includeInactive?: boolean; includeArchived?: boolean; now?: Date; }): Promise; /** * Build the bounded health scan from a hosted snapshot. The classifier is * shared with local SQLite through {@link HealthSource}; only snapshot * population differs by transport. * * Failed per-loop reads remain visible in `unchecked` and degrade the scan, * rather than becoming an empty history that looks like a clean fleet. */ export declare function buildHostedHealthScan(store: LoopStore, opts?: BuildHealthScanOptions): Promise; /** * Doctor against the hosted control plane. * * Split deliberately in two: the machine-scoped checks answer "can a loop * execute here", the control-plane-scoped ones answer "what does the scheduler * hold". Neither substitutes for the other, and mixing them unlabelled is how * an operator reads a green local toolchain as a green scheduler. */ export declare function buildHostedDoctorReport(store: LoopStore): Promise;