/** One issue waiting its turn, and what has been done about it so far. */ export interface QueueItem { /** The six-digit issue id. */ issue: string; /** * Which coding tools work it, in the order they take their turns, chosen when * it was queued. * * A list rather than one name because the picker is a selector: naming two * says they consult, and consulting is turns rather than a committee. The * first drafts, the second reviews what it finds and revises, and so on round * the list for as many turns as the issue's attempts allow. */ tools: string[]; /** * Whose turn is next, as an index into `tools` modulo its length. * * Absent means the first. It advances only when an attempt has actually been * spent, which is the same evidence a second handoff already waited for, so a * queue watching an unchanged board never rotates. */ turn?: number; queuedAt: string; /** * When a Terminal was actually opened for it. * * Absent means it is still waiting; present means the handoff happened and * what the queue is waiting for now is lookout's own ruling. */ handedOffAt?: string; /** * The issue's spent-attempt count at the moment it was handed off. * * This is what makes a second handoff safe: one only happens once * `verify-fix` has actually charged an attempt and come back still-open, so * a queue watching an unchanged board never opens a second window. */ handedOffAtAttempt?: number; /** Durable claim written before an external handoff is invoked. */ dispatching?: { token: string; pid: number; at: string; }; /** * When a handoff was attempted and could not happen, and why. * * Terminal until somebody acts on it. Without it the head would match the * "not handed off yet" case again on the next tick, and since saving the * reason is itself a write into a watched directory, that is an unbounded * loop rather than a retry. */ failedAt?: string; lastReason?: string; } /** * The tools a press asked for, as a list the queue can hold. * * The page sends what its selector has on; this decides what that means. An * unknown key is dropped rather than refused, because a page from a newer * build naming a tool this server has never heard of should still queue the * issue with the ones it does know. Nothing selected, or nothing recognised, * falls back to the one tool every install has a mark for, which is what the * older single-choice payload always meant. */ export declare function queuedTools(body: { tool?: string; tools?: unknown; }): string[]; export declare function queuePath(projectDir: string): string; /** The file's mtime, or 0 when there is no file. What a reload is decided on. */ export declare function queueMtime(projectDir: string): number; export declare function loadQueue(projectDir: string): Promise; export declare function saveQueue(projectDir: string, items: QueueItem[]): Promise; /** Apply one queue intent to the latest on-disk value. */ export declare function updateQueue(projectDir: string, mutate: (items: QueueItem[]) => T | Promise, opts?: { initial?: readonly QueueItem[]; save?: (result: T) => boolean; }): Promise<{ items: QueueItem[]; result: T; }>; /** What is written to disk, for deciding whether writing is worth doing. */ export declare function queueDigest(items: QueueItem[]): string;