import { type BackgroundAgentRecord, type BackgroundAgentStore } from "./background-agent-store.js";
import { type StopSource, type TaskAccess, type TaskRetrievalStatus, type UnifiedTaskOutput, type UnifiedTaskResult, type BackgroundAgentTaskHandle, type DurableAgentCore, type ParkedClaimTicket, type RegisterBackgroundAgentInput } from "./task-registry-shared.js";
import { type ToolResultStore } from "./tool-result-store.js";
import { type AgentState } from "./agent-state.js";
import type { CheckpointSeat } from "./checkpoint-seat.js";
/**
 * Subagent transcript persistence (delegation entry caps) — the ACTIVE handles of one delegation
 * tree in THIS process's registry: `background_agent` handles whose status is running/pending
 * (parked does not burn a concurrency slot — a suspension is not concurrency; terminal handles are
 * not active) under the `(scope, rootSessionId)` key (full depth: a grandchild's row carries the
 * tree's fixed-point root, so the whole tree shares one pool; a depth-1 row whose rootSessionId
 * predates the floor falls back to its parentSessionId — same fallback the access predicate's root
 * arm rides). SYNCHRONOUS by contract: the caps enforcement runs check→register in one synchronous
 * segment, which is what makes the reservation race-free in-process.
 */
export declare function activeDelegationHandlesLane(core: DurableAgentCore, scope: string, rootSessionId: string): string[];
export declare function ensureDurableHeartbeatLane(core: DurableAgentCore): void;
/** design/151 S1a — enqueue one durable-row write (see {@link DurableAgentLane} for the lane
 *  contract). `patch` is captured at CALL time (the settle-site values), applied in chain order.
 *
 *  hardening — failure taxonomy, decided by EVIDENCE not by exception class:
 *   - thrown store errors get a bounded in-lane retry (a transient outage must not permanently
 *     strand a terminal write — the settle is often the row's LAST write);
 *   - `already_exists` on a put and a lost CAS both trigger a read-back writerId check first: an
 *     AMBIGUOUS earlier commit (backend committed, response failed) or a stale-arm flip
 *     (reap wrote rev up under a live run) is OUR row wearing a newer rev — ADOPT the rev and
 *     re-apply (the real terminal truth must beat a reaper's guess); only a row carrying a
 *     FOREIGN writerId poisons the lane (never clobber another writer). */
export declare function durableAgentWriteLane(handle: BackgroundAgentTaskHandle, patch: Partial<BackgroundAgentRecord>, clear?: readonly (keyof BackgroundAgentRecord)[]): void;
/** design/151 S1b — is this row's durable lane ARMED (store wired at registration, not contaminated)?
 *  Observability/test face. ⚠️ NOT the lifecycle-flip key: arming says a row was ATTEMPTED, not
 *  that it EXISTS — release anchors gate on {@link durableAgentRowProbe}. */
export declare function durableAgentArmedLane(core: DurableAgentCore, id: string): boolean;
/** design/151 S1b — the AWAITABLE lifecycle-flip key. Returns undefined when no
 *  lane was armed; otherwise a probe CLOSURE over the HANDLE (outlives its eviction from the map —
 *  retain-ledger TTL arms fire hours after terminal GC) that flushes the queued writes and answers
 *  whether a durable row actually EXISTS right now (initial put confirmed, not contaminated). A store
 *  that never accepted the put answers false — the caller then RELEASES the session (pre-151 path)
 *  instead of stranding an unreachable transcript.
 *
 *  The closure reads `handle.durable` at CALL time rather than capturing the lane: a revive's claim
 *  hands the row to a fresh lane and retires the one that was current when the probe was minted, and
 *  a probe bound to the retired object would answer "no row" for a row that plainly exists — and the
 *  caller acts on that by releasing the child's transcript session, the exact strand this probe was
 *  built to prevent. Reading through the handle also survives the map eviction (the closure keeps the
 *  handle object alive), so the outlives-terminal-GC property the retain arms rely on is unchanged. */
export declare function durableAgentRowProbeLane(core: DurableAgentCore, id: string): (() => Promise<boolean>) | undefined;
/** design/151 §7.3 (F-8) — open the in-process claim window for a tier-3 revival of `id`.
 *  SYNCHRONOUS admission check + mark in one call: refuses (false) while the handle is live
 *  running/pending in THIS process (the live delivery ladder owns it), while a reap sweep is
 *  adjudicating it, or while another claim holds the window. The caller MUST call
 *  {@link endDurableClaim} in a finally — the window spans its whole claim-CAS→spawn/rollback
 *  sequence, and a leaked mark would permanently fence the handle from revival, reap AND the
 *  terminal-handle GC (which skips ids inside this window), i.e. it would also leak the handle. */
