/**
 * Live Reconciler Data Provider — Wires the Reconciler to real services
 *
 * Replaces the stub data provider with actual Task Pool, Claim Service,
 * Storage Service, and Agent Suspend integrations. This enables the
 * Reconciler to perform real reconciliation passes including:
 * - Detecting expired claims and revoking them
 * - Finding stuck WorkItems and re-queuing them
 * - Hybrid Wake: waking dormant agents when tasks go unclaimed
 *
 * @module services/reconciler/reconciler-data-provider
 */
import type { ReconcilerDataProvider } from './reconciler.service.js';
import type { AgentHealth } from './reconcile-rules.js';
import type { WorkItem, Request, TaskClaim, ReconcileCorrection, WakeAction } from '../../types/v2/index.js';
import type { EventBusService } from '../event-bus/event-bus.service.js';
/**
 * Cap on concurrent active agents while the system is under memory
 * pressure. Named `WAKE_FLOOR` for historical reasons — the value
 * acts as a CEILING on wake actions under pressure, not a guaranteed
 * floor. The reconciler does not proactively bring the active count
 * up to this value; it only permits wakes when `activeCount < N` and
 * blocks them otherwise.
 *
 * Behaviour:
 *  - `activeCount <  N` AND memory pressure → wake allowed (keeps the
 *    system minimally productive instead of fully wedged).
 *  - `activeCount >= N` AND memory pressure → wake blocked (prevents
 *    an OOM cascade by capping additional spawns during a crisis).
 *  - No memory pressure → this gate is not consulted.
 *
 * History: an earlier implementation blocked EVERY wake under memory
 * pressure, which wedged the system on 2026-05-13 (6+ hours, free RAM
 * 16-33 MB, queued WIs piling up). On 2026-05-14 the system stalled
 * again — this gate worked as designed, but `IdleDetectionService`
 * silently stopped releasing idle agents, so `activeCount` stayed
 * above N for ~20 hours. The cap itself is not the bug; the absence
 * of forward progress when the cap is held is. See the heartbeat
 * additions in `idle-detection.service.ts`.
 */
export declare const WAKE_FLOOR_UNDER_PRESSURE = 3;
/**
 * Minimal slice of `AgentRegistrationService` the provider needs for the
 * memory-pressure eviction path. Declared narrowly so test fixtures can
 * stub a single method without simulating the full registration surface.
 */
export interface IAgentRegistrationServiceLike {
    terminateAgentSession(sessionName: string, role?: string): Promise<{
        success: boolean;
        message?: string;
        error?: string;
    }>;
}
/**
 * Production-ready ReconcilerDataProvider that connects to live services.
 *
 * Reads WorkItems and Claims from the Task Pool, builds the agent health
 * map from StorageService team data, and executes wake actions via
 * AgentSuspendService.
 *
 * @example
 * ```typescript
 * const provider = new LiveReconcilerDataProvider();
 * const reconciler = new ReconcilerService(provider);
 * reconciler.start();
 * ```
 */
