/** Release-readiness DTOs. No extension runtime or filesystem dependencies. */ import type { RpcObservationScope } from "./subagent-rpc.ts"; export type { RpcObservationScope } from "./subagent-rpc.ts"; export declare const RELEASE_READINESS_EVENT = "release:readiness:v1"; export type ReleaseReadinessCommand = { type: "release_readiness"; id?: string; version: 1; }; export type ReleaseBlockerSource = "core" | "subagents" | "intercom" | "scheduler" | (string & {}); export interface ReleaseBlocker { source: ReleaseBlockerSource; /** Short stable machine token, e.g. streaming, compacting, retrying, queued_messages, pending_tool_calls, pending_bash, * extension_dialog, compaction_prompt_queue, async_run, foreground_run, undelivered_result, inbound_ask, outbound_ask, * armed_schedule, releasing, contributor_error. */ kind: string; id?: string; detail: string; /** Epoch milliseconds when the blocking condition began (or, for armed schedules, is next due). */ since?: number; } export interface ReleaseReadiness extends RpcObservationScope { /** True only when `blockers` is empty. A false negative here means lost work, so uncertainty is reported as a blocker. */ safe: boolean; blockers: ReleaseBlocker[]; /** Extension contributors that answered. `safe` with an empty list means nobody reported. */ contributors: string[]; } export type ReleaseReadinessResponse = { id?: string; type: "response"; command: "release_readiness"; success: true; data: ReleaseReadiness; }; /** Atomic "release if safe": see `decideRelease`. Validated exactly like `release_readiness`. */ export type ReleaseCommand = { type: "release"; id?: string; version: 1; }; export interface ReleaseResult { /** True only when the process committed to a gentle exit (exit code 0, no abort). False: it keeps running normally. */ released: boolean; /** The readiness the decision was based on; when `released` is false it lists what blocked the release. */ readiness: ReleaseReadiness; } export type ReleaseResponse = { id?: string; type: "response"; command: "release"; success: true; data: ReleaseResult; }; /** * Core blocker kind reported by `release_readiness` once a `release` has been committed (the process is about to exit). * `kind` is `releasing`. */ export declare const RELEASING_BLOCKER_KIND = "releasing"; /** * Whether a readiness answer permits an immediate release. "Nobody answered" (`contributors` empty, e.g. extensions not * loaded) is NOT safe: the process cannot prove that no background work exists. */ export declare function decideRelease(readiness: Pick): boolean; /** * Synchronous broadcast on the session EventBus. Every listener calls `contribute` before `emit` returns. * Listeners MUST ignore requests whose `sessionId` is not the session they are bound to. */ export interface ReleaseReadinessRequest { version: 1; sessionId: string; contribute(name: string, blockers: ReleaseBlocker[]): void; } /** * Listener-side helper: gate on session identity, compute blockers, and fail closed. * The EventBus swallows listener exceptions, so a contributor that throws would otherwise look like "not loaded" * and the host would report safe. Always answer through this helper (or reproduce its try/catch). */ export declare function answerReleaseReadiness(raw: unknown, name: string, boundSessionId: string | null | undefined, compute: () => ReleaseBlocker[]): void; /** Bounded shape check for blockers received from trusted-but-fallible extension contributors. */ export declare function isReleaseBlocker(v: unknown): v is ReleaseBlocker; export declare const STOP_ALL_BACKGROUND_EVENT = "release:stop-all:v1"; /** Total budget for one `stop_all_background`: core abort plus every extension's (possibly asynchronous) stop. */ export declare const STOP_ALL_BACKGROUND_TIMEOUT_MS = 5000; /** * Destructive: aborts the turn and stops every background run, session-only schedule and outbound ask of this session. * Validated exactly like `release_readiness` and `release`; refused while a `release` is committed. */ export type StopAllBackgroundCommand = { type: "stop_all_background"; id?: string; version: 1; }; export interface StopAllBackgroundItem { source: ReleaseBlockerSource; /** Short stable machine token, e.g. turn, retry, compaction, bash, queued_messages, async_run, foreground_run, schedule, outbound_ask, inbound_ask, contributor. */ kind: string; id?: string; detail: string; /** True when the thing is no longer running/armed/pending. False: it could not be stopped (see `error`). */ ok: boolean; error?: string; } export interface StopAllBackgroundResult extends RpcObservationScope { /** Everything that was running, armed or pending when the command arrived, with the outcome of each stop. Empty on an idle session. */ stopped: StopAllBackgroundItem[]; /** Readiness computed AFTER the stop: what is still running or pending (also lists things that cannot be stopped). */ remaining: ReleaseReadiness; } export type StopAllBackgroundResponse = { id?: string; type: "response"; command: "stop_all_background"; success: true; data: StopAllBackgroundResult; }; /** * Synchronous broadcast on the session EventBus, like `ReleaseReadinessRequest`. Every listener calls `contribute` before * `emit` returns; the stop itself should start synchronously. A contributor that needs to wait (e.g. for a runner to * acknowledge) passes a promise and must settle by `deadline` (epoch ms) with its still-pending items as `ok:false, error:"timeout"`. * Listeners MUST ignore requests whose `sessionId` is not the session they are bound to. */ export interface StopAllBackgroundRequest { version: 1; sessionId: string; deadline: number; contribute(name: string, items: StopAllBackgroundItem[] | PromiseLike): void; } /** * Listener-side helper: gate on session identity and fail closed. A synchronous throw becomes an `ok:false` item, so one * extension failing never prevents the others from stopping (the bridge also converts a rejected promise). */ export declare function answerStopAllBackground(raw: unknown, name: string, boundSessionId: string | null | undefined, compute: (request: Pick) => StopAllBackgroundItem[] | PromiseLike): void; /** The item every failure path uses, so a broken contributor is visible instead of silent. */ export declare function stopAllContributorError(source: string, error: unknown): StopAllBackgroundItem; /** Bounded shape check for items received from trusted-but-fallible extension contributors. */ export declare function isStopAllBackgroundItem(v: unknown): v is StopAllBackgroundItem;