export declare function beginDurableClaimLane(core: DurableAgentCore, id: string): boolean;
/** Close the {@link beginDurableClaim} window (idempotent). */
export declare function endDurableClaimLane(core: DurableAgentCore, id: string): void;
/** design/151 §3.1 MED-7 — the BLESSED retention path: the joint reap that drops a
 *  doomed row under its rev guard and THEN releases its transcript session (raw `store.reap`
 *  strands transcripts — its contract says so). Policy semantics mirror the store sweep (double
 *  bound + stale-running flip; running rows are never deleted).
 *
 *  ORDER: conditional DELETE first, release only after the delete WINS. The
 *  reverse (release→delete) destroyed a live transcript whenever a concurrent writer revived the
 *  row between the release and the losing CAS (stale-flip heal / retained-session revive: row
 *  back to running, session already gone). Failure economics of this order: a crash (or release
 *  throw) after the winning delete LEAKS the session to the deployment's session TTL sweep —
 *  recoverable — instead of stranding a live transcript — not. The release must therefore treat
 *  a missing/already-released id as a no-op (idempotent — a release that throws on
 *  not_found merely forfeits this bookkeeping, the TTL sweep still owns the orphan). An
 *  IN-PROCESS handle running again gates the row out entirely (a revive flips memory before its
 *  durable write flushes). `sessions` is structural (unpin/release) so any SessionStore fits
 *  without an import cycle.
 *  ⚠️ Review note: passing `sessions` DECLARES that its `release` truly ends the
 *  transcript's addressability (durable deletion or an equivalent lifecycle handoff). A face
 *  whose release only clears in-memory state must NOT be passed — omit `sessions` instead
 *  (fail-closed: rows are kept and counted in `skippedNoSessions`, and the deployment's own
 *  session GC owns the joint lifecycle). A half-true release deletes the row while the
 *  transcript lives on unanchored — the exact strand this orchestration exists to prevent. */
export declare function reapDurableAgentsLane(core: DurableAgentCore, scope: string, deps: {
    store: BackgroundAgentStore;
    /** `listPlaced` (subagent transcript persistence, optional): arms the PARTITION leg below —
     *  placed transcript sessions whose owning row is GONE (row never landed / deleted-but-release-
     *  failed) are the orphan shape only a session-side enumeration can find. Absent = that leg is
     *  unavailable (documented; the row-joined path still runs). */
    sessions?: {
        unpin?(sessionId: string): unknown;
        release(sessionId: string): Promise<void> | void;
        listPlaced?(kind: "subagent", opts?: {
            olderThanMs?: number;
            scope?: string;
        }): Promise<Array<{
            sessionId: string;
            placedAt: number;
        } & ({
            scope: string;
            handle: string;
        } | {
            tupleIncomplete: true;
        })>>;
    };
    /** design/151 §7.7 (F-13) — the row's mailbox dies with the row: a WINNING delete also drops
     *  the (scope, handle) mailbox (advisory — a mailbox fault never blocks the reap; an orphaned
     *  box is bounded by the mailbox's own `reap` policy). Structural face (drop only), so the
     *  deployment passes its `RunnerDeps.mailboxStore` directly. */
    mailbox?: {
        drop(scope: string, handle: string): Promise<void>;
    };
}, policy: {
    now?: number;
    maxAgeMs?: number;
    keep?: number;
    staleRunningMaxAgeMs?: number;
}): Promise<{
    rowsReaped: number;
    sessionsReleased: number;
    skippedNoSessions: number;
    orphanPlacedReleased: number;
}>;
/** after a probe-false RELEASE the row must stop claiming a transcript:
 *  the heartbeat's F-1 arm keeps re-driving a flush-failed lane, so a later successful flush
 *  would otherwise persist a row whose sessionId points at the session the caller just released.
 *  Clearing the anchor makes the eventual row honest: state/result survive, transcript does not. */
export declare function releaseDurableTranscriptAnchorLane(core: DurableAgentCore, id: string): void;
/** design/151 S1a — bind the child's freshly-minted store session id onto the row (the transcript /
 *  resume anchor; absent at register time because the child session is created after registration). */
export declare function bindBackgroundAgentSessionLane(core: DurableAgentCore, id: string, sessionId: string): void;
/**
 * #22 — record the org-memory admission verdict THIS leg adjudicated onto the durable row, so the
 * next CROSS-PROCESS revival (which rebuilds the spec from the reviving caller's mount and cannot
 * see this process's memory) starts from it instead of re-adjudicating unconstrained. Called once
 * per leg at the injector-ready barrier (prepare has succeeded by then, so the verdict exists); a
 * revival cycle overwrites the previous cycle's record with its own, which the admission door
 * guarantees is a subset. Same durable write lane as every other post-registration fact — a
 * store-less registration is a no-op, and a contaminated lane stays contaminated.
 *
 * A DROPPED write is disclosed. This record is the only carrier a narrowing has across a process
 * boundary, so what stands on the row when the write does not land is the PREVIOUS leg's wider
 * verdict — which the next revival then seeds from. Two drop shapes, one message each: a contaminated
 * lane refuses at its front door, and an exhausted flush leaves the value unwritten with the lane
 * still armed. The channel is the same durable-agents warning channel the lane uses for the contamination
 * itself (that one says writes stopped; this one says WHICH fact stopped with them). The write
 * remains best-effort: no leg faults because its bookkeeping failed.
 *
 * The FORK background lane deliberately does not call this: a fork row refuses the tier-3 claim
 * (subagent.ts, revival preflight), so it has no reader.
 */
