import { type GitRunner } from './project.js';
/**
 * Turn a plan's own verdict into queued work (#1334).
 *
 * The missing link in the autonomy chain. Tickets arrive from GitHub, [Spike & plan] costs them,
 * and the drain implements whatever is on the queue -- but nothing carried a plan's conclusion
 * onto that queue, so a ticket the planner had already judged trivial still waited for a triage
 * run to read the same ticket and reach the same conclusion a second time.
 *
 * The promotion is done here rather than by an agent because it is a decision the plan has
 * already made: reading two keys out of a file and appending a line needs judgement from nobody,
 * and spending a subscription turn to re-derive an answer already written down is the waste #879
 * exists to avoid. It is the daemon that writes, for the reason queue-promote.ts gives: agents
 * stay sandboxed in their worktrees with no write access to the checkout.
 */
/** How much work the plan says the ticket is. */
export type PlanEffort = 'quick-win' | 'significant';
/** Whether the plan says there is anything left to decide. */
export type PlanConsensus = 'consensual' | 'open-questions';
/** The two keys a plan records about itself, absent when the plan did not say. */
export interface PlanVerdict {
    effort?: PlanEffort;
    consensus?: PlanConsensus;
}
/**
 * Read a plan file's verdict keys.
 *
 * Only the header is scanned -- everything above the first `##` section -- because that is where
 * the ticket format puts its keys, and because a plan that *discusses* quick wins in its prose
 * must not be read as declaring itself one.
 */
export declare function parsePlanVerdict(md: string): PlanVerdict;
/**
 * Whether a plan authorises the drain to implement its ticket unattended.
 *
 * Fails closed, and demands both keys explicitly: the same polarity as `quotaHeadroom` (#879),
 * for the same reason. A plan that forgot to say, or said something this version does not
 * recognise, means a human decides -- not that an agent starts.
 */
export declare function isAutoImplementable(verdict: PlanVerdict): boolean;
/** `tickets/<slug>.plan.md` for `tickets/<slug>.md`, and the read back. */
export declare function planPathFor(ticket: string): string;
/** The ticket a plan belongs to, or undefined for a file that is not one. */
export declare function ticketForPlan(plan: string): string | undefined;
/** A ticket's `Status:`/`Priority:`/title, as the queue needs them. */
export interface TicketHeader {
    title: string;
    priority: number;
    open: boolean;
}
/**
 * Read a ticket's header. Keys sit above the `# Title`, per the ticket format.
 *
 * A ticket with no `Status:` counts as open: the key is what a *closed* ticket is marked with,
 * and treating an unmarked one as closed would silently drop it out of the roadmap.
 */
export declare function parseTicketHeader(md: string): TicketHeader;
/** The queue line for a planned ticket: the link, and nothing else. */
export declare function queueEntryFor(ticket: string, title: string): string;
/**
 * Add an entry under its priority heading, creating the section when the file has none.
 *
 * Placement is the whole point rather than a nicety: `parseTodoEntries` returns entries in file
 * order and the drain takes the first, so an entry appended to the end of the file is the last
 * thing that would ever be worked -- which is the opposite of what "autonomously work on
 * quick-wins" asks for. Additive like `landPinnedEntry`, so it composes with whatever else is
 * mid-flight: it only ever inserts one line.
 */
export declare function insertQueueEntry(md: string, entry: string, priority: number): string;
/** Everything the promotion reads and writes, injected so the policy above tests off disk. */
export interface PlanPromoteDeps {
    list?: (dir: string) => Promise<string[]>;
    read?: (path: string) => Promise<string>;
    write?: (path: string, content: string) => Promise<void>;
    git?: GitRunner;
}
/** What one promotion pass did. Never throws: this runs on a background tick. */
export interface PlanPromotion {
    /** The entries appended, in the order they were added. */
    queued: string[];
    /** Why nothing was queued, when nothing was. */
    reason?: string;
    /**
     * Something stood in the way, as opposed to there simply being nothing to promote.
     *
     * The distinction is what keeps the daemon log readable: "no plan called its ticket a quick-win"
     * is the ordinary state of a healthy repo and would otherwise print on every tick of every
     * project forever, burying the one line that means a human should look.
     */
    blocked?: true;
}
/** The commit message a promotion writes, naming the count so the history reads at a glance. */
export declare function plannedQueueMessage(count: number): string;
/**
 * Queue every ticket whose plan declares itself a consensual quick-win and that is not on the
 * queue already (#1334).
 *
 * Skips wholesale on a dirty queue file, for the same reason `promoteQueue` does: a human editing
 * the queue by hand outranks an unattended tidy-up, and the next tick will try again.
 */
export declare function promotePlannedQuickWins(projectCwd: string, deps?: PlanPromoteDeps): Promise<PlanPromotion>;
//# sourceMappingURL=planned-quick-wins.d.ts.map