/**
 * design/252 G-6 — the LIVENESS half the wiring manifest deliberately does not have.
 *
 * The manifest's own §0 boundary says it: "this is STATIC ASSEMBLY SELF-DISCLOSURE — seam presence and
 * shape, as facts. It does NOT prove liveness (a callback bound to the wrong run, a dead queue, an
 * adapter's internal failure, an answer routed to the wrong instance). Liveness belongs to round-trip
 * probes, which are a separate obligation." This module is that obligation for the PARK lane, and it
 * quotes the boundary rather than dissolving it: a manifest reporting `parkLane.effective: true` over a
 * store declaring `durability: "durable"` says a store is wired and what it CLAIMS. It cannot say the
 * store accepts a row, returns the same row, and lets the fence win — which is the whole park contract,
 * and the part a deployment gets wrong (a read-only mount, a serializer that drops a nested field, a
 * scope column missing from the WHERE).
 *
 * TWO CHECKS, DIFFERENT KINDS, DELIBERATELY IN ONE MODULE:
 *  · {@link probeParkRoundTrip} — the live probe: mint a synthetic parked row, read it back, verify the
 *    load-bearing fields survived, fence it, confirm the fence landed.
 *  · {@link durableParkGapOf} — the STATIC two-halves reading: a durable park is a durable checkpoint
 *    store AND a durable session store, and a deployment with one of them is the configuration whose
 *    failure mode is a resume that reports a missing session instead of the seat that is missing. One
 *    module because they are one question asked at two costs, and a second home for "what does a whole
 *    durable park need" is how the two answers drift.
 *
 * WHAT THE PROBE WRITES (read this before wiring it): it PUTs a real checkpoint row into the real
 * store, under a scope of its own (`{@link PARK_SELFCHECK_SCOPE_PREFIX}<random>`) that no task ever
 * uses, and fences it to `expired` on EVERY exit — including the failing ones, since a pending row is,
 * to an approval inbox, an approval waiting for someone.
 *
 * The expired row then REMAINS, and remains permanently as far as this interface is concerned: there is
 * no delete verb on `CheckpointStore`, and `reap` moves PENDING rows to expired rather than removing
 * expired ones. So each probe run costs one small terminal row under one throwaway scope, and reclaiming
 * them is the backend's own retention concern (a table TTL, a sweep keyed on the scope prefix). An inbox
 * does not see them — `listByScope` enumerates pending rows only — but `listScopes` may still report the
 * scope, and during the probe's own window the row is briefly enumerable and, in principle, resolvable
 * by anything watching the whole store. Both are the price of probing the real lane rather than a
 * pretend one; a deployment that cannot pay it should not run the probe, and there is no read-only
 * variant because a read-only probe would prove exactly what the manifest already discloses.
 */
import type { RunnerDeps, TaskSpec } from "./types.js";
/** The scope prefix every synthetic probe row is filed under — never a task scope, so a probe row can
 *  never be mistaken for (or resolved as) a real pending approval. */
export declare const PARK_SELFCHECK_SCOPE_PREFIX = "sema:park-selfcheck:";
/**
 * How long any single store call may take before the probe stops waiting and calls it a failure.
 *
 * A bound is MANDATORY rather than optional, for the reason this module exists at all: the probe is a
 * DIAGNOSTIC for storage that may be sick, and the sickness it is most likely to meet — a connection
 * that neither answers nor errors — is exactly the one an unbounded `await` turns into a wedged
 * startup. A probe that hangs instead of reporting is worse than no probe: it fails in the shape it was
 * written to detect, and silently.
 */
export declare const PARK_SELFCHECK_STEP_TIMEOUT_MS = 10000;
/**
 * How far in the FUTURE the synthetic row's abandonment deadline sits.
 *
 * A past deadline would make the row reapable the instant it is filed, and a CORRECT concurrent reaper
 * could then expire it between the probe's own steps — reporting a healthy deployment as a broken one
 * (the read that follows would see an expired row, or the enumeration an empty scope). A short future
 * window keeps the row out of a reaper's reach for the length of the probe while still leaving any
 * residue from a crashed probe reapable shortly after, without an operator doing anything.
 */
export declare const PARK_SELFCHECK_ROW_TTL_MS = 60000;
/**
 * The closed set of things a park round-trip can fail at. A machine keys on these; the accompanying
 * `detail` is prose for a person and is never the discriminator.
 *
 * Ordered as the probe walks the contract, which is also the order an operator debugs in: a store that
 * cannot be written is a different day's work from one that writes and then hands back a row with a
 * dropped field.
 */
export type ParkProbeFindingCode = 
/** `put` threw — the store did not accept a checkpoint at all. */
"put_failed"
/** `get` threw, or answered `null` for a token the store had just accepted. */
 | "row_not_readable"
/** The row came back, but a load-bearing field did not survive the round-trip (see `detail` for which). */
 | "row_not_faithful"
/** The row came back with a status other than `pending` — a park nobody can resolve. */
 | "row_not_pending"
/** `listByScope` is implemented and did NOT list the pending row: the inbox enumeration is blind to it. */
 | "row_not_enumerable"