export declare function recordBackgroundAgentOrgAdmissionLane(core: DurableAgentCore, id: string, verdict: import("./memory-admission.js").OwnOrgAdmissionVerdict): void;
/** design/115 P3: register a background sub-agent run. The CALLER owns driving the child promise and
 *  calling {@link settleBackgroundAgent} at the end; the registry provides the unified task_id, the
 *  owner/scope guard, poll/stop dispatch, and terminal GC — exactly like the other two kinds. */
export declare function registerBackgroundAgentLane(core: DurableAgentCore, input: RegisterBackgroundAgentInput): string;
/**
 * design/153 §7.1 — the SINGLE running→parked transition point (r4 F-02: every parked-related
 * transition goes through registry discipline, never a bare store-status write). Called by the bg
 * watcher's `suspended` branch AFTER the durable checkpoint exists and the deployment attested the
 * child session durable (§7.3 capability). First-writer-wins like settle: a TaskStop that already
 * flipped killed refuses the park (returns undefined — the CALLER must then EXPIRE the checkpoint,
 * the §7.1 no-orphans compensation). Releases the delivery channel like the other non-running
 * transitions (a parked child has no live lane; a SendMessage parks per session as with terminal).
 */
export declare function parkBackgroundAgentLane(core: DurableAgentCore, id: string, park: {
    checkpointToken: string;
    seq?: number;
    resolveStop?: () => Promise<boolean>;
}): "parked" | undefined;
/**
 * design/153 §7.1 (件1 split-brain fence) — the registry-aware reconciliation entry an
 * IN-PROCESS deployment calls on its retention cadence. Two halves, one call:
 *  1. LIVE half: this instance's own parked handles are probed against their checkpoint and, on
 *     expired/missing/DECIDED-ELSEWHERE, settled failed THROUGH the handle (poll/stop/durable row
 *     stay coherent — quiescence poked, arbitration closure dropped, durable clear rides the settle
 *     write).
 *  2. STORE half: delegates to the store-level {@link reconcileParkedAgents} with
 *     `excludeWriterId` = this instance's writerId, so foreign (dead-process) rows are cleaned
 *     without ever touching a row this process is live-managing.
 *
 * The live half used to skip EVERY non-expired/missing state, `resolved` included, and
 * that was the whole zombie: a parked row whose checkpoint was decided by the task-level
 * `resumeCheckpoint` leg (a serving layer's documented fallback when its parked-row discriminator
 * misses) is decided but still says `parked`, its side effects already executed by a path that never
 * touched this registry. Nothing else could reach it either — a re-claim answers
 * `checkpoint_not_pending`, and the store half excludes exactly the rows this process live-manages —
 * so it stayed `parked` for the life of the process. It now converges here. The one `resolved` case
 * that must still be LET THROUGH is the registry's own claim window (reservation → consume flip): that
 * skip is load-bearing, and it is now expressed as what it actually is — a claim in flight — instead
 * of as a blanket state filter that also swallowed the case with no claimant at all.
 */
export declare function reconcileParkedAgentsLane(core: DurableAgentCore, stores: {
    agentStore: import("./background-agent-store.js").BackgroundAgentStore;
    checkpointStore: Pick<import("./checkpoint-store.js").CheckpointStore, "get">;
}, scope: string, now: number, opts?: {
    staleClaimMaxAgeMs?: number;
}): Promise<{
    failed: number;
    rolledBack: number;
}>;
/**
 * design/153 §7.2c (件3b) — the RESERVATION half of the parked-resume claim. Pure reservation
 * (r6 H-1): the row STAYS `parked` — only `parkClaimId` is written (guarded CAS binding
 * rev+status+token+claim-absence, single-claimer by construction), the live handle keeps its
 * parked state AND its TaskStop arbitration closure (an expire during the reservation window
 * still wins — by design; the resume's token-consume CAS is the only thing that can beat it).
 * parked→running happens ONLY at the 件3c consume flip, never here.
 *
 * AUTHORIZATION LAYERING (r4 F-06, doc-pinned): `access` is ROW VISIBILITY only
 * ({@link canAccessAgentRecord}); the operator's approval authority (/decide) is the SERVER's
 * front gate — this verb must only be reached by an already-authorized decision path.
 * Binding (r6): the token comes FROM THE ROW (never caller-supplied), the checkpoint must be
 * `pending`, and `cp.sessionId === row.sessionId` (same child transcript — blocks swapping in a
 * different child's checkpoint).
 */
