import type { SessionManager, SessionInfo } from "./session-manager.js";
import type { RoleStore, Role } from "./role-store.js";
import type { ToolManager } from "./tool-manager.js";
import type { ColorStore } from "./color-store.js";
import type { GateStore } from "./gate-store.js";
import type { VerificationHarness } from "./verification-harness.js";
import type { ProjectContextManager } from "./project-context-manager.js";
/**
 * Build a markdown list of available roles (excluding team-lead and assistant)
 * for injection into the team lead prompt via {{AVAILABLE_ROLES}}.
 * Accepts anything with a getAll() method (RoleStore or RoleManager).
 */
export declare function buildAvailableRolesList(roleSource?: {
    getAll?: () => Role[];
    listRoles?: () => Role[];
}): string;
export declare class GateDependencyError extends Error {
    constructor(message: string);
}
/**
 * Format elapsed time since a timestamp as a human-readable string.
 * Exported for testing.
 */
export declare function formatElapsed(sinceMs: number): string;
import { TaskManager } from "./task-manager.js";
export interface TeamAgent {
    sessionId: string;
    role: string;
    /**
     * Distinguishes verification reviewer sessions (managed by VerificationHarness)
     * from regular worker agents spawned via spawnRole. Reviewer agents must NOT
     * fire team-lead nudges on agent_end — the harness manages their lifecycle.
     * Defaults to "worker" if missing on load.
     */
    kind: "worker" | "reviewer";
    worktreePath?: string;
    branch?: string;
    baseSha?: string;
    task: string;
    createdAt: number;
    /** Unsubscribe from the agent_end event listener (cleanup on dismiss). */
    unsubscribeEvent?: () => void;
}
export interface TeamAgentInfo {
    sessionId: string;
    role: string;
    status: string;
    worktreePath?: string;
    branch?: string;
    task: string;
    createdAt: number;
}
export interface TeamState {
    goalId: string;
    teamLeadSessionId: string | null;
    agents: TeamAgentInfo[];
    maxConcurrent: number;
}
/**
 * Manages team goal lifecycles — team lead sessions and role agent sessions
 * with isolated git worktrees.
 */
