/** Hard caps. Goals are user-typed prose; tight limits keep prompt
 *  injection from blowing the context window on a single thread. */
export declare const MAX_TITLE_CHARS = 200;
export declare const MAX_BODY_CHARS = 4000;
export declare const MAX_PROGRESS_NOTE_CHARS = 500;
export declare const MAX_PROGRESS_NOTES_INJECTED = 5;
/** Goal lifecycle states.
 *  - active: counted as the thread's current goal; injected into prompts
 *  - paused: kept around but NOT injected (operator wants a break)
 *  - completed / cancelled: historical only */
export type GoalStatus = 'active' | 'paused' | 'completed' | 'cancelled';
export interface ProgressNote {
    ts: string;
    by: string;
    text: string;
}
export interface GoalRow {
    id: number;
    platform: string;
    channelId: string;
    threadId: string;
    userId: string;
    title: string;
    body: string;
    status: GoalStatus;
    /** Newest-last array (push on progress; render reversed for "most recent first"). */
    progressLog: ProgressNote[];
    createdAt: string;
    updatedAt: string;
    /** ISO timestamp of completion / cancellation, when applicable. */
    closedAt: string | null;
}
/**
 * Set (or replace) the ACTIVE goal for a thread. Idempotent semantics:
 * if there's already an active goal, it's auto-paused first (kept in
 * the table) and a fresh row replaces it. This avoids accidental
 * silent drops of partially-tracked work — the operator can /goal
 * list to find paused predecessors and /goal resume <id> if they
 * changed their mind.
 */
export declare function setActiveGoal(input: {
    platform: string;
    channelId: string;
    threadId: string;
    userId: string;
    title: string;
    body?: string;
}): GoalRow | null;
/** Append a progress note to a goal. Caller picks `by` (typically
 *  'user' for /goal progress, 'agent' for future MCP tool call,
 *  'system' for status transitions). */
export declare function appendProgress(goalId: number, by: ProgressNote['by'], text: string): boolean;
export declare function updateStatus(goalId: number, status: GoalStatus): boolean;
/** Resume a paused goal — also auto-pauses any currently-active goal
 *  in the same thread so there's never more than one active. */
export declare function resumeGoal(goalId: number): boolean;
export declare function getGoalById(id: number): GoalRow | null;
/** The single active goal for a thread (or null if none). */
export declare function getActiveGoal(platform: string, channelId: string, threadId: string): GoalRow | null;
/** Cheap boolean form of getActiveGoal — same query but returns only a
 *  flag. Used by the wall-timeout extension path (v1.2.86) where the
 *  caller just needs to know "should we be generous about timeouts on
 *  this thread". Safe to call from hot paths; same fail-soft semantics
 *  as getActiveGoal (db unavailable → false). */
export declare function hasActiveGoal(platform: string, channelId: string, threadId: string): boolean;
/** v1.2.86 — when an active goal exists on the addressed thread, the
 *  caller may legitimately need much longer to finish (research/coding
 *  marathons). Multiply the base timeout by IMHUB_GOAL_ACTIVE_TIMEOUT_MULTIPLIER
 *  (default 3×). Returns `base` unchanged when no thread context, no
 *  active goal, or db unavailable.
 *
 *  Hard cap: 6 h. Even with goals, a runaway loop should not pin a
 *  worker indefinitely.
 */
export declare function applyGoalTimeoutBoost(base: number, ctx?: {
    platform?: string;
    channelId?: string;
    threadId?: string;
}): number;
/** All goals (any status) for a thread, newest first. Used by /goal list. */
export declare function listGoalsForThread(platform: string, channelId: string, threadId: string, limit?: number): GoalRow[];
/** Admin / debug — every active goal across the install. */
export declare function listAllActiveGoals(): GoalRow[];
/**
 * Build the per-turn prompt-prefix snippet for the active goal. Bounded
 * to ~MAX_PROGRESS_NOTES_INJECTED recent notes + truncated body so a
 * verbose goal doesn't dominate the prompt budget. Empty string when no
 * active goal — router treats falsy snippets as "skip this block".
 *
 * The snippet is OVER THE WIRE only — it's prepended to the prompt the
 * agent sees but NOT stored in session history, so it doesn't bloat the
 * persisted conversation.
 */
export declare function buildGoalSnippet(platform: string, channelId: string, threadId: string): string;
/** For /goal show — render an operator-facing summary including ALL
 *  retained progress notes (capped at MAX_PROGRESS_NOTES_LISTED so the
 *  IM bubble doesn't explode). */
export declare function formatGoalShow(goal: GoalRow): string;
/** Test-only. Drops everything; safe to call repeatedly in beforeEach. */
export declare function _truncateForTests(): void;
//# sourceMappingURL=goals.d.ts.map