export declare function claimParkedAgentLane(stores: {
    agentStore: import("./background-agent-store.js").BackgroundAgentStore;
    checkpointStore: Pick<import("./checkpoint-store.js").CheckpointStore, "get">;
}, handle: string, access: TaskAccess): Promise<{
    ok: true;
    ticket: ParkedClaimTicket;
} | {
    ok: false;
    reason: "not_found" | "not_parked" | "binding_broken" | "checkpoint_not_pending" | "claim_lost" | "store_unreachable";
}>;
/**
 * design/153 §7.2c (件3b) — roll back / settle a reservation whose resume could not proceed.
 * Disposition follows the CHECKPOINT truth re-read at call time (r6: never blind):
 *  - `pending`  → the reservation is cleared, the row returns to plainly-redeemable `parked`
 *    ("rolled_back"); no ownership change (a reservation never transferred it, so no epoch churn).
 *  - `expired`/`missing` → honest terminal `failed` ("failed") — same shape reconciliation mints.
 *  - `resolved` → the approval was CONSUMED (the resume died post-consume): NON-COMPENSABLE
 *    (r6 H-4) — terminal `failed`/outcome-unknown ("failed"); NEVER back to parked.
 *  - store unreachable → "retry" (nothing written; the reconciliation cadence is the backstop).
 * A LOCAL live parked handle follows the failed dispositions (poll/stop stay coherent).
 */
export declare function rollbackParkedClaimLane(core: DurableAgentCore, stores: {
    agentStore: import("./background-agent-store.js").BackgroundAgentStore;
    checkpointStore: Pick<import("./checkpoint-store.js").CheckpointStore, "get">;
}, ticket: ParkedClaimTicket): Promise<"rolled_back" | "failed" | "lost" | "retry">;
/**
 * design/153 §7.2d (件3c 3c H-1) — the CONSUME FLIP, SERIALIZED THROUGH THE DURABLE LANE:
 * the guarded parked→running store CAS runs INSIDE the lane chain (ordered after every seeded
 * write — the session-bind CAS included), so no in-flight lane write can race it, CAS-fail on the
 * flip's rev bump, read the new epoch as foreign, and contaminate the lane (which would permanently
 * drop finalize/terminal/re-park writes). On a won CAS the lane record/rev swap happens in the
 * SAME chain step and the live handle adopts (running, arbitration dropped — the token is
 * consumed; `parkClaimId` stays visible until finalize). Returns false when the row moved
 * (claim/status/token guard lost) — the caller aborts the resume.
 */
export declare function consumeParkedFlipLane(core: DurableAgentCore, id: string, stores: {
    agentStore: import("./background-agent-store.js").BackgroundAgentStore;
}, ticket: ParkedClaimTicket): Promise<boolean>;
/**
 * design/153 §7.2d (件3c) — attach finalize: the resume's delivery lane is live, the claim is
 * complete — clear `parkClaimId` (handle + durable row) so reconciliation stops seeing an
 * in-flight claim. Idempotent; a terminal settle that lands first clears the same keys itself.
 */
export declare function finalizeParkedResumeLane(core: DurableAgentCore, id: string): void;
/** Terminal update for a background agent (the spawn-side then/catch calls this exactly once).
 *  Reap sentinel note: {@link BG_AGENT_REAP_STOP_ERROR} is never STORED as `error` — status "killed"
 *  + stoppedBy already carry that fact, and an `error:` line beside a salvaged partial result reads
 *  as "the child's work failed" (review A1 follow-up). Real errors (e.g. "session released", a
 *  child crash) still land.
 *  design/129-B: returns the WINNING terminal status — the earlier writer's when this settle is refused
 *  (first-writer-wins), `undefined` when the handle is gone (evicted). Callers report THIS in their
 *  notification/terminal event so the push never contradicts the registry row (a completed-notify over a
 *  killed row — the TaskStop-then-late-resolve race — was an observable incoherence). */
export declare function settleBackgroundAgentLane(core: DurableAgentCore, id: string, outcome: {
    status: "completed" | "failed" | "killed";
    result?: string;
    resultFull?: string;
    error?: string;
    errorCode?: string;
    retryable?: boolean;
    errorKind?: string;
    retryAfterMs?: number;
    stoppedBy?: StopSource;
    seq?: number;
    cycle?: number;
}): "completed" | "failed" | "killed" | undefined;
/** Abort every background agent belonging to `access` (parent-task teardown — a finished parent must
 *  not leave orphan child runs burning tokens; mirrors clearBackgroundForOwner for bash). */
