import type Database from 'better-sqlite3';
import type { BlameBlock, Plan, PlanAction, PlanChangedBy, PlanExecuteMode, PlanExecuteResult, PlanListItem, PlanVersion, PlanVersionMeta } from '../../shared/entities.js';
import type { WsGateway } from '../ws/gateway.js';
import type { ChatService } from './chat.js';
export interface PlanUpdateInput {
    threadId: string;
    action: PlanAction;
    content: string;
    anchor?: string;
    heading?: string;
    changeSummary?: string;
    changedBy: PlanChangedBy;
    actionParams?: Record<string, unknown>;
}
export interface PlanUpdateResult {
    plan: Plan;
    version: number;
}
export declare class PlanService {
    private db;
    private ws;
    private chat;
    constructor(db: Database.Database, ws: WsGateway, chat: ChatService);
    getByThread(threadId: string): Plan | null;
    getById(planId: number): Plan;
    threadCount(planId: number): number;
    listPlans(opts?: {
        limit?: number;
        offset?: number;
        search?: string;
    }): {
        plans: PlanListItem[];
        total: number;
    };
    attachThreadToPlan(planId: number): {
        threadId: string;
    };
    findLastThreadIdForPlan(planId: number): string | null;
    updatePlanTitle(planId: number, title: string | null): Plan;
    markPlanSeenByThread(threadId: string): void;
    /** Returns the `<system-reminder>` block to prepend to user message when plan is stale, or null. */
    getStalePlanReminder(threadId: string): string | null;
    update(input: PlanUpdateInput): PlanUpdateResult;
    listVersions(planId: number, opts?: {
        limit?: number;
        offset?: number;
    }): {
        versions: PlanVersionMeta[];
        total: number;
    };
    getVersion(planId: number, version: number): PlanVersion;
    blame(planId: number): BlameBlock[];
    execute(planId: number, mode: PlanExecuteMode, opts?: {
        threadId?: string;
    }): PlanExecuteResult;
    private hydrate;
    private hydrateVersion;
    private hydrateVersionMeta;
}
