"use strict";
// context-continuity.ts — Supreme Context Thread Engine
// Maintains cross-session memory so AI never forgets context between sessions.
// Captures the "continuation mindset" — what was happening, what's next, why.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getActiveThread = getActiveThread;
exports.getAllThreads = getAllThreads;
exports.detectOrCreateThread = detectOrCreateThread;
exports.closeThread = closeThread;
exports.addBridgeHint = addBridgeHint;
exports.addOpenQuestion = addOpenQuestion;
exports.resolveQuestion = resolveQuestion;
exports.addPendingAction = addPendingAction;
exports.addKeyLearning = addKeyLearning;
exports.addDecision = addDecision;
exports.updateFileFocus = updateFileFocus;
exports.buildContinuityContext = buildContinuityContext;
exports.captureSessionEnd = captureSessionEnd;
exports.getContinuityBlock = getContinuityBlock;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
function getContinuityDir(projectDir) {
    const d = path.join(projectDir, '.cell', 'continuity');
    if (!fs.existsSync(d))
        fs.mkdirSync(d, { recursive: true });
    return d;
}
function threadPath(projectDir, threadId) {
    return path.join(getContinuityDir(projectDir), `${threadId.replace(/[^a-z0-9_-]/gi, '_')}.json`);
}
function getActiveThread(projectDir) {
    const dir = getContinuityDir(projectDir);
    const activeFile = path.join(dir, '_active.json');
    if (!fs.existsSync(activeFile))
        return null;
    return JSON.parse(fs.readFileSync(activeFile, 'utf-8'));
}
function getAllThreads(projectDir) {
    const dir = getContinuityDir(projectDir);
    if (!fs.existsSync(dir))
        return [];
    return fs.readdirSync(dir)
        .filter(f => f.endsWith('.json') && !f.startsWith('_'))
        .map(f => JSON.parse(fs.readFileSync(path.join(dir, f), 'utf-8')))
        .sort((a, b) => new Date(b.lastActiveAt).getTime() - new Date(a.lastActiveAt).getTime());
}
function detectOrCreateThread(projectDir, project, recentDecisions, touchedFiles) {
    const existing = getActiveThread(projectDir);
    // Auto-detect thread intent from recent decisions and files
    const intentStrings = [...recentDecisions, ...touchedFiles].join(' ').toLowerCase();
    let intent = 'General development';
    if (/bug|fix|error|crash|broken/.test(intentStrings))
        intent = 'Bug fixing';
    else if (/feature|add|implement|create|build|new/.test(intentStrings))
        intent = 'Feature development';
    else if (/refactor|clean|improve|optimize|restructure/.test(intentStrings))
        intent = 'Refactoring';
    else if (/test|spec|coverage|jest|vitest/.test(intentStrings))
        intent = 'Testing';
    else if (/docs|readme|document|wiki/.test(intentStrings))
        intent = 'Documentation';
    else if (/deploy|release|ship|launch|publish/.test(intentStrings))
        intent = 'Release/Deploy';
    if (existing) {
        // Same thread — update it
        existing.lastActiveAt = new Date().toISOString();
        existing.sessionCount++;
        existing.contextTags = [...new Set([...existing.contextTags, intent])];
        if (intent !== existing.threadIntent && existing.sessionCount > 2) {
            existing.threadIntent = existing.threadIntent + ' → ' + intent;
        }
        saveThread(projectDir, existing);
        setActiveThread(projectDir, existing);
        return existing;
    }
    // New thread
    const threadId = `${project}-${intent.replace(/\s+/g, '-').toLowerCase()}-${Date.now()}`;
    const thread = {
        project,
        threadId,
        activeSince: new Date().toISOString(),
        lastActiveAt: new Date().toISOString(),
        sessionCount: 1,
        contextTags: [intent],
        openQuestions: [],
        pendingActions: [],
        keyLearnings: [],
        decisionLog: [],
        fileFocus: touchedFiles.slice(0, 10),
        threadIntent: intent,
        bridgeHints: [],
    };
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
    return thread;
}
function saveThread(projectDir, thread) {
    fs.writeFileSync(threadPath(projectDir, thread.threadId), JSON.stringify(thread, null, 2), 'utf-8');
}
function setActiveThread(projectDir, thread) {
    const dir = getContinuityDir(projectDir);
    fs.writeFileSync(path.join(dir, '_active.json'), JSON.stringify(thread, null, 2), 'utf-8');
}
function closeThread(projectDir) {
    const dir = getContinuityDir(projectDir);
    const activeFile = path.join(dir, '_active.json');
    if (fs.existsSync(activeFile)) {
        const thread = JSON.parse(fs.readFileSync(activeFile, 'utf-8'));
        thread.lastActiveAt = new Date().toISOString();
        saveThread(projectDir, thread);
        fs.unlinkSync(activeFile);
    }
}
function addBridgeHint(projectDir, hint) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return;
    thread.bridgeHints.push(hint);
    // Keep only last 20 hints
    if (thread.bridgeHints.length > 20)
        thread.bridgeHints = thread.bridgeHints.slice(-20);
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
}
function addOpenQuestion(projectDir, question) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return;
    if (!thread.openQuestions.includes(question)) {
        thread.openQuestions.push(question);
    }
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
}
function resolveQuestion(projectDir, question) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return;
    thread.openQuestions = thread.openQuestions.filter(q => q !== question);
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
}
function addPendingAction(projectDir, action) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return;
    if (!thread.pendingActions.includes(action)) {
        thread.pendingActions.push(action);
    }
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
}
function addKeyLearning(projectDir, learning) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return;
    if (!thread.keyLearnings.includes(learning)) {
        thread.keyLearnings.push(learning);
        if (thread.keyLearnings.length > 15)
            thread.keyLearnings = thread.keyLearnings.slice(-15);
    }
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
}
function addDecision(projectDir, what, why) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return;
    thread.decisionLog.push({ what, why, when: new Date().toISOString() });
    if (thread.decisionLog.length > 15)
        thread.decisionLog = thread.decisionLog.slice(-15);
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
}
function updateFileFocus(projectDir, files) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return;
    thread.fileFocus = [...new Set([...files, ...thread.fileFocus])].slice(0, 15);
    saveThread(projectDir, thread);
    setActiveThread(projectDir, thread);
}
// Build Supreme context from continuity data
function buildContinuityContext(projectDir, project) {
    const activeThread = getActiveThread(projectDir);
    const recentThreads = getAllThreads(projectDir).filter(t => t.threadId !== activeThread?.threadId).slice(0, 3);
    const crossSessionWarnings = [];
    const predictedNextSteps = [];
    if (activeThread) {
        // Warnings
        if (activeThread.openQuestions.length > 0) {
            crossSessionWarnings.push(`Has ${activeThread.openQuestions.length} unanswered questions from previous sessions`);
        }
        if (activeThread.pendingActions.length > 0) {
            crossSessionWarnings.push(`${activeThread.pendingActions.length} planned actions remain uncompleted — may have been interrupted`);
        }
        if (activeThread.sessionCount >= 3 && activeThread.bridgeHints.length < 5) {
            crossSessionWarnings.push('Multiple sessions but limited context continuity — might be working blind across sessions');
        }
        // Predictions
        for (const hint of activeThread.bridgeHints.filter(h => h.type === 'prediction')) {
            predictedNextSteps.push(hint.text);
        }
        for (const action of activeThread.pendingActions.slice(0, 3)) {
            predictedNextSteps.push(action);
        }
        if (activeThread.openQuestions.length > 0) {
            predictedNextSteps.push(`Answer open question: "${activeThread.openQuestions[0]}"`);
        }
    }
    // Memory thread — human-readable summary
    let memoryThread = 'No prior context thread found. This appears to be a fresh session.';
    if (activeThread && activeThread.sessionCount > 1) {
        const parts = [];
        parts.push(`Working on: ${activeThread.threadIntent}`);
        parts.push(`Across ${activeThread.sessionCount} sessions since ${activeThread.activeSince.split('T')[0]}`);
        if (activeThread.keyLearnings.length > 0) {
            parts.push(`Key learnings: ${activeThread.keyLearnings.slice(-3).join('; ')}`);
        }
        if (activeThread.pendingActions.length > 0) {
            parts.push(`⏭️  Pending: ${activeThread.pendingActions.slice(0, 3).join(', ')}`);
        }
        if (activeThread.fileFocus.length > 0) {
            parts.push(`Focus files: ${activeThread.fileFocus.slice(0, 5).map(f => path.basename(f)).join(', ')}`);
        }
        memoryThread = parts.join('. ');
    }
    return {
        currentThread: activeThread,
        recentThreads,
        crossSessionWarnings,
        predictedNextSteps,
        memoryThread,
    };
}
// Auto-capture on session end — takes a full snapshot
function captureSessionEnd(projectDir, project, decisions, files, approaches, questions) {
    const thread = getActiveThread(projectDir);
    if (!thread)
        return; // No active thread to capture into
    // Record decisions
    for (const d of decisions.slice(-5)) {
        if (!thread.decisionLog.some(dl => dl.what === d)) {
            thread.decisionLog.push({ what: d, why: '', when: new Date().toISOString() });
        }
    }
    // Unresolved questions
    for (const q of questions.filter(q => !q.resolved)) {
        if (!thread.openQuestions.includes(q.question)) {
            thread.openQuestions.push(q.question);
        }
    }
    // Failed/tried approaches → bridge hints
    for (const a of approaches.filter(a => a.status === 'failed' || a.status === 'tried')) {
        const existing = thread.bridgeHints.find(h => h.text.includes(a.approach));
        if (!existing) {
            thread.bridgeHints.push({
                type: 'watch_out',
                text: `Previously tried: "${a.approach}" — ${a.status}. Don't retry.`,
                confidence: 85,
                fromSessionId: thread.sessionCount,
                createdAt: new Date().toISOString(),
            });
        }
    }
    // Successful approaches → remember
    for (const a of approaches.filter(a => a.status === 'accepted' || a.status === 'worked')) {
        const existing = thread.bridgeHints.find(h => h.text.includes(a.approach));
        if (!existing) {
            thread.bridgeHints.push({
                type: 'remember',
                text: `Approach that worked: "${a.approach}" — reuse if similar problem.`,
                confidence: 75,
                fromSessionId: thread.sessionCount,
                createdAt: new Date().toISOString(),
            });
        }
    }
    // File focus
    updateFileFocus(projectDir, files);
    saveThread(projectDir, thread);
}
// Get the supreme context block for insertion into prompt
function getContinuityBlock(context) {
    const lines = [];
    if (context.currentThread && context.currentThread.sessionCount > 0) {
        lines.push('🧵 CONTINUITY THREAD');
        lines.push(`   ${context.memoryThread}`);
        if (context.predictedNextSteps.length > 0) {
            lines.push('');
            lines.push('   🔮 LIKELY NEXT:');
            for (const step of context.predictedNextSteps.slice(0, 4)) {
                lines.push(`     → ${step}`);
            }
        }
        if (context.crossSessionWarnings.length > 0) {
            lines.push('');
            for (const w of context.crossSessionWarnings.slice(0, 3)) {
                lines.push(`   ⚠️  ${w}`);
            }
        }
        if (context.currentThread.bridgeHints.length > 0) {
            lines.push('');
            lines.push('   🧠 BRIDGE MEMORY:');
            for (const h of context.currentThread.bridgeHints.slice(-5)) {
                const icon = h.type === 'watch_out' ? '🚫' : h.type === 'remember' ? '✅' : '🔮';
                lines.push(`     ${icon} ${h.text}`);
            }
        }
    }
    else {
        lines.push('🧵 CONTINUITY THREAD');
        lines.push('   No prior context — fresh session.');
    }
    return lines.join('\n');
}
//# sourceMappingURL=context-continuity.js.map