export declare function abortBackgroundAgentsForOwnerLane(core: DurableAgentCore, access: TaskAccess, opts?: {
    skipSessionScoped?: boolean;
    sessionScopedOnly?: boolean;
}): number;
/** CC206-B name resolution over the caller-visible background_agent rows (CC `cgo`/`gvy`, 206:575142-575178
 *  and 206:575199-575210 — sema's single-lane subset: no teammate/name-registry branches).
 *
 *  [c209-D] PUBLIC + explicit-name layer 0: the single resolver both TaskStop (:1839 leg) and
 *  SendMessage consume, so the two verbs can never drift. Ladder:
 *   0a. verbatim `handle.name` match — LATEST-WINS (CC SendMessage.md: "a newer agent took the name
 *       (latest wins)"; older rows stay task_id-addressable), any status (names keep working after
 *       completion — the resume face is the CC "resumes it from its transcript" counterpart).
 *       **Latest-wins is RESOLUTION, not permission to redirect a conversation**: CC pairs the same
 *       resolver with a per-conversation pin guard (`send_message_pin_guard`), and SendMessage REFUSES
 *       a send whose name has changed hands since this caller last used it. That guard lives at the
 *       SendMessage face (`createSendMessageTool`), exactly as it does upstream — this resolver stays
 *       a pure resolver, and TaskStop keeps its own (preferRunning) posture untouched;
 *   0b. normalized `handle.name` match — same latest-wins (the spawn regex bans whitespace, so
 *       normalization here is effectively NFKC+lowercase: "Builder"/"builder" share the name pool);
 *   1+. the pre-[c209] description layers, UNCHANGED (exact → normalized, running-preferred +
 *       ambiguous posture — TaskStop's anchored behavior does not regress).
 *  Matching key of the legacy layers = normalized description (the spawn label that IS the agent's
 *  name on this face). Running rows are preferred over terminal ones (CC `gvy`), so a re-used label
 *  addresses the live agent, while a lone terminal match still resolves. */
/** NOTE (server[1523] 对等复审 4b, recorded): the name pool scans LIVE handles only — durable-only
 *  rows (restart survivors) are deliberately NOT name-addressable through this rung (canonical-only
 *  裁决); tier-3 revival's name rung goes through the roster instead (design/151 §7.4). */
export declare function resolveBackgroundAgentByNameLane(core: DurableAgentCore, name: string, access: TaskAccess, opts?: {
    preferRunning?: boolean;
}): {
    status: "found";
    handle: BackgroundAgentTaskHandle;
} | {
    status: "ambiguous";
    message: string;
} | {
    status: "not_found";
    suggestion?: string;
};
/** S2b': flip the park-redeemability bit AFTER retention is actually secured
 *  (tryRetainChild success) — registration happens before the retain attempt, and session-scope
 *  alone does NOT retain the child session, so declaring at register time acknowledged parks that
 *  a capacity/pin failure (or plain session-scope) could never drain. No-op on unknown ids. */
export declare function markRetainedContinuationLane(core: DurableAgentCore, id: string): void;
/**
 * The stop-cycle generation of the RUN BEING SPAWNED under this row (the same counter the
 * register/revive lanes keep on the handle: fresh spawn = 1, durable-seeded revive = the claimed
 * row's seq, in-memory wake = the bump). The spawn lanes read it ONCE, right after registering, to
 * thread into the child's `RunInternals.cycleSeq` — one authoritative source instead of each lane
 * re-deriving the seed-vs-fresh arithmetic. `undefined` for an unknown id or a non-agent row.
 *
 * PARKED-BORN arm (falsification F1): a parked handle's counter still names the cycle that PARKED —
 * the run this spawn lane is about to drive begins at the consume flip, which installs the bumped
 * value (`flipped.seq = seq + 1`, the §7.2d consume write). Answering the pre-flip number made one
 * resumed run speak two generations (spawn/ticks at n, terminal at n+1), so the parked arm answers
 * the flip's target instead. A resume that loses the consume arbitration never runs, so the answer
 * is never attached to a live cycle it doesn't describe.
 */
export declare function backgroundAgentCycleSeqLane(core: DurableAgentCore, id: string): number | undefined;
/** S2b RB-27② — REVIVE a settled background-agent row for a retained-session RESUME cycle: the
 *  row flips back to "running" with a fresh "attaching" channel and a bumped revive-cycle stamp
 *  (returned; the resume leg threads it through attach and settle so a stale cycle's late calls
 *  can never clobber the new cycle's channel). Only terminal rows revive; running rows refuse
 *  (the SendMessage still_running path owns that story).
 *
 *  The DURABLE transition is a {@link claimTerminalRowForRevive} claim, awaited BEFORE the in-memory
 *  flip — the two orders are not equivalent: flipping memory first (the pre-arbitration shape, a plain lane
 *  write with no row guard) let a foreign claim win the row while this process kept serving
 *  `running`, and every later write of this cycle then died in the contaminated lane without a trace.
 *  Three lane shapes, three treatments:
 *   - NO lane (store-less registration): the pre-arbitration in-memory-only transition, unchanged — there is
 *     no row, hence no arbitration domain and no competitor;
 *   - lane whose initial put never CREATED a row: same — nothing exists for a foreign claim to have
 *     won, and the write lane keeps retrying the put. This is decided by the claim's own read INSIDE
 *     the chain (row absent AND the put still unconfirmed after the chain drained), never by the
 *     entry-time flag: a put merely in flight, or one that committed under a failed response, would
 *     otherwise exempt a row that does exist — the split-brain window this claim exists to close;
 *   - Contaminated lane (stale-flip ownership transfer / row reaped mid-write / heartbeat re-drive
 *     ceiling): the claim runs DIRECTLY through the store — the dead lane's chain is no longer a
 *     serialization point, the rev guard is. Re-arming that lane object in place is what is NOT
 *     done: an in-flight write from it would then see its own writerId on the re-claimed row and
 *     adopt it. It stays contaminated (its record keeps the pre-claim writerId/epoch, so its read-back
 *     answers "foreign" and it stops), and a row that cannot be claimed — gone, or live under
 *     another writer — REFUSES the revive rather than resuming with a durably unreachable row.
 *  A WON claim always hands the row to a FRESH lane for the claimed generation (both paths), for the
 *  reason spelled out at the handoff: a write appended while the claim was in flight speaks for the
 *  cycle that just ended and must not be applied under the new ownership.
 *  While the claim is in flight the handle holds the in-process claim window
 *  ({@link beginDurableClaimLane}'s mark), so a tier-3 claim, a reap sweep and a second revive of
 *  the same row all observe it and take their existing refusals. */
