import { type CampaignStatus, type RunRecord, type TaskRecord } from "./types.js"; export type TaskAdviceEvidence = { readonly status: "none"; } | { readonly status: "valid"; readonly recommendation: "short" | "long"; } | { readonly status: "invalid"; readonly reason: string; }; /** * Journal-derived facts used by the pure classifier. The campaign composition, * not a model or MCP caller, builds this evidence from exact parsers. */ export interface TaskProgressEvidence { readonly advice: TaskAdviceEvidence; readonly launch_binding_valid: boolean; readonly launch_activation_valid: boolean; readonly pending_result_valid: boolean; readonly terminal_evidence_valid: boolean; readonly github_cancellation_terminal_valid: boolean; readonly github_cancellation_pending: false | "source_removed" | "source_changed" | "invalid"; } export type TaskProgress = "done" | "blocked" | "pending_result" | "needs_advice" | "ready_to_launch" | "activation_pending" | "worker_in_flight" | "cancellation_pending" | "quota_parked" | "recovery_pending" | "exhausted" | "invalid"; export interface TaskProgressView { readonly task: TaskRecord; readonly progress: TaskProgress; readonly lane?: "short" | "long"; readonly reason?: string; } export type CampaignProgressDecision = { readonly type: "no_campaign"; } | { readonly type: "terminal"; readonly status: Exclude; } | { readonly type: "wait"; readonly reason: "stop_in_progress" | "worker_in_flight" | "role_in_flight" | "quota_parked" | "recovery_pending" | "no_runnable_task"; } | { readonly type: "needs_human"; readonly run_id: string; readonly run_version: number; readonly reason: string; readonly persisted: boolean; } | { readonly type: "expire_deadline"; readonly run_id: string; readonly run_version: number; } | { readonly type: "ensure_single_goal_task"; readonly run_id: string; readonly run_version: number; readonly goal_digest: string; } | { readonly type: "process_result"; readonly run_id: string; readonly run_version: number; readonly task_id: string; readonly task_version: number; readonly source_digest: string; } | { readonly type: "cancel_worker"; readonly run_id: string; readonly run_version: number; readonly task_id: string; readonly task_version: number; readonly reason: "source_removed" | "source_changed"; } | { readonly type: "request_advice"; readonly run_id: string; readonly run_version: number; readonly task_id: string; readonly task_version: number; readonly source_digest: string; } | { readonly type: "launch_worker"; readonly run_id: string; readonly run_version: number; readonly task_id: string; readonly task_version: number; readonly source_digest: string; readonly lane: "short" | "long"; } | { readonly type: "complete_campaign"; readonly run_id: string; readonly run_version: number; readonly status: "completed" | "blocked"; }; /** * Closed, mutually exclusive task classification. Exact journal validation is * represented by evidence booleans so this function remains dependency-neutral * and exhaustive-testable. */ export declare function classifyTaskProgress(input: { readonly expectedRunId: string; readonly task: TaskRecord; readonly evidence: TaskProgressEvidence; }): TaskProgressView; /** * Pure campaign routing. No adapter calls and no mutation. */ export declare function decideCampaignProgress(input: { readonly nowIso: string; readonly run: RunRecord | null; readonly tasks: readonly TaskProgressView[]; }): CampaignProgressDecision; /** * Monitor loop decisions are fixed probes only — never routing judgment. * Skills/conductor choose tickets; this module only reports timer due state. */ export type MonitorLoopAction = { readonly type: "heartbeat"; } | { readonly type: "pane_health"; } | { readonly type: "github_poll"; } | { readonly type: "deadline_check"; } | { readonly type: "idle"; readonly sleep_ms: number; }; export declare function decideMonitorActions(input: { readonly nowIso: string; readonly run: RunRecord | null; readonly nextGithubPollAt: string | null; readonly nextPaneHealthAt: string | null; readonly leaseExpiresAt: string | null; }): readonly MonitorLoopAction[]; /** * Queue-empty completion: no runnable/working/parked tasks and two consecutive * successful empty polls after the last queue-affecting transition. */ export declare function evaluateQueueCompletion(input: { readonly workSource: RunRecord["work_source"]; readonly tasks: readonly TaskRecord[]; readonly emptyPollStreak: number; readonly lastPollWasSuccessfulEmpty: boolean; }): "continue" | "completed" | "blocked"; export declare function nextEmptyPollStreak(current: number, successfulEmpty: boolean): number;