/**
 * Working Memory Service — auto-injectable "why am I awake" wake card
 * for agent prompts.
 *
 * Builds a compact (≤1.5KB) markdown card that summarizes the most-
 * recent active WorkItem assigned to an agent, the parent Request, the
 * upstream WorkItem chain (max 5), the required next action, and any
 * known constraints / open loops on the Request — so every agent wakes
 * with the answer to "why am I awake right now?" without having to
 * query the task pool manually.
 *
 * Per Memory Phase 1 / Fix M2: today, when an agent wakes (assigned
 * to a WorkItem), it doesn't automatically know its parent Request,
 * the upstream task chain, or relevant prior episodes — it receives
 * just the WorkItem description and has to query manually. This
 * service closes that gap by feeding a tiny wake card into prompt
 * assembly automatically, alongside the M1 mission card.
 *
 * Out of scope for Phase 1 (deferred to later phases):
 *   - Narrative summarization of upstream chain (no LLM round-trip)
 *   - Episode memory / event timeline (M5 work)
 *   - Vector embedding / semantic recall
 *   - Memory review queue / supersession
 *
 * @module services/memory/working-memory.service
 */
import type { WorkItem, WorkItemStatus } from '../../types/v2/work-item.types.js';
import type { Request } from '../../types/v2/request.types.js';
/**
 * Hard upper bound on the rendered wake card. Spec calls for ≤1.5KB;
 * we cap at 1.5KB and truncate aggressively (drop optional sections
 * first, then trim verbose sections) when over budget.
 */
export declare const WAKE_CARD_HARD_CAP_BYTES = 1536;
/**
 * WorkItem statuses that count as "currently active for this agent".
 *
 * An agent that is `proposed` an item is about to wake on it, an
 * `accepted` / `running` agent is mid-flight, and `blocked` /
 * `escalated` are still the agent's open loop. Terminal statuses
 * (done, verified, failed, cancelled) are NOT counted — the agent
 * has nothing to wake on if its only assignment is closed.
 */
declare const ACTIVE_WORK_ITEM_STATUSES: ReadonlySet<WorkItemStatus>;
/**
 * Inputs accepted by `getWakeCardForAgent`.
 *
 * `sessionName` is what the WorkItem.target field is set to (e.g.
 * `crewly-product-leo-21a5477e`); the service uses this to find the
 * agent's currently-active WorkItem. `agentId` is used for logging
 * only (typically the same string, but we keep them separate so a
 * caller using memberId for logging can still set sessionName for
 * the lookup).
 */
export interface WakeCardRequest {
    /** Agent identifier — used for logging only. */
    agentId: string;
    /** Agent's session name — used to filter WorkItems by target. */
    sessionName: string;
    /** Absolute path to the project root that owns `.crewly/`. */
    projectPath: string;
    /** Optional team id — currently unused, reserved for future filters. */
    teamId?: string;
}
/**
 * Internal shape used during card rendering. Captures the data points
 * the spec calls out and lets `renderWakeCard` stay pure / testable.
 */
export interface WakeCardData {
    /** The current active WorkItem for this agent, if any. */
    current: WorkItem | null;
    /** The parent Request, if linked. */
    parentRequest: Request | null;
    /**
     * The upstream WorkItem chain (oldest → most-recent), up to
     * UPSTREAM_CHAIN_MAX_ITEMS entries. Excludes `current` itself.
     */
    upstreamChain: WorkItem[];
    /**
     * Open-loop / constraint summaries surfaced under "Known constraints".
     * Sourced from Request metadata when present.
     */
    openLoops: string[];
}
/**
 * Service that builds the working-memory wake card injected into
 * agent prompts.
 *
 * Singleton (mirrors {@link MissionContextService}). Caller side is
 * fail-soft: any read error logs a warning and the service returns
 * the empty string so prompt assembly never breaks.
 *
 * @example
 * ```typescript
 * const svc = WorkingMemoryService.getInstance();
 * const card = await svc.getWakeCardForAgent({
 *   agentId: 'member-uuid',
 *   sessionName: 'crewly-product-leo-21a5477e',
 *   projectPath: '/Users/me/projects/crewly',
 *   teamId: '28a4ac10-...',
 * });
 * if (card) prompt += `\n${card}`;
 * ```
 */
export declare class WorkingMemoryService {
    private static instance;
    private readonly logger;
    private constructor();
    /** Get the shared singleton instance. */
    static getInstance(): WorkingMemoryService;
    /** Reset for tests. */
    static clearInstance(): void;
    /**
     * Build the working-memory wake card for an agent.
     *
     * Returns the empty string when no signals are available (no active
     * WorkItem assigned to this agent) — callers should treat empty
     * output as "skip the section entirely" rather than rendering an
     * empty heading.
     *
     * Errors reading the task pool / request store are caught and logged
     * as warnings; the method still returns the empty string so prompt
     * assembly never breaks.
     *
     * @param req - Request inputs
     * @returns A ≤1.5KB markdown card, or `''` when nothing is worth showing
     */
    getWakeCardForAgent(req: WakeCardRequest): Promise<string>;
    /**
     * Gathers everything the renderer needs for one agent.
     *
     * Steps:
     *   1. Find the agent's most-recent active WorkItem in the task pool.
     *   2. If linked, load the parent Request.
     *   3. Walk the parentWorkItemId chain (most-recent → oldest), up to
     *      UPSTREAM_CHAIN_MAX_ITEMS, and reverse for chronological order.
     *   4. Extract open-loop / constraint summaries from Request metadata.
     *
     * @param req - Caller request
     * @returns Populated WakeCardData (current may be null when nothing
     *   is awake for this agent).
     */
    private collectWakeData;
    /**
     * Loads a Request by id, returning null on miss / error.
     *
     * Wraps {@link RequestService.getById} (singleton scoped to
     * `req.projectPath`) so a missing or malformed Request file is
     * downgraded to a debug-level warning rather than aborting the
     * whole wake-card build.
     */
    private loadRequest;
}
/**
 * Pick the most-recent active WorkItem assigned to an agent.
 *
 * "Active" = status in {@link ACTIVE_WORK_ITEM_STATUSES}. "Most recent"
 * = greatest `startedAt` (when set) else greatest `createdAt`. Ties
 * resolve to whichever item appears later in the iteration order
 * (effectively pool insertion order).
 *
 * Returns null when no item is currently active for this agent.
 *
 * @param items - All WorkItems in the pool
 * @param sessionName - The agent's session name (matched against `target`)
 */
export declare function pickCurrentWorkItem(items: readonly WorkItem[], sessionName: string): WorkItem | null;
/**
 * Walk the `parentWorkItemId` chain to build the upstream task
 * sequence in chronological order (oldest → most-recent), capped at
 * `maxItems` entries. The current WorkItem itself is NOT included in
 * the result.
 *
 * Defends against cycles by tracking visited ids.
 *
 * @param items - All WorkItems in the pool
 * @param current - The wake-card's current WorkItem (chain anchor)
 * @param maxItems - Maximum number of upstream entries to surface
 */
export declare function buildUpstreamChain(items: readonly WorkItem[], current: WorkItem, maxItems: number): WorkItem[];
/**
 * Extract open-loop / constraint summaries from a parent Request.
 *
 * Today the Request type does not have a dedicated `openLoops` field,
 * so we derive one signal: the `confirmationReason` (when set —
 * indicates a pending user confirmation that the agent should be
 * aware of). When neither signal is present, returns an empty array
 * and the renderer drops the section entirely.
 *
 * Phase 2 (M5 / M6) will add richer signals (decisions, lessons,
 * outstanding sub-task statuses); this function is the extension
 * point.
 *
 * @param request - Parent Request, or null
 */
export declare function collectOpenLoops(request: Request | null): string[];
/**
 * Render a one-line summary for a WorkItem suitable for the
 * upstream-chain bullet list. Format: `"<status> · <title>"` truncated
 * at SUMMARY_LINE_MAX_CHARS.
 */
export declare function summarizeWorkItem(wi: WorkItem): string;
/**
 * Compose the full wake-card markdown from collected data.
 *
 * Sections (in order):
 *   1. Header — "## Why You Are Awake"
 *   2. WorkItem — title (always present when called)
 *   3. Parent Request — title + 1-line summary
 *   4. Upstream chain — bullet list of prior WorkItems (max 5)
 *   5. Required next action — from WorkItem description
 *   6. Known constraints / open loops — from Request metadata (if any)
 *
 * Sections 3-6 are emitted only when they have content; an absent
 * parent Request or empty chain simply drops the corresponding
 * heading.
 */
export declare function renderWakeCard(data: WakeCardData): string;
/**
 * Enforce the hard byte cap. Truncates the card at the last newline
 * boundary that still fits, so we never cut a markdown bullet
 * mid-line. If even the header exceeds the cap (shouldn't happen),
 * the input is hard-truncated by byte length.
 *
 * @param content - Original rendered card
 * @param capBytes - Hard cap in UTF-8 bytes
 * @returns The card, possibly truncated, never exceeding `capBytes`
 */
export declare function enforceHardCap(content: string, capBytes: number): string;
/** Re-export for tests. */
export { ACTIVE_WORK_ITEM_STATUSES };
//# sourceMappingURL=working-memory.service.d.ts.map