import { Effect } from "effect"; import type { DeviceSnapshot, HostProfile, TelemetryField } from "../contracts"; /** What a probe contributes to the merged snapshot. */ export type SnapshotFragment = Partial>; export interface ProbeResult { readonly fragment: SnapshotFragment; /** Fields this probe can genuinely answer on this host. A field absent here renders as * "unsupported" rather than as a plausible zero. */ readonly capabilities: readonly TelemetryField[]; } export interface DeviceProbe { readonly id: string; /** Cheap gate — no I/O. Probes that pass still have to tolerate missing tooling. */ readonly detect: (host: HostProfile) => boolean; readonly run: (host: HostProfile) => Effect.Effect; } export const emptyResult: ProbeResult = { fragment: {}, capabilities: [] }; /** A probe must never fail the snapshot: a missing tool is data, not an error. */ export const neverFails = (effect: Effect.Effect): Effect.Effect => effect.pipe(Effect.catchCause(() => Effect.succeed(emptyResult)));