export declare function reviveBackgroundAgentLane(core: DurableAgentCore, id: string, access: TaskAccess, abort?: AbortController): Promise<{
    ok: true;
    cycle: number;
} | {
    ok: false;
    reason: "not_found" | "still_running" | "recycling";
}>;
/** S2b RB-27② — settle a REVIVED cycle (cycle-stamped: a stale cycle's late settle is a no-op so
 *  it can never flip a newer revived cycle back to terminal / clear its channel). */
export declare function settleRevivedAgentLane(core: DurableAgentCore, id: string, cycle: number, outcome: {
    status: "completed" | "failed" | "killed";
    result?: string;
    resultFull?: string;
    error?: string;
    errorCode?: string;
    retryable?: boolean;
    errorKind?: string;
    retryAfterMs?: number;
}): "completed" | "failed" | "killed" | undefined;
/**
 * design/164 — record LIVE ACTIVITY on a running background-agent row (one tool-lifecycle beat).
 *
 * Why this exists: retiring `SESSION_BG_DEFAULT_TIMEOUT_SEC` removed the wall-clock ceiling that used to
 * bound a session-scoped background child, and the design/129 F3 anti-zombie duty had to land somewhere
 * that does not punish a legitimately long task. Collecting by STALL needs a stall signal, and the
 * in-memory row had none: `updatedAt` moved only at registration / park / settle, so a child grinding
 * through a two-hour job looked exactly like one whose lane died. This is that signal — the same
 * tool-lifecycle beat the fleet view already samples, recorded on the row.
 *
 * Cheap and idempotent: a timestamp write on a running row, no-op for anything else.
 */
export declare function noteBackgroundAgentActivityLane(core: DurableAgentCore, id: string, now?: number): void;
/**
 * design/164 — collect SESSION-SCOPED background agents that have gone SILENT, the replacement for the
 * retired 30-minute wall-clock ceiling on that lane.
 *
 * By STALL, not by age, deliberately: the old ceiling killed a child at thirty minutes whether it was
 * wedged or working, and "this task has run a long time" is not evidence of anything. `staleMs` is the
 * caller's policy — there is no default here either, matching every other retention policy in this file
 * (`maxAgeMs` / `keep` / `staleRunningMaxAgeMs` are all caller-supplied). Size it well above the child's
 * expected quiet stretches; the durable twin's guidance (≥10× the heartbeat) is the reference point.
 *
 * A collected row is settled `killed` with attribution `"system"` and the SAME wording the durable
 * stale-running sweep writes, so an operator reading either face sees one explanation, and its run is
 * aborted. Returns how many rows were collected.
 */
export declare function reapStaleSessionBackgroundAgentsLane(core: DurableAgentCore, staleMs: number, now?: number, onTerminal?: (note: () => void) => void): number;
/** S2b — retention is REVOCABLE: every retain-ledger eviction path (TTL / LRU / abandon /
 *  parent-teardown disposeAll) runs the entry's release closure, and the spawner wraps that closure
 *  to call this — so a park can never be acknowledged against a continuation that was already
 *  released (the write-once bit was a lie window during parent teardown). */
export declare function unmarkRetainedContinuationLane(core: DurableAgentCore, id: string): void;
/** design/147 S2a — park a RUNNING child's live notification injector on its handle (called by the
 *  spawner once the child's lane binds). No-op for unknown / non-agent / already-terminal rows —
 *  the lane can outrace a fast child, and a stale attach must never resurrect a settled handle. */
export declare function attachAgentNotifyLane(core: DurableAgentCore, id: string, notify: NonNullable<BackgroundAgentTaskHandle["notify"]>, cycle?: number): void;
/** design/147 S2a — deliver a message TO a RUNNING background agent at its next turn boundary
 *  (CC's in-memory pendingMessages pedestal). Access-checked like every registry verb; returns a
 *  typed refusal instead of throwing so the SendMessage face can phrase honestly:
 *  `not_running` (row isn't running any more — race with settle; caller re-reads status) or
 *  `no_channel` (running but its lane never attached — e.g. a non-core spawner). */