export interface TeamManagerConfig {
    /** Color store for assigning unique palette indices to team sessions */
    colorStore: ColorStore;
    /** Task manager for looking up tasks assigned to sessions */
    taskManager: TaskManager;
    /** Role store for looking up role definitions (prompts, accessories, tools) */
    roleStore?: RoleStore;
    /** @deprecated Gate store — resolve per-goal via projectContextManager instead. */
    gateStore?: GateStore;
    /** Broadcast a WS event to all clients viewing a goal */
    broadcastToGoal?: (goalId: string, event: any) => void;
    /** Project context manager for per-project store resolution */
    projectContextManager?: ProjectContextManager;
    /** Tool manager for resolving extension paths via the cascade */
    toolManager?: ToolManager;
}
export declare class TeamManager {
    private sessionManager;
    private config;
    private taskManager;
    private teams;
    /** Local team store — used only in the non-PCM (test) path. */
    private localStore;
    /** Local GoalManager — used only in the non-PCM (test) path. */
    private _localGoalManager;
    /** Timers for the idle-nudge mechanism (goalId → timer). One-shot setTimeouts that reschedule with exponential backoff. */
    private idleNudgeTimers;
    /** Count of consecutive workers-nudges sent for a goal (goalId → count). Reset on agent_start. */
    private idleNudgeCount;
    /** Separate timer for nudging when no workers remain (goalId → timer). One-shot setTimeouts that reschedule with exponential backoff. */
    private noWorkersNudgeTimers;
    /** Count of consecutive no-workers nudges sent for a goal (goalId → count).
     *  Reset only by external prompts (source "user" or "system"). */
    private noWorkersNudgeCount;
    /** Guard flag: true while an auto-nudge prompt is pending (not yet processed by the agent). */
    private nudgePending;
    private verificationHarness?;
    /** Base delay before nudging the idle team lead when workers are active (ms). Successive nudges back off exponentially up to MAX_IDLE_NUDGE_DELAY_MS. */
    private static readonly IDLE_NUDGE_DELAY_MS;
    /** Maximum delay between workers-nudges (ms). Caps the exponential backoff. */
    private static readonly MAX_IDLE_NUDGE_DELAY_MS;
    /** Delay before nudging the idle team lead when no workers remain (ms). */
    private static readonly NO_WORKERS_NUDGE_DELAY_MS;
    /** Maximum delay between no-workers nudges (ms). Caps the exponential backoff. */
    private static readonly MAX_NO_WORKERS_NUDGE_DELAY_MS;
    /**
     * If any team member is actively streaming, suppress the workers-nudge unless at
     * least one has been streaming longer than this threshold. Prevents nagging the
     * team lead while workers are making real progress.
     */
    private static readonly LONG_STREAMING_THRESHOLD_MS;
    /** Reverse lookup: sessionId → goalId for quick dismissal. */
    private sessionToGoal;
    /** Track last notification time per worker session to debounce rapid agent_end events. */
    private lastNotifyTime;
    /** In-flight startTeam promises to prevent concurrent team creation for the same goal. */
    private startTeamLocks;
    constructor(sessionManager: SessionManager, config: TeamManagerConfig, stateDir?: string);
    private resolveTeamStore;
    private resolveGateStore;
    /** Set the broadcastToGoal function (called after WebSocket server is created). */
    setBroadcastToGoal(fn: (goalId: string, event: any) => void): void;
    /** Wire in the verification harness so nudge logic can check for active verifications. */
    setVerificationHarness(harness: VerificationHarness): void;
    /** Pick a palette index (0-19) not already used by any session, with randomisation. */
    private assignUniqueColor;
    /**
     * Convert an in-memory TeamEntry to a PersistedTeamEntry for storage.
     */
    private toPersistedEntry;
    /**
     * Persist the current state of a team entry to disk.
     */
    private persistEntry;
    /**
     * Restore teams from disk persistence.
     * Reconstructs the in-memory Maps from the persisted store.
     */
    /**
     * Phase 1: Restore team data structures and reverse lookups from disk.
     * Called from the constructor (before sessions are restored).
     * Event subscriptions are deferred to resubscribeTeamEvents().
     */
    private restoreTeams;
    /**
     * Phase 2: Re-subscribe to team lead and worker agent events.
     * Must be called AFTER sessions have been restored (restoreSessions()),
     * because it needs live session objects to attach event listeners.
     */
    resubscribeTeamEvents(): void;
    /**
     * Clear and remove all idle-nudge timers for a goal.
     */
    private clearIdleNudgeTimer;
    /**
     * Format elapsed time since a timestamp.
     */
    private formatElapsed;
    /** Common pre-checks for nudge timer ticks. Returns true if the nudge should be skipped. */
    private shouldSkipNudge;
    /** Get active (non-reviewer, non-terminated) workers for a goal. */
    private getActiveWorkers;
    /**
     * Start both idle-nudge timers when the team lead goes idle.
     *
     * Two independent repeating timers run in parallel:
     * - **No-workers timer** (5 min): fires when the team lead is idle with zero
     *   active workers — one-shot nudge then self-clears.
     * - **Workers timer** (10 min): fires when the team lead is idle while workers
     *   are still active — repeats every 10 min.
     *
     * Each timer checks conditions on every tick and returns early if they don't apply.
     */
    private startIdleNudgeTimer;
    /**
     * Schedule the next no-workers nudge for a goal using exponential backoff.
     * Delay = NO_WORKERS_NUDGE_DELAY_MS * 2^count, capped at MAX_NO_WORKERS_NUDGE_DELAY_MS.
     * Aborts cleanly without incrementing the counter if a worker appears before
     * the timer fires — the workers-nudge takes over that case.
     */
    private scheduleNoWorkersNudge;
    /**
     * Schedule the next workers-nudge for a goal using exponential backoff.
     * Delay = IDLE_NUDGE_DELAY_MS * 2^count, capped at MAX_IDLE_NUDGE_DELAY_MS.
     */
    private scheduleWorkersNudge;
    /**
     * Subscribe to the team lead session's RPC events to manage the idle-nudge timer.
     * On agent_end (idle): start the timer. On agent_start (streaming): clear it.
     */
    private subscribeTeamLeadEvents;
    private get goalManager();
    /**
     * Resolve tasks for a session using the correct project's TaskManager.
     * When PCM is active, resolves via the goal's project context.
     */
    private resolveTasksForSession;
    /** Resolve a goal across all project contexts. */
    private resolveGoal;
    /** Get a GoalManager scoped to the project owning the given goal. */
    private resolveGoalManager;
    /**
     * Start a team for the given goal.
     * Creates a Team Lead session and returns it.
     */
    startTeam(goalId: string): Promise<SessionInfo>;
    private _startTeamImpl;
    /**
     * Spawn a role agent for a team goal.
     * Creates an isolated git worktree and a session with the role's system prompt.
     * Sends the task as the first prompt.
     */
    /**
     * Build context from passed upstream dependency gates.
     *
     * If `explicitInputIds` is provided, those workflow gate IDs are used directly.
     * Otherwise, auto-resolves from the DAG's `dependsOn` for `workflowGateId`.
     */
    buildDependencyContext(goalId: string, workflowGateId?: string, explicitInputIds?: string[]): string;
    /**
     * Try to extract a workflowGateId from the task description.
     * Looks for a pattern like `[gate:some-id]` in the task text.
     */
    private extractWorkflowGateId;
    spawnRole(goalId: string, role: string, task: string, opts?: {
        workflowGateId?: string;
        inputGateIds?: string[];
    }): Promise<{
        sessionId: string;
        worktreePath?: string;
    }>;
    /**
     * Notify the team lead that a worker agent has gone idle.
     * Sends a steer message with task context so the team lead can decide next steps.
     */
    private notifyTeamLead;
    /**
     * Notify the team lead when a task transitions to a terminal state.
     * Called from the task transition REST endpoint so the team lead wakes up
     * even if the worker continues with another task without going idle.
     */
    notifyTeamLeadOfTaskCompletion(goalId: string, taskTitle: string, taskState: string): void;
    /**
     * Dismiss (terminate) a role agent session and clean up its worktree.
     */
    dismissRole(sessionId: string): Promise<boolean>;
    /**
     * Register a verification reviewer session as a team agent without creating a worktree.
     * The verification harness manages the session lifecycle — no agent_end subscription is needed.
     * Silently returns if no team exists for the goal (handles manual gate signals).
     */
    registerReviewerSession(goalId: string, sessionId: string, stepName: string): void;
    /**
     * Unregister a verification reviewer session from the team.
     * Called after the session is terminated so archiving happens first.
     */
    unregisterReviewerSession(goalId: string, sessionId: string): void;
    /**
     * List all active agents for a goal.
     */
    listAgents(goalId: string): TeamAgentInfo[];
    /**
     * Find a team agent by session ID across all goals.
     * Returns the TeamAgent record if found, undefined otherwise.
     */
    findAgentBySessionId(sessionId: string): TeamAgent | undefined;
    /**
     * Complete a team: dismiss all role agents but keep the team lead alive.
     * The team lead remains active to await further instructions.
     */
    completeTeam(goalId: string): Promise<void>;
    /**
     * Fully tear down a team: dismiss all agents AND terminate the team lead.
     * Use this when explicitly shutting down everything.
     */
    teardownTeam(goalId: string): Promise<void>;
    /**
     * Get the full team state for a goal.
     */
    getTeamState(goalId: string): TeamState | undefined;
}
//# sourceMappingURL=team-manager.d.ts.map