/** * `chat-recall escalate` — the WRITE half of the Context Engineering loop. * * The read half already exists: `chat-recall memory wake-up` (SessionStart * hook) injects prior knowledge into a new session. This module closes the * loop at the other end: at SessionEnd it extracts a finished session's * learnings and asserts them into the temporal knowledge graph, so the NEXT * wake-up already knows them. Three kinds of learning, three predicates: * * - decisions the agent announced → → decided → * - corrections the user gave → → user_corrected → * - how the session ended → → session_outcome → * * Sources: decisions + outcome come from the server's own outcome analyzer * (`GET /api/conversations/:id/outcome` — the same data recall_summary shows); * corrections are extracted client-side from the synced transcript * (`GET /api/conversations/:id?limit=0`) with the marker heuristics below. * Writes go through `POST /api/kg/add` — the same endpoint recall_kg_add and * recall_decision_record use — with `supersede: false` (learnings are * multi-valued: a project accumulates many decisions) and `origin: 'asserted'` * stamped server-side. * * Hook safety: this runs from a SessionEnd hook, so every "cannot proceed" * condition (not logged in, server down, session not synced yet) is a dim * note + a clean return — the CLI command exits 0. A hook must never break * session end. */ export interface ConvoMessage { line?: number; role: string; content: string; } export interface SessionOutcome { status?: string; reason?: string; decisions?: Array<{ text: string; }>; } export interface Learning { kind: 'decision' | 'correction' | 'outcome'; subject: string; predicate: string; object: string; confidence: number; } /** Minimal server access the runner needs — cli.ts passes its own helpers. */ export interface EscalateDeps { get(path: string): Promise; getSoft(path: string): Promise<{ status: number; data: T | null; message?: string; }>; post(path: string, body: unknown): Promise; /** Informational output (goes to stdout via the CLI's own styling). */ log(line: string): void; } export interface EscalateOptions { /** Explicit session id; wins over `latest`. */ sessionId?: string; /** Resolve the most recent synced session of the cwd's project. */ latest?: boolean; /** KG entity name for the facts. Default: basename of the session's project path, then of cwd. */ project?: string; /** Extract and print without writing. */ dryRun?: boolean; cwd: string; } /** Collapse whitespace and cut at a word boundary. */ export declare function clip(text: string, max?: number): string; /** * Corrections the user gave, in transcript order. The FIRST user message is * skipped (the task statement cannot correct anything), noise carriers are * skipped, and the result is deduplicated and capped. */ export declare function extractCorrections(messages: ConvoMessage[], cap?: number): string[]; /** * Assemble the full learning set for one session. Confidence 0.8 marks these * as auto-extracted — below a deliberate recall_decision_record (1.0), above * the KG's auto-mined guesses (0.5). */ export declare function extractLearnings(input: { project: string; messages: ConvoMessage[]; outcome: SessionOutcome | null; }): Learning[]; export interface EscalateResult { sessionId: string; written: number; skippedExisting: number; dryRun: boolean; } /** * Resolve → extract → dedup → write. Returns null when there is nothing to do * (not synced, no learnings) — the caller exits 0 either way. */ export declare function runEscalate(deps: EscalateDeps, opts: EscalateOptions): Promise; //# sourceMappingURL=escalate.d.ts.map