import { type LiveAgent, type AgentMeta } from '../store/index.js';
import type { ProjectSummary, ProjectionRead } from './projects.js';
import { type AgentHandoff } from './agent-handoff.js';
import { type PrLister } from './gh.js';
export { interventionKey } from './keys.js';
/**
 * One item awaiting the human. Two kinds: an open `pr` to review/merge or close, and an
 * `awaiting` run paused on a choice gate. The card, the browser hook, and the Discord watcher
 * all iterate the flat list, branching on `kind` for the fields that differ.
 */
export interface Intervention {
    projectId: string;
    projectName: string;
    /**
     * `pr` = an open PR to review/merge or close; `awaiting` = an agent paused on a choice gate (#636);
     * `unpushed` = a finished agent whose branch has commits that were never pushed (#860).
     */
    kind: 'pr' | 'awaiting' | 'unpushed';
    title: string;
    /** Where to act: the PR on GitHub (`pr`), or the dashboard (the other two, when the URL is known). */
    url: string;
    /** The PR number (`pr` only). */
    number?: number;
    /** The parked gate's id (`awaiting` only) — its stable identity, so it notifies exactly once. */
    awaitId?: string;
    /** Which run this is about (`awaiting` #738 / `unpushed`): a project has several agents. */
    agentId?: string;
    /** The branch the work is sitting on (`unpushed` only). */
    branch?: string;
    /** How many commits are waiting (`unpushed` only). */
    commits?: number;
    /** When the PR was opened (`pr`) or the agent last updated (the other two), ISO, for ordering. */
    createdAt?: string;
}
/** Injectable seam so {@link buildInterventions} is unit-testable off disk. */
export interface InterventionsDeps {
    prs?: PrLister;
    /** The live-agent reader (default {@link readLiveMetas}); drives the `awaiting` source (#636). */
    liveAgents?: (cwd: string) => Promise<LiveAgent[]>;
    /** The finished-agent reader (default {@link listAgents}); drives the `unpushed` source (#860). */
    agents?: (cwd: string) => Promise<AgentMeta[]>;
    /** Reads a branch's state (default {@link readAgentHandoff}); drives the `unpushed` source (#860). */
    handoff?: (cwd: string, branch: string) => Promise<AgentHandoff | undefined>;
    /**
     * How many of a project's most recent finished agents to inspect for unpushed work. Each one costs
     * a handful of git reads, and this runs on a poll, so old history is not re-walked every minute:
     * work that has sat unpushed for dozens of agents is not news, and the agent list stays the record.
     */
    handoffLimit?: number;
    /**
     * The dashboard's own URL, so an `awaiting` item can link back to it. Only the daemon knows
     * it (the card path resolves the project client-side and needs no URL), so it is optional; an
     * awaiting item's `url` is empty when it is unset.
     */
    dashboardUrl?: string;
}
/**
 * Build the cross-project interventions queue: every registered project's open PRs, plus any run
 * currently paused on a choice gate (#636), newest first. Forgiving — a project with no remote
 * (or an unreadable one) simply contributes nothing. Hand-opened draft PRs are excluded: they are
 * not yet asking for review. A session's own draft is not (#1102), because that is how
 * auto-handoff hands work back.
 *
 * Which projects were read whole comes back alongside the items (#1623): forgiveness here is what
 * lets one unreachable project keep the queue useful, and it is also what would let that project's
 * whole backlog announce itself as new the moment it came back. The queue's panels ignore this;
 * the notification watcher is the caller that cannot.
 */
export declare function buildInterventions(projects: ProjectSummary[], deps?: InterventionsDeps): Promise<ProjectionRead<Intervention>>;
/**
 * How one intervention reads on Discord. Beside {@link Intervention} rather than inside the
 * watcher that posts it: it switches on every `kind`, so adding a kind is a change here, not in
 * a transport module that has no other opinion about what an intervention is.
 *
 * A PR reads `#123 Title — url`; a paused agent (#636) has no number and only the dashboard url,
 * so it reads `Title — awaiting your answer` with the link appended when the daemon knows it.
 * Unpushed work (#860) names the branch, since that is the actionable part.
 */
export declare function interventionLine(item: Intervention): string;
/**
 * Post the given interventions to a Discord webhook as one message, resolving whether Discord
 * accepted it (#940). `fetch` is injectable for tests.
 */
export declare function postInterventionsDiscord(webhook: string, items: Intervention[], fetchImpl?: typeof fetch): Promise<boolean>;
//# sourceMappingURL=interventions.d.ts.map