export declare class LiveReconcilerDataProvider implements ReconcilerDataProvider {
    private readonly logger;
    private readonly storage;
    private eventBus;
    private agentRegistration;
    private consecutivePressureSkips;
    private lastPressureNotifiedAt;
    /**
     * Per-WorkItem redeliver cooldown. The reconciler fast loop runs every
     * ~10s and re-emits a `redeliver` wake for any queued WI whose target is
     * active-but-idle — with NO per-WI rate-limit in the rule. Without this
     * gate a queued-but-unclaimed WI (e.g. one the orc has read but not yet
     * claimed) is re-POSTed to its PTY every 10s (~50-60/hr), which is the
     * wiki-bridge "spam" the user saw and the same class as the 2026-05-27
     * PTY-flood incident. We cap redelivery of a given WI to once per
     * {@link REDELIVER_COOLDOWN_MS}.
     */
    private readonly lastRedeliverAt;
    constructor();
    /**
     * Inject the EventBus used to broadcast `system:memory_pressure` to
     * orc. Optional — when not set, the reconciler still functions but
     * no user-facing notification is emitted. Called once from the
     * server bootstrap after both services are constructed.
     *
     * @param eventBus - The EventBusService singleton wired in `index.ts`
     */
    setEventBus(eventBus: EventBusService): void;
    /**
     * Inject the AgentRegistrationService so the memory-pressure eviction
     * path can terminate idle agents (the same primitive
     * `IdleDetectionService` uses). Optional — when not wired, eviction
     * is disabled and the reconciler falls back to the prior skip-on-floor
     * behaviour.
     *
     * @param svc - AgentRegistrationService instance from the bootstrap
     */
    setAgentRegistrationService(svc: IAgentRegistrationServiceLike): void;
    /**
     * Returns all non-terminal WorkItems from the Task Pool.
     * Non-terminal means items that are not 'done' or 'cancelled'.
     *
     * @returns Active WorkItems
     */
    getActiveWorkItems(): Promise<WorkItem[]>;
    /**
     * Returns WorkItems belonging to a specific Request.
     *
     * @param requestId - The Request ID
     * @returns WorkItems for the given request
     */
    getWorkItemsForRequest(requestId: string): Promise<WorkItem[]>;
    /**
     * Returns all non-terminal Requests.
     *
     * Note: V3 Requests are not yet fully persisted — returns empty
     * until the Request storage layer is implemented. The Reconciler
     * gracefully handles empty arrays.
     *
     * @returns Active Requests
     */
    getActiveRequests(): Promise<Request[]>;
    /**
     * Returns all active/expiring TaskClaims.
     *
     * **F-CYCLE7-3 (2026-05-07):** Returns `[]` defensively if the pool
     * returns a non-array (e.g. partial post-restart hydration where
     * `pool.json` is missing the `claims` field). Storage-not-ready is
     * logged at `debug`, not `error`, to avoid the post-restart error
     * storm seen at 11:19→11:21Z. Genuine failures (thrown errors) keep
     * their `error`-level log.
     *
     * @returns Active claims (always an array)
     */
    getActiveClaims(): Promise<TaskClaim[]>;
    /**
     * Builds the agent health map from StorageService team data.
     *
     * Iterates all teams and members to produce a Map<sessionName, AgentHealth>
     * representing the current state of all known agents.
     *
     * @returns Map of agent session name to health info
     */
    getAgentHealthMap(): Promise<Map<string, AgentHealth>>;
    /**
     * Applies a reconciliation correction by updating entity status.
     *
     * @param correction - The correction to apply
     */
    applyCorrection(correction: ReconcileCorrection): Promise<void>;
    /**
     * Releases a WorkItem back to the Task Pool for re-claiming.
     *
     * @param workItemId - The WorkItem ID to release
     * @param reason - Why the item is being released
     */
    releaseToPool(workItemId: string, reason: string): Promise<void>;
    /**
     * Re-queues a WorkItem (increments retryCount, sets status to 'queued').
     *
     * @param workItemId - The WorkItem ID to re-queue
     */
    requeueWorkItem(workItemId: string): Promise<void>;
    /**
     * Marks a claim as 'expiring' (lease expired, within grace period).
     *
     * @param claimId - The claim ID to mark
     */
    markClaimExpiring(claimId: string): Promise<void>;
    /**
     * Revokes a claim and releases its WorkItem back to the pool.
     *
     * @param claimId - The claim ID to revoke
     * @param reason - Why the claim is being revoked
     */
    revokeClaimAndRelease(claimId: string, reason: string): Promise<void>;
    /**
     * Returns all available (queued, unclaimed) WorkItems from the Task Pool.
     * Used by Hybrid Wake to find items that need agents.
     *
     * **F-CYCLE7-3 (2026-05-07):** Returns `[]` defensively if the pool
     * returns a non-array (e.g. partial post-restart hydration where
     * `pool.json` is missing the `workItems` field). Storage-not-ready is
     * logged at `debug`, not `error`, to avoid the post-restart error
     * storm seen at 11:19→11:21Z.
     *
     * @returns Available pool items (always an array)
     */
    getAvailablePoolItems(): Promise<WorkItem[]>;
    /**
     * Executes a wake action — rehydrates a suspended agent or starts an inactive one.
     *
     * Strategy mapping:
     * - 'rehydrate' → AgentSuspendService.rehydrateAgent()
     * - 'start' → AgentRegistrationService.createAgentSession() (via start-agent API)
     *
     * @param action - The wake action to execute
     * @returns True if the wake was initiated successfully
     */
    /**
     * Count agent sessions currently in an alive state. Used by the
     * memory-pressure gate in {@link executeWakeAction} to decide whether
     * a new wake would push us past the concurrency floor.
     *
     * Counts `'active'`, `'started'`, and `'starting'` — anything that
     * has a live process consuming RAM. `started` and `starting` cover
     * in-flight wakes from prior reconciler ticks that haven't fully
     * promoted to active yet. `suspended` / `inactive` are NOT alive and
     * don't contribute (suspended drops the runtime; inactive never had
     * one).
     *
     * @returns The number of agent sessions currently alive
     */
    private countActiveAgentSessions;
    /**
     * Broadcast `system:memory_pressure` to the EventBus when wake actions
     * have been skipped enough consecutive times to indicate a sustained
     * stall. Throttled so a long pressure episode emits at most one event
     * per `MEMORY_PRESSURE_REFIRE_MS` window — orc only needs to surface
     * the condition once per stuck period, not on every reconciler tick.
     *
     * The 2026-05-14 incident skipped wakes ~4,200 times across 20 hours
     * with zero user-visible signal. After this change, orc receives a
     * critical event within ~50 seconds of the stall starting and every
     * ~5 minutes thereafter until pressure clears.
     *
     * @param stats - Snapshot of memory stats at the skip moment
     * @param activeCount - Current active agent count (already computed)
     */
    private maybeBroadcastMemoryPressure;
    /**
     * Reset the memory-pressure broadcast state. Called on every wake
     * that runs without pressure so the next sustained episode re-fires
     * the first-time threshold instead of being silenced by stale state.
     */
    private resetMemoryPressureBroadcast;
    /**
     * Per-WI dedup of `task:queued_too_long` broadcasts. Maps WI id to the
     * ISO timestamp at which we last fired. A WI is only re-broadcast
     * after {@link STUCK_WI_REBROADCAST_MS} has elapsed since the last
     * fire — keeps the orc terminal sane when many WIs accumulate.
     *
     * Cleaned on every reconcile pass that observes the WI is no longer
     * `queued`, so a successful resume cancels the dedup naturally.
     */
    private lastStuckWiNotifiedAt;
    /**
     * Re-broadcast window for the same WI. Picked to roughly match the
     * reconciler's own staleness threshold so a long-stuck WI gets a
     * follow-up reminder ~hourly without flooding.
     */
    private static readonly STUCK_WI_REBROADCAST_MS;
    /**
     * Broadcast `task:queued_too_long` for WIs the reconciler has just
     * detected as stale-queued past the threshold. Public so the
     * reconciler service can call it after the existing log line at
     * reconciler.service.ts:213.
     *
     * Per-WI dedup ensures a long-stuck WI fires at most once per
     * {@link STUCK_WI_REBROADCAST_MS}. Missing target/owner is fine — the
     * subscription filter side handles defaults.
     *
     * @param staleWorkItems - List of `{id, target, owner, createdAt}` for
     *   each WI past the staleness threshold. The reconciler resolves
     *   these from {@link getTaskPoolService}.findWorkItem before calling.
     */
    broadcastStaleQueuedWIs(staleWorkItems: ReadonlyArray<{
        id: string;
        target?: string;
        owner?: string;
        createdAt: string;
    }>): void;
    /**
     * Drop dedup entries for WIs that are no longer stuck. Called by the
     * reconciler each pass with the current set of `queued` WI ids — any
     * id in our map that is NOT in the current set has been resolved
     * (claimed, completed, cancelled) and its dedup window should be
     * released so a future re-stale gets a fresh first-fire.
     */
    clearResolvedStuckWiDedup(currentlyQueuedIds: ReadonlySet<string>): void;
    /**
     * Find one idle, evictable agent that can be terminated to free a wake
     * slot under memory pressure.
     *
     * An agent is "evictable" when ALL of the following hold:
     *   - `agentStatus === 'active'` (no point evicting an already-dead one)
     *   - `workingStatus === 'idle'` (don't kill a mid-task agent)
     *   - role is NOT in `ALWAYS_ON_ROLES` (orchestrator, auditor)
     *   - no non-terminal WorkItem in the pool targets this sessionName
     *     (otherwise eviction would orphan that WI just like Atlas's)
     *   - sessionName !== `incomingAgent` (don't evict ourselves)
     *
     * Among eligible agents, returns the longest-idle one (oldest
     * `updatedAt`). This biases towards freeing agents that have been sitting
     * quietly without work — the freshest idle agent might be about to claim
     * something via the auto-claim path.
     *
     * @param incomingAgent - sessionName of the agent we want to wake;
     *   excluded from the eviction pool so we never recommend evicting the
     *   very agent we're trying to wake.
     * @returns Eviction candidate metadata, or `null` if no agent qualifies.
     */
    private findEvictableIdleAgent;
    /**
     * Terminate an evicted agent so the wake slot is freed.
     *
     * Uses the same `terminateAgentSession` + `updateAgentStatus(..,
     * 'idle_exit_pressure')` pair that `IdleDetectionService` uses for the
     * regular auto-stop path, just with a different dropoutReason so the
     * pressure-driven evictions are distinguishable in audit logs.
     *
     * @param victim - Eviction candidate returned by `findEvictableIdleAgent`
     * @returns `true` if the agent was terminated AND marked inactive;
     *   `false` if either step failed (the caller falls back to skip).
     */
    private evictIdleAgent;
    executeWakeAction(action: WakeAction): Promise<boolean>;
    /**
     * Backfill token usage on completed WorkItems that still show 0 tokens.
     *
     * Scans all done/failed WorkItems with zero inputTokens, looks up token
     * usage from TokenUsageService by the agent session (target field), and
     * writes the data to the WorkItem.
     *
     * @returns Number of WorkItems updated
     */
    backfillTokenUsage(): Promise<number>;
    /**
     * Maps TeamMember agentStatus to AgentHealth status.
     *
     * @param agentStatus - The TeamMember's agentStatus field
     * @returns Normalized status for reconcile rules
     */
    private mapAgentStatus;
}
//# sourceMappingURL=reconciler-data-provider.d.ts.map