export declare function deliverToRunningAgentLane(core: DurableAgentCore, id: string, access: TaskAccess, notification: import("./task-notification.js").TaskNotificationPayload, opts?: {
    priority?: import("./task-notification.js").SystemInjectionPriority;
}): Promise<{
    ok: true;
    disposition: "queued" | "parked" | "pending";
} | {
    ok: false;
    reason: "not_found" | "not_running" | "no_channel" | "queue_full";
}>;
/** CC `ugo`/`rxo` (206:575227-575243 = 220:467937-467951): `id (label)` rows for a not-found footer —
 *  running bg agents the CALLER can address (canAccess scopes; CC's self/observer exclusions have no
 *  counterpart rows here). This variant is the SENDMESSAGE footer's source and lists EVERY running
 *  agent, named or not: SendMessage addresses by name AND by id, so dropping named rows here (the way
 *  {@link runningAgentFooterLane} does for the task faces, per CC `rxo`'s `!n.has(i.id)`) would hide the
 *  very rows a retry needs. The task faces' split lives in `runningAgentFooterLane` (RB-332). */
export declare function runningBackgroundAgentLabelsLane(core: DurableAgentCore, access: TaskAccess): string[];
/**
 * The not-found FOOTER's two rows, split the way CC 220 assembles them:
 *  - `named`  = CC `uG_` (220:467941-467953): the agentNameRegistry's KEYS whose task is a running local
 *               agent, listed as BARE NAMES — the string a retry should pass verbatim. sema's counterpart
 *               of "has a registry entry" is the handle carrying an explicit `name` (spawn-time label),
 *               the same field TaskStop's name leg and SendMessage address by.
 *  - `background` = CC `rxo` (220:467937-467951): the remaining running background agents as `id (label)`
 *               rows. CC filters `!n.has(i.id)` — a NAMED agent is deliberately NOT repeated here, because
 *               its addressable form is the name, not the id. The pre-RB-332 sema code merged both legs
 *               into one list and justified it with "named has no counterpart", a claim [c209-D] retired
 *               when the explicit `name` field landed.
 * CC's `YEd` "Running teammates:" leg has no sema counterpart (no teammate registry on this face) and is
 * honestly absent rather than faked.
 */
export declare function runningAgentFooterLane(core: DurableAgentCore, access: TaskAccess): {
    named: string[];
    background: string[];
};
/** The not-found TAIL both task faces share (CC `rxo`, appended by `uMs` for TaskStop
 *  and by `xwd` 220:472095-472097 for TaskOutput). Empty string when the caller has nothing running. */
export declare function notFoundRunningAgentsTail(footer: {
    named: string[];
    background: string[];
}): string;
/** design/151 S1a (RB-425) — the SINGLE construction of a background-agent row's poll `details`. The
 *  live in-process poll ({@link pollBackgroundAgentLane}) and the cross-restart durable fallback
 *  ({@link serveDurableAgentRowLane}) must serve the IDENTICAL field set: that symmetry IS the S1a
 *  contract ("a consumer cannot tell a fallback read from a live one except by the row being older than
 *  the process"), and two hand-maintained object literals had already drifted — `error` was live-only,
 *  so a structured consumer lost the failure FACT at exactly the moment it could no longer reach the
 *  live handle, left to scrape the prose body's `error:` line.
 *
 *  The fact gates live here too (failed ⇒ error/errorCode/retryable/retryAfterMs; `stoppedBy` rides
 *  whenever the ROW carries it, on any status — a reaper-settled `failed` row keeps its attribution,
 *  see the widening note in the builder) rather than at the call sites: which facts a given row may
 *  carry is part of the same contract, and a gate copied per face is the same drift with extra steps. `error` is model/provider-influenceable text, so
 *  the fencing + bounding (RB-386②'s posture) happens once, here, for both faces.
 *  The parked projection is this builder with fewer facts, not a third literal. */
export interface AgentPollDetailsInput {
    taskId: string;
    status: UnifiedTaskOutput["status"];
    retrievalStatus: TaskRetrievalStatus;
    seq?: number;
    stoppedBy?: StopSource;
    error?: string;
    errorCode?: string;
    errorRetryable?: boolean;
    errorRetryAfterMs?: number;
    resultIsPartial?: boolean;
    completionId?: string;
    /** The agent's current state ({@link import("./agent-state.js").readAgentState}) — rides as
     *  `agentState` when given; the poll arms always give it, a serving layer may omit it. */
    agentState?: AgentState;
}
/** PUBLIC (see the doc above): a serving layer that renders its own protocol projection of a row
 *  builds the structured facts HERE, so the status gates and the untrusted-text fencing apply to it
 *  too — a third literal is exactly the drift this builder exists to prevent. Input only; it reads no
 *  store and authorizes nothing, so the caller must already have passed the row through
 *  {@link import("./background-agent-store.js").canAccessAgentRecord}. */
export declare function buildAgentPollDetails(input: AgentPollDetailsInput): UnifiedTaskOutput;
/** design/151 S1a — serve a TERMINAL durable row in the exact pollBackgroundAgent terminal shape
 *  (same body grammar, same details fields — {@link buildAgentPollDetails} is the shared source of
 *  the latter), so a consumer cannot tell a fallback read from a live one except by the row being
 *  older than the process.
 *
 *  PUBLIC: a serving layer answering for a row whose writing process is gone renders it through THIS,
 *  not through a hand-written projection that would drift from the live poll's. It takes a row the
 *  caller has ALREADY read and authorized — it reads no store and applies no predicate, so a
 *  deployment passes every row through
 *  {@link import("./background-agent-store.js").canAccessAgentRecord} before it gets here. */
export declare function serveDurableAgentRowLane(row: BackgroundAgentRecord, 
/** The row's current state ({@link import("./agent-state.js").readAgentState} over
 *  {@link import("./agent-state.js").agentStateSourceOfRecord}(row)): rendered as the `state:` line and
 *  carried as `details.agentState`. Absent ⇒ neither appears (a serving layer that does not read it). */
agentState?: AgentState): UnifiedTaskResult;
/**
 * design/158 S1 (RB-205-B 半) — spill the FULL text behind a CLIPPED background_agent result to the
 * offload store, and append a ref-disclosure so the middle `clipTaskOutput` drops is not gone for good.
 * `RegisterBackgroundAgentInput` deliberately carries no `outputFile` (ref-not-path is the design/158
 * §2.4 divergence — TOC/TOB compatible, unlike a local path), so this is the only pageback this lane
 * gets; it reuses the SAME vocabulary as the offload face (design/108: {@link OFFLOAD_TOOL_NAME},
 * {@link buildToolResultRef} — RB-273's single mint point) instead of inventing a parallel one.
 *
 * Lazy: only writes on the FIRST poll whose clip actually cut something (`clipped !== full`) — a short
 * result never touches the store, matching design/158 §2.1 ("spill is a fidelity layer, not a new
 * source of truth"). Idempotent PER REVIVE CYCLE: the ref folds in `handle.reviveCycle` (a revive clears
 * `handle.spillRef` — see {@link reviveBackgroundAgentLane} — but `handle.id` itself does NOT change
 * across a revive, so without the cycle in the ref, cycle 2's spill would mint the SAME ref string as
 * cycle 1's and the store's write-once contract would silently keep cycle 1's STALE text under a ref
 * now disclosed as cycle 2's current result). Caching the minted ref on the handle (rather than just
 * re-deriving+re-`put`ting every poll and trusting the store's own write-once no-op) keeps the disclosed
 * ref byte-stable across polls and avoids a redundant round-trip to a durable backend on every poll.
 *
 * No store configured (a deployment that never wired a `toolResultStore`) ⇒ returns `clipped` UNCHANGED
 * — the legal degrade design/158 §2.2 calls for, byte-identical to pre-S1 behavior.
 *
 * Backlog #169 — a FAILING `put` (throwing or rejecting; the store contract admits both dialects) is
 * NOT fatal to the poll: the clipped text is still served, with {@link AGENT_SPILL_FAILED_NOTE} in
 * place of the ref disclosure (advertising a ref nobody can read back would be a false promise), and
 * `handle.spillFailed` latches so later polls of the same cycle repeat the honest note instead of
 * retrying the write — see the catch below for why latch-not-retry. Same "store failure is never
 * fatal" posture as the monitor/offload/budget/compaction write sites. A put that settles AFTER a
 * revive (stale cycle) is generation-guarded: it answers its own caller honestly but never writes
 * spill state onto the new cycle (see `mintCycle` below).
 */
export declare function spillClippedAgentResult(handle: BackgroundAgentTaskHandle, full: string, clipped: string, store: ToolResultStore | undefined, sessionId: string | undefined): Promise<string>;
export declare function pollBackgroundAgentLane(handle: BackgroundAgentTaskHandle, deadline?: number, signal?: AbortSignal, 
/** Mirrors {@link import("./types.js").TaskSpec.oneShot} (see
 *  {@link import("./task-registry.js").TaskToolOptions.oneShot} for the full contract): this run has
 *  no later turn for an async background notification to land in, so the still-running body must
 *  not teach "you will be notified when it completes". */
oneShot?: boolean, 
/** design/158 S1 — the offload store a clipped result's full text spills to (see
 *  {@link spillClippedAgentResult}). Absent ⇒ legal degrade, byte-identical to pre-S1 output. */
store?: ToolResultStore, 
/** design/158 S1 — the caller's session id, folded into the minted ref for global uniqueness (same
 *  role `sessionId` plays at every other {@link buildToolResultRef} call site). */
sessionId?: string, 
/** The run's checkpoint seat — the store a parked row's approval card is read from
 *  ({@link import("./agent-state.js").readAgentState}). Absent ⇒ a parked row reads `approval unreadable`. */
checkpointSeat?: CheckpointSeat): Promise<UnifiedTaskResult>;
export declare function stopBackgroundAgentLane(core: DurableAgentCore, handle: BackgroundAgentTaskHandle): Promise<UnifiedTaskResult>;