/** `expire` threw, or lost a CAS it was the only contender for — the fence the reaper and
 *  `TaskStream.destroy` both depend on does not close. */
 | "fence_failed"
/** The fence reported a win and the row is still `pending` on a re-read: the CAS did not land. */
 | "fence_not_durable";
/** One thing that went wrong, with the prose a person needs to act on it. */
export interface ParkProbeFinding {
    readonly code: ParkProbeFindingCode;
    readonly detail: string;
}
/**
 * What one probe run concluded.
 *
 * `"round_trip_ok"` is the ONLY affirmative word, and it is only ever reported with an empty
 * `findings` list — the invariant is asserted rather than assumed, because a probe whose failure can be
 * read as a pass is worse than no probe (it is the manifest's disclosure wearing a verification's
 * clothes, which is precisely what the §0 boundary forbids).
 */
export interface ParkSelfCheckResult {
    readonly verdict: "round_trip_ok" | "failed" | "not_probed";
    /** NON-EMPTY ⟺ `verdict === "failed"`. The two non-failing verdicts carry none: `"round_trip_ok"`
     *  because nothing went wrong, `"not_probed"` because nothing was attempted (its reason is in
     *  {@link summary} — a finding there would name a defect in a store that was never touched). */
    readonly findings: readonly ParkProbeFinding[];
    /** The scope the synthetic row was filed under, so an operator can find (and reap) the residue.
     *  Present from the moment a write was ATTEMPTED — including a `put` that threw, because a backend can
     *  commit and then surface a transport error, so a scope on a failed attempt is exactly where an
     *  operator has to look. Absent only on `"not_probed"`, where nothing was attempted. */
    readonly scope?: string;
    /** A single sentence naming the outcome — for a startup log line. Never the machine discriminator. */
    readonly summary: string;
    /** The static two-halves reading taken alongside the probe (see {@link durableParkGapOf}); absent when
     *  the durable topology is whole or does not apply. A probe can pass every round-trip check on a
     *  deployment whose parks still cannot be resumed after a restart, and this is that fact. */
    readonly durableTopologyGap?: string;
    /** Additive, on `"round_trip_ok"` only: the expire CAS reported a LOSS while the row nonetheless
     *  closed. From outside this is indistinguishable from the store's own housekeeping getting there
     *  first — so the verdict stays green — but a backend that transitions the row and then mis-reports
     *  the CAS win would pass on exactly this arm, and `TaskStream.destroy` trusts that boolean. A
     *  machine-readable member rather than a summary sentence, so a harness that wants to alert on it
     *  can (the summary is never the discriminator). */
    readonly casLossObserved?: true;
}
/**
 * design/252 G-6 (sibling finding, from the G-5 demo) — the DURABLE PARK's two halves, and the sentence
 * to say when only one of them is wired.
 *
 * A park that survives a restart needs BOTH: the checkpoint row (the question) and the session (the
 * conversation the answer resumes into). A deployment that wires a durable checkpoint store over the
 * default in-memory session store parks perfectly and then, after a restart, fails the resume with
 * "session … does not exist" — a SYMPTOM, reported at the seat that is present, naming nothing about
 * the seat that is missing. Whoever reads that message goes looking for a lost session id.
 *
 * Returns the naming sentence, or `undefined` when there is nothing to say: both halves durable (whole),
 * or no checkpoint store at all (the deployment is not doing durable parks, so there is no gap — the
 * manifest's `parkLane.capable: false` is the fact there).
 */
export declare function durableParkGapOf(halves: {
    checkpointDurable: boolean;
    checkpointWired: boolean;
    sessionDurable: boolean;
}): string | undefined;
/** The two-halves reading taken off a deployment's own seats. Split from {@link durableParkGapOf} so the
 *  sentence can be unit-tested without a Runner and the seat reading has one home. */
export declare function durableParkGapFor(deps: Pick<RunnerDeps, "checkpointStore" | "sessionStore">, spec?: Pick<TaskSpec, "checkpointStore">): string | undefined;
/**
 * design/252 G-6 — drive one synthetic park through the wired store and report what the assembly can
 * actually DO, as opposed to what it declares.
 *
 * Never throws for a store's failure: every step's exception is captured into a {@link ParkProbeFinding}
 * so a startup self-check can decide for itself whether a dead park lane is fatal. That decision is the
 * deployment's, deliberately — this module reports, loudly and in a closed vocabulary, and does not
 * legislate. What it will NOT do is report a pass it did not observe: `"round_trip_ok"` is returned only
 * with an empty findings list, and the invariant is asserted below rather than left to reading.
 *
 * This is a DIAGNOSTIC probe, not a health-poll body: every run files (and then fences) one real
 * synthetic row under the reserved scope prefix. Mounted on a high-frequency health endpoint it
 * becomes write amplification against the checkpoint store — run it at startup, on demand, or on a
 * coarse operator cadence, not per request.
 */
export declare function probeParkRoundTrip(deps: Pick<RunnerDeps, "checkpointStore" | "sessionStore">, spec?: Pick<TaskSpec, "checkpointStore">): Promise<ParkSelfCheckResult>;
