/** * Ticket autopilot settings (specs/2026-09-30-ticket-autopilot.md §2). * * Stored on the project record (`Project.ticketAutopilot` in projects.json). * Absent = off. Only the owner or the orchestrator changes it. * * @module types/ticket-autopilot.types */ import { TICKET_AUTOPILOT_CONSTANTS } from '../constants.js'; /** Autopilot speed (specs/2026-10-04-autopilot-speed-modes.md). */ export type AutopilotSpeedMode = 'rush' | 'normal' | 'chill'; /** What a speed mode supplies (see TICKET_AUTOPILOT_CONSTANTS.SPEED_MODES). */ export type AutopilotSpeedProfile = (typeof TICKET_AUTOPILOT_CONSTANTS.SPEED_MODES)[AutopilotSpeedMode]; /** * Whether a value is a speed mode name. * * @param value - Anything * @returns True for rush / normal / chill */ export declare function isAutopilotSpeedMode(value: unknown): value is AutopilotSpeedMode; /** * The profile of a speed mode. * * @param mode - Mode * @returns Its replan gap / cap, self-review cadence, empty-replan retry and default budget */ export declare function speedProfile(mode: AutopilotSpeedMode): AutopilotSpeedProfile; /** The per-project switch as stored. Every field but `enabled` is optional. */ export interface TicketAutopilotSettings { /** Master switch (default off) */ enabled: boolean; /** Session that triages; absent = the lead of the project's team */ driver?: string; /** * Daily tokens (input incl. cached + output) of the project's team agents * since local midnight at which the autopilot pauses for the rest of the * day. Absent = the default * ({@link TICKET_AUTOPILOT_CONSTANTS.DEFAULT_DAILY_BUDGET_TOKENS}). A usage * boost on the project's teams raises it for the day. */ dailyBudgetTokens?: number; /** * Pre-token budget in USD. Read only to migrate it: converted with * {@link USAGE_CONSTANTS.TOKENS_PER_USD} (see {@link legacyBudgetTokens}). * @deprecated */ dailyBudgetUsd?: number; /** In-progress tickets one member may hold at a time (default 1) */ maxInFlightPerMember?: number; /** * Daily retro for the driver (specs/2026-10-03-autopilot-experiments.md §4). * Absent = on while an autopilot experiment on the project is running. */ retro?: boolean; /** * Goal replans per local day (specs/2026-10-04-autopilot-goal-replan.md): * a hard cap on how often the driver may be woken to plan the next tickets * toward the project's goal when nothing is left to triage. 0 = off. * Absent = the speed mode's daily cap. */ replansPerDay?: number; /** * Speed mode (specs/2026-10-04-autopilot-speed-modes.md): replan gap and * daily cap, self-review cadence, retry after an empty replan, and the * budget when none is set. Absent = normal. */ speedMode?: AutopilotSpeedMode; /** * Hours a goal replan may stay live before it is expired (cancelled where * possible, never counted as live again). Absent = the default * ({@link TICKET_AUTOPILOT_CONSTANTS.DEFAULT_REPLAN_TTL_HOURS}). */ replanTtlHours?: number; /** * Labels that keep a ticket out of triage (a parked / deferred backlog). * Absent = {@link TICKET_AUTOPILOT_CONSTANTS.DEFAULT_SKIP_LABELS}; `[]` = skip nothing. */ skipLabels?: string[]; } /** Settings with every default filled in. */ export interface ResolvedTicketAutopilotSettings { enabled: boolean; /** The configured driver, or null (= the project team's lead) */ driver: string | null; dailyBudgetTokens: number; maxInFlightPerMember: number; /** The retro switch as set (null = the default: on while an autopilot experiment runs) */ retro: boolean | null; /** Goal replans allowed per local day (0 = off): the explicit setting, else the mode's cap */ replansPerDay: number; /** Hours a goal replan may stay live */ replanTtlHours: number; /** Labels that keep a ticket out of triage (lower-case) */ skipLabels: string[]; /** Speed mode (normal when never set) */ speedMode: AutopilotSpeedMode; /** Where the budget comes from: the project's own setting, or the mode's default */ budgetSource: 'explicit' | 'mode'; /** Where the daily replan cap comes from: the project's own setting, or the mode */ replansPerDaySource: 'explicit' | 'mode'; /** A replan never starts sooner than this after the last one (ms) */ replanMinGapMs: number; /** Cadence of the driver's self-review (ms) */ selfReviewEveryMs: number; /** After a replan that opened no tickets: retry after this many hours, or this many days later */ emptyReplanRetry: { unit: 'hours' | 'days'; amount: number; }; } /** A change request for the settings (API / skill body). */ export interface TicketAutopilotSettingsInput { enabled?: unknown; /** A session name; `null` or `''` resets to the team lead */ driver?: unknown; /** Tokens: a positive number or text like "20M"; `null` resets to the default */ dailyBudgetTokens?: unknown; /** Rejected: budgets are in tokens now */ dailyBudgetUsd?: unknown; /** An integer 1..limit; `null` resets to the default */ maxInFlightPerMember?: unknown; /** `true` / `false` (also "on" / "off"); `null` or "default" resets to the default */ retro?: unknown; /** An integer 0..limit (0 = no goal replans); `null` resets to the default */ replansPerDay?: unknown; /** An integer 1..limit (hours); `null` resets to the default */ replanTtlHours?: unknown; /** rush / normal / chill; `null` or "default" resets to normal */ speedMode?: unknown; /** A list of labels (or a comma-separated string); `null` / "default" resets to parked, deferred; `[]` skips nothing */ skipLabels?: unknown; } /** Outcome of {@link applyTicketAutopilotInput}. */ export type TicketAutopilotInputResult = { ok: true; settings: TicketAutopilotSettings; } | { ok: false; error: string; }; /** * Fill in the defaults of stored (possibly absent) settings. * * @param stored - `Project.ticketAutopilot` (may be undefined or partial) * @returns Settings with defaults */ /** * The token budget a stored pre-token USD budget converts to, or null. * * @param stored - Stored settings * @returns Tokens (USD × TOKENS_PER_USD), or null when there is no USD budget */ export declare function legacyBudgetTokens(stored: Partial | undefined | null): number | null; export declare function resolveTicketAutopilotSettings(stored: Partial | undefined | null): ResolvedTicketAutopilotSettings; /** * Apply a change request to the stored settings, validating every field. * Fields not present in the input are kept; `null` resets a field to its * default (removes it from the stored object). * * @param current - Stored settings (may be absent) * @param input - Requested changes * @returns The new stored settings, or a validation error * * @example * ```typescript * applyTicketAutopilotInput(undefined, { enabled: true, dailyBudgetTokens: '10M' }); * // → { ok: true, settings: { enabled: true, dailyBudgetTokens: 10000000 } } * ``` */ export declare function applyTicketAutopilotInput(current: Partial | undefined | null, input: TicketAutopilotSettingsInput): TicketAutopilotInputResult; //# sourceMappingURL=ticket-autopilot.types.d.ts.map