/**
 * Corrections Log — extracts error→fix patterns from verification retry successes
 * and injects relevant corrections into future execute-task prompts.
 *
 * Uses the existing memory-store with category='correction'. Fire-and-forget
 * semantics: extraction never throws, never blocks the auto-loop (D002).
 */
import { applyMemoryActions, getActiveMemoriesRanked, } from "./memory-store.js";
// ─── Extraction ─────────────────────────────────────────────────────────────
/**
 * Distill an error→fix pair into a concise correction entry.
 * Returns a memory-compatible object with category='correction'.
 * Content is capped at ~200 chars: "Error: <pattern> → Fix: <resolution>".
 */
export function extractCorrection(unitId, failureContext, successContext) {
    // Extract the first meaningful line from failure context (skip blank/header lines)
    const failureLines = failureContext.split("\n").filter((l) => l.trim().length > 0);
    const errorSummary = (failureLines[0] ?? "unknown error").slice(0, 80).trim();
    // Extract a concise resolution hint from success context
    const successLines = successContext.split("\n").filter((l) => l.trim().length > 0);
    const fixSummary = (successLines[0] ?? "retried successfully").slice(0, 80).trim();
    const content = `[${unitId}] Error: ${errorSummary} → Fix: ${fixSummary}`.slice(0, 200);
    return {
        category: "correction",
        content,
        confidence: 0.7,
    };
}
/**
 * Extract and store a correction from a retry-success event.
 * Fire-and-forget: catches all errors internally, never throws.
 */
export function storeCorrection(unitId, failureContext, successContext) {
    try {
        const correction = extractCorrection(unitId, failureContext, successContext);
        applyMemoryActions([{ action: "CREATE", category: correction.category, content: correction.content, confidence: correction.confidence }], "execute-task", unitId);
    }
    catch {
        // Fire-and-forget: never block the auto-loop
    }
}
// ─── Retrieval ──────────────────────────────────────────────────────────────
/**
 * Query corrections relevant to the current task/slice.
 * Filters active memories by category='correction', then optionally by
 * keyword overlap with the task/slice title for relevance.
 */
export function getRelevantCorrections(taskTitle, sliceTitle, limit = 10) {
    // Get all active memories ranked by confidence, then filter to corrections
    const allMemories = getActiveMemoriesRanked(100);
    const corrections = allMemories.filter((m) => m.category === "correction");
    if (corrections.length === 0)
        return [];
    // Extract keywords from task + slice titles for relevance filtering
    const titleWords = new Set(`${taskTitle} ${sliceTitle}`
        .toLowerCase()
        .split(/\W+/)
        .filter((w) => w.length > 2));
    if (titleWords.size === 0) {
        // No meaningful keywords: return most recent corrections
        return corrections.slice(0, limit);
    }
    // Score each correction by keyword overlap
    const scored = corrections.map((c) => {
        const contentWords = c.content.toLowerCase().split(/\W+/);
        const overlap = contentWords.filter((w) => titleWords.has(w)).length;
        return { memory: c, score: overlap };
    });
    // Return corrections with any keyword match first, then by original ranking
    scored.sort((a, b) => b.score - a.score);
    return scored.slice(0, limit).map((s) => s.memory);
}
// ─── Prompt Formatting ──────────────────────────────────────────────────────
/**
 * Format corrections as a markdown section for prompt injection.
 * Respects a token budget (~4 chars per token). Returns empty string if
 * no corrections or budget exhausted.
 */
export function formatCorrectionsForPrompt(corrections, tokenBudget = 500) {
    if (corrections.length === 0)
        return "";
    const charBudget = tokenBudget * 4;
    const header = "## Prior Corrections (auto-learned error→fix patterns)\n\n";
    let output = header;
    let remaining = charBudget - header.length;
    for (const c of corrections) {
        const bullet = `- ${c.content}\n`;
        if (remaining < bullet.length)
            break;
        output += bullet;
        remaining -= bullet.length;
    }
    return output.trimEnd();
}
