"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_EXPIRED_DAYS = exports.DEFAULT_STALE_DAYS = void 0;
exports.buildContext = buildContext;
exports.formatContextForInjection = formatContextForInjection;
exports.formatContextForTool = formatContextForTool;
exports.estimateTokens = estimateTokens;
exports.getStalenessStatus = getStalenessStatus;
const database_1 = require("../../06-memory/database/database");
const logger_1 = require("../../06-memory/database/logger");
const context_continuity_1 = require("./context-continuity");
const context_bridge_1 = require("./context-bridge");
const context_predictor_1 = require("./context-predictor");
const team_supreme_1 = require("../../04-team/collab/team-supreme");
const community_supreme_1 = require("../../05-community/stats/community-supreme");
const _PROJECT_DIR = process.cwd();
function buildContext(projectPath, toolName) {
    const db = (0, database_1.getDb)();
    const profile = readProfile(db, projectPath);
    const blindSpots = readBlindSpots(db, projectPath);
    const topPatterns = readTopPatterns(db, projectPath);
    const recentActivity = readRecentActivity(db, projectPath);
    const skills = readSkills(db);
    const collaborators = readCollaborators(db);
    const toolStats = toolName ? readToolStats(db, toolName) : null;
    const stackDNA = readStackDNA(db, projectPath);
    const dbPredictions = readPredictions(db, projectPath);
    const lastSession = readLastSession(db, projectPath);
    const lastLiveFile = readLastLiveEvent(db, projectPath);
    const triedApproaches = readTriedApproaches(db, projectPath);
    const mostTouchedFiles = readMostTouchedFiles(db, projectPath);
    const openQuestions = readOpenQuestions(db, projectPath);
    const whoYouAre = buildWhoYouAre(profile, skills, collaborators, stackDNA, blindSpots);
    const rightNow = buildRightNow(recentActivity, profile, lastSession);
    const yourStyle = buildYourStyle(topPatterns, profile, skills);
    const watchOut = buildWatchOut(blindSpots, profile);
    const predictions = buildPredictions(blindSpots, recentActivity, toolStats);
    const toolHint = toolName ? buildToolHint(toolName) : undefined;
    const staleness = buildStalenessInfo(profile, recentActivity);
    // Phase 2D: Context ranker — top memories for AI context
    let keyMemories;
    try {
        const { getTopMemoriesForContext } = require('../../06-memory/stores/context-ranker');
        const project = projectPath ? require('path').basename(projectPath) : undefined;
        if (project) {
            const ranked = getTopMemoriesForContext(project, 1500);
            keyMemories = ranked.map((m) => ({ type: m.type, topic: m.topic, summary: m.summary, importance: m.importance, relevance: m.relevance }));
        }
    }
    catch { /* memory store not available */ }
    const ctx = {
        whoYouAre,
        rightNow,
        yourStyle,
        watchOut,
        predictions,
        dbPredictions,
        injectedAt: new Date().toISOString(),
        toolHint,
        lastSession,
        lastLiveFile,
        triedApproaches,
        mostTouchedFiles,
        openQuestions,
        staleness,
        keyMemories,
    };
    // Step 3.6: Vibe profile injection
    try {
        const { getVibeForContext } = require('../../06-memory/vibe/vibe-context');
        const vibe = getVibeForContext(projectPath);
        if (vibe)
            ctx.vibe = vibe.data;
    }
    catch { /* vibe not yet initialized */ }
    return ctx;
}
function formatContextForInjection(ctx, compact = false) {
    if (compact) {
        return compactContext(ctx);
    }
    return fullContext(ctx);
}
function formatContextForTool(ctx, toolName, projectNameOverride) {
    if (!toolName)
        return atCellBlock(ctx, projectNameOverride);
    const t = toolName.toLowerCase().trim();
    if (t === 'cell' || t === '@cell' || t === 'cell-block') {
        return atCellBlock(ctx, projectNameOverride);
    }
    if (t === 'claude-code' || t === 'claude' || t === 'claude-code-cli') {
        return atCellBlock(ctx, projectNameOverride);
    }
    if (t === 'cursor' || t === 'cursor-ide' || t === 'cursor-ai') {
        return formatForCursor(ctx, projectNameOverride);
    }
    if (t === 'windsurf' || t === 'codeium' || t === 'windsurf-ide') {
        return formatForWindsurf(ctx, projectNameOverride);
    }
    if (t === 'copilot' || t === 'github-copilot') {
        return formatForCopilot(ctx, projectNameOverride);
    }
    if (t === 'antigravity' || t === 'gemini' || t === 'aider' || t === 'continue-dev' || t === 'opencode') {
        return formatForAntigravity(ctx, projectNameOverride);
    }
    return atCellBlock(ctx, projectNameOverride);
}
// Compact `@cell` block format: matches the @cell Context convention from CLAUDE.md
// Updated to match the Pre-Launch Test 7 exact format spec:
//   ━━━━━━━━━━━━━━━━━━━━━━━━
//   ⚡ CELL CONTEXT — <project>
//   ━━━━━━━━━━━━━━━━━━━━━━━━
//
//   📦 PROJECT
//   Stack: ...
//
//   ⚠️ BLIND SPOTS:
//   → file:line
//
//   🎯 LAST SESSION
//   Working on: ...
function atCellBlock(ctx, projectNameOverride) {
    const lines = [];
    const divider = '━'.repeat(25);
    // ─── Staleness banner (top-priority) ────────────────────────────────
    if (ctx.staleness?.warning) {
        lines.push('> ' + ctx.staleness.warning);
        lines.push('');
    }
    // ─── Header (Pre-Launch Test 7 exact format) ────────────────────────
    lines.push(divider);
    const projectName = projectNameOverride || ctx.lastSession?.project || 'unknown project';
    lines.push(`⚡ CELL CONTEXT — ${projectName}`);
    lines.push(divider);
    lines.push('');
    // ─── 🎭 VIBE (Developer Personality) ─────────────────────────────────
    if (ctx.vibe) {
        lines.push(ctx.vibe);
        lines.push('');
    }
    // ─── 🌉 SUPREME CONTEXT: Bridge + Continuity + Predictions ───────────
    // These ensure AI never starts a session blind — always knows previous context
    try {
        const bridge = (0, context_bridge_1.peekSessionBridge)(_PROJECT_DIR);
        if (bridge && !bridge.consumed) {
            lines.push((0, context_bridge_1.formatBridgeForContext)(bridge));
            lines.push('');
        }
    }
    catch { }
    try {
        const continuityCtx = (0, context_continuity_1.buildContinuityContext)(_PROJECT_DIR, projectName);
        if (continuityCtx.currentThread && continuityCtx.currentThread.sessionCount > 0) {
            const block = (0, context_continuity_1.getContinuityBlock)(continuityCtx);
            if (block.split('\n').length > 2) {
                lines.push(block);
                lines.push('');
            }
        }
    }
    catch { }
    try {
        const predictorState = (0, context_predictor_1.predictContext)(projectName, _PROJECT_DIR);
        if (predictorState.predictions.length > 0) {
            lines.push((0, context_predictor_1.formatPredictions)(predictorState));
            lines.push('');
        }
    }
    catch { }
    // ─── 👥 TEAM CONTEXT ─────────────────────────────────────────────────
    try {
        const teamCtx = (0, team_supreme_1.buildTeamSupremeContext)();
        if (teamCtx.members.length > 0) {
            lines.push((0, team_supreme_1.formatTeamContext)(teamCtx));
            lines.push('');
        }
    }
    catch { }
    // ─── 🌍 COMMUNITY CONTEXT ────────────────────────────────────────────
    try {
        const communityCtx = (0, community_supreme_1.buildCommunitySupremeContext)();
        if (communityCtx.communityHealth.totalPatterns > 0) {
            lines.push((0, community_supreme_1.formatCommunityContext)(communityCtx));
            lines.push('');
        }
    }
    catch { }
    // ─── 📦 PROJECT (Stack + Developer Context) ─────────────────────────
    lines.push('📦 PROJECT');
    const developer = [];
    if (ctx.whoYouAre)
        developer.push(ctx.whoYouAre.split('\n')[0] || '');
    if (developer[0])
        lines.push(developer[0]);
    // Stack line
    const stackLine = ctx.yourStyle ? ctx.yourStyle.split('\n').filter(Boolean).slice(0, 1).join(' | ') : '';
    if (stackLine) {
        lines.push(`Stack: ${stackLine.replace(/^Stack:\s*/i, '')}`);
    }
    else {
        lines.push('Stack: (no scan yet — run `cell scan`)');
    }
    // Style details
    const styleLine = ctx.yourStyle ? ctx.yourStyle.split('\n').filter(Boolean).slice(0, 4).join(' | ') : '';
    if (styleLine && styleLine !== stackLine) {
        lines.push(`Style: ${styleLine.replace(/^Style:\s*/i, '')}`);
    }
    lines.push('');
    // ─── ⚠️ BLIND SPOTS ─────────────────────────────────────────────────
    lines.push('⚠️ BLIND SPOTS:');
    if (ctx.watchOut) {
        const watchItems = ctx.watchOut.split('\n').filter(Boolean).slice(0, 4);
        if (watchItems.length > 0) {
            for (const w of watchItems) {
                // Normalize: ensure → bullet prefix
                const line = w.trim().startsWith('→') ? w : `→ ${w}`;
                lines.push(line);
            }
        }
        else {
            lines.push('→ (none detected)');
        }
    }
    else {
        lines.push('→ (none detected)');
    }
    lines.push('');
    // ─── 🎯 LAST SESSION ───────────────────────────────────────────────
    lines.push('🎯 LAST SESSION');
    if (ctx.lastSession) {
        const ago = ctx.lastSession.endTime ? formatRelativeTime(ctx.lastSession.endTime) : 'active';
        const tool = ctx.lastSession.toolName || 'unknown';
        lines.push(`Tool: ${tool} (${ago})`);
        if (ctx.lastSession.contextSnapshot) {
            lines.push(`Working on: ${ctx.lastSession.contextSnapshot.split('\n')[0]}`);
        }
        if (ctx.lastSession.filesTouched.length > 0) {
            const lastFile = ctx.lastSession.filesTouched[0];
            lines.push(`Last file: ${lastFile}`);
        }
        if (ctx.lastSession.keyDecisions.length > 0) {
            lines.push(`Key decision: ${ctx.lastSession.keyDecisions[0]}`);
        }
    }
    else if (ctx.lastLiveFile) {
        // Fallback: when no explicit session has been opened, surface the most
        // recent live file event captured by the watcher. Prevents the "no session
        // yet" cold-start message from hiding real work the user is doing.
        const ago = ctx.lastLiveFile.createdAt ? formatRelativeTime(ctx.lastLiveFile.createdAt) : 'just now';
        const verb = ctx.lastLiveFile.eventType === 'file_save' ? 'saved' :
            ctx.lastLiveFile.eventType === 'file_create' ? 'created' :
                ctx.lastLiveFile.eventType === 'file_delete' ? 'deleted' : 'touched';
        lines.push(`Live: ${verb} ${ctx.lastLiveFile.filePath} (${ago})`);
        lines.push('Session: (open one with `cell session start` for full context)');
    }
    else {
        lines.push('Working on: (no session yet — first run)');
    }
    lines.push('');
    // ─── Key memories (top relevant) ─────────────────────────────────────
    if (ctx.keyMemories && ctx.keyMemories.length > 0) {
        lines.push('🧠 KEY MEMORIES');
        for (const m of ctx.keyMemories.slice(0, 5)) {
            const imp = m.importance >= 8 ? '★★' : m.importance >= 5 ? '★' : '';
            lines.push(`→ ${imp}[${m.type}] ${m.summary.substring(0, 100)}`);
        }
        lines.push('');
    }
    // ─── 🔮 PREDICTIONS (compact, optional) ─────────────────────────────
    if (ctx.predictions && ctx.predictions.trim()) {
        const predItems = ctx.predictions.split('\n').filter(Boolean).slice(0, 2);
        if (predItems.length > 0) {
            lines.push('🔮 PREDICTIONS');
            for (const p of predItems) {
                const line = p.trim().startsWith('→') ? p : `→ ${p}`;
                lines.push(line);
            }
            lines.push('');
        }
    }
    // ─── Tried approaches (collapse to one line) ────────────────────────
    if (ctx.triedApproaches.length > 0) {
        const triedLine = ctx.triedApproaches.slice(0, 3)
            .map(a => `${a.approach}(${a.status})`)
            .join(' | ');
        lines.push(`⏭️  TRIED (skip): ${triedLine}`);
        lines.push('');
    }
    // ─── Footer marker ──────────────────────────────────────────────────
    lines.push('# ─── End @cell Context ───');
    return lines.join('\n');
}
function estimateTokens(text) {
    return Math.ceil(text.length / 4);
}
function fullContext(ctx) {
    let out = '';
    out += '━━━ CELL CONTEXT ━━━\n\n';
    if (ctx.staleness?.warning) {
        out += '⚠ ' + ctx.staleness.warning + '\n\n';
    }
    out += '▸ WHO YOU ARE\n';
    out += ctx.whoYouAre + '\n\n';
    out += '▸ RIGHT NOW\n';
    out += ctx.rightNow + '\n\n';
    if (ctx.lastSession) {
        const ago = ctx.lastSession.endTime ? formatRelativeTime(ctx.lastSession.endTime) : 'active';
        out += '▸ LAST SESSION (' + ago + ')\n';
        out += `Tool: ${ctx.lastSession.toolName}\n`;
        if (ctx.lastSession.contextSnapshot) {
            out += `Working on: ${ctx.lastSession.contextSnapshot}\n`;
        }
        if (ctx.lastSession.keyDecisions.length > 0) {
            out += 'Key decisions: ' + ctx.lastSession.keyDecisions.slice(0, 3).join(' · ') + '\n';
        }
        out += '\n';
    }
    if (ctx.triedApproaches.length > 0) {
        out += '▸ TRIED ALREADY (don\'t suggest these)\n';
        for (const a of ctx.triedApproaches.slice(0, 5)) {
            out += `→ ${a.approach} — ${a.status}${a.count > 1 ? ` (${a.count}x)` : ''}\n`;
        }
        out += '\n';
    }
    if (ctx.openQuestions.length > 0) {
        out += '▸ OPEN QUESTIONS\n';
        for (const q of ctx.openQuestions.slice(0, 5)) {
            out += `→ [${q.priority}] ${q.question}\n`;
        }
        out += '\n';
    }
    out += '▸ YOUR STYLE\n';
    out += ctx.yourStyle + '\n\n';
    out += '▸ WATCH OUT\n';
    out += ctx.watchOut + '\n\n';
    if (ctx.mostTouchedFiles.length > 0) {
        out += '▸ HOT FILES (recently active)\n';
        for (const f of ctx.mostTouchedFiles.slice(0, 5)) {
            out += `→ ${f.filePath} (${f.touchCount} touches, ${f.sessionCount} sessions)\n`;
        }
        out += '\n';
    }
    if (ctx.keyMemories && ctx.keyMemories.length > 0) {
        out += '▸ KEY MEMORIES (top relevant)\n';
        for (const m of ctx.keyMemories.slice(0, 8)) {
            const imp = m.importance >= 8 ? '★★' : m.importance >= 5 ? '★' : '';
            out += `→ ${imp}[${m.type}] ${m.summary}${m.topic ? ` (${m.topic})` : ''}\n`;
        }
        out += '\n';
    }
    out += '▸ PREDICTIONS\n';
    out += ctx.predictions;
    if (ctx.toolHint) {
        out += '\n\n▸ TOOL HINT\n' + ctx.toolHint;
    }
    return out;
}
function compactContext(ctx) {
    let out = '';
    if (ctx.staleness?.warning) {
        out += '⚠ ' + ctx.staleness.warning + '\n\n';
    }
    out += '## Developer Context\n';
    out += ctx.whoYouAre.replace(/\n/g, ' | ') + '\n\n';
    out += '### Current\n';
    out += ctx.rightNow.replace(/\n/g, ' | ') + '\n\n';
    if (ctx.triedApproaches.length > 0) {
        out += '### Tried (skip these)\n';
        out += ctx.triedApproaches.slice(0, 3).map(a => `${a.approach}(${a.status})`).join(' | ') + '\n\n';
    }
    if (ctx.openQuestions.length > 0) {
        out += '### Open Questions\n';
        out += ctx.openQuestions.slice(0, 3).map(q => `[${q.priority}] ${q.question}`).join(' | ') + '\n\n';
    }
    out += '### Style\n';
    out += ctx.yourStyle.replace(/\n/g, ' | ') + '\n\n';
    out += '### Blind Spots\n';
    out += ctx.watchOut.replace(/\n/g, ' | ') + '\n\n';
    out += '### Predictions\n';
    out += ctx.predictions.replace(/\n/g, ' | ');
    if (ctx.toolHint) {
        out += '\n\n### Tool Note\n' + ctx.toolHint;
    }
    return out;
}
function formatForCursor(ctx, projectNameOverride) {
    const lines = [];
    const projectName = projectNameOverride || ctx.lastSession?.project || 'fivo-cell';
    lines.push(`@context ${projectName}`);
    if (ctx.staleness?.warning)
        lines.push('! ' + ctx.staleness.warning);
    if (ctx.lastSession) {
        lines.push('last: ' + ctx.lastSession.toolName + ' (' + (ctx.lastSession.endTime ? formatRelativeTime(ctx.lastSession.endTime) : 'active') + ')');
        if (ctx.lastSession.contextSnapshot)
            lines.push('working: ' + ctx.lastSession.contextSnapshot);
    }
    lines.push('');
    lines.push('style: ' + (ctx.yourStyle.split('\n')[0] || ''));
    if (ctx.triedApproaches.length > 0) {
        lines.push('avoid: ' + ctx.triedApproaches.slice(0, 3).map(a => `${a.approach}[${a.status}]`).join(', '));
    }
    if (ctx.openQuestions.length > 0) {
        lines.push('q: ' + ctx.openQuestions.slice(0, 2).map(q => `${q.question.slice(0, 50)}…`).join(' | '));
    }
    if (ctx.mostTouchedFiles.length > 0) {
        lines.push('hot: ' + ctx.mostTouchedFiles.slice(0, 3).map(f => f.filePath).join(', '));
    }
    if (ctx.watchOut) {
        const topBlindSpot = ctx.watchOut.split('\n').find(l => l.trim().startsWith('-'));
        if (topBlindSpot)
            lines.push('watch: ' + topBlindSpot.replace(/^-\s*/, '').slice(0, 80));
    }
    return lines.join('\n');
}
function formatForWindsurf(ctx, projectNameOverride) {
    const lines = [];
    const projectName = projectNameOverride || ctx.lastSession?.project || 'unknown';
    lines.push(`# Cell Context — ${projectName}`);
    if (ctx.staleness?.warning)
        lines.push('> ⚠ ' + ctx.staleness.warning);
    if (ctx.lastSession) {
        lines.push('## Last Session');
        lines.push(`- **Tool**: ${ctx.lastSession.toolName}`);
        if (ctx.lastSession.contextSnapshot)
            lines.push(`- **Working on**: ${ctx.lastSession.contextSnapshot}`);
        if (ctx.lastSession.keyDecisions.length > 0)
            lines.push(`- **Decisions**: ${ctx.lastSession.keyDecisions.slice(0, 2).join(', ')}`);
    }
    if (ctx.openQuestions.length > 0) {
        lines.push('## Open Questions');
        for (const q of ctx.openQuestions.slice(0, 3)) {
            lines.push(`- [${q.priority}] ${q.question}`);
        }
    }
    lines.push('## Style');
    lines.push(ctx.yourStyle.split('\n')[0] || '');
    lines.push('## Suggestions');
    if (ctx.watchOut) {
        const spots = ctx.watchOut.split('\n').filter(l => l.trim().startsWith('-')).slice(0, 3);
        spots.forEach(s => lines.push('- ' + s.replace(/^-\s*/, '')));
    }
    if (ctx.mostTouchedFiles.length > 0) {
        lines.push('## Active Files');
        ctx.mostTouchedFiles.slice(0, 3).forEach(f => lines.push(`- ${f.filePath} (${f.touchCount} touches)`));
    }
    return lines.join('\n');
}
function formatForCopilot(ctx, projectNameOverride) {
    const parts = [];
    if (ctx.staleness?.warning)
        parts.push('⚠ ' + ctx.staleness.warning.replace(/`/g, ''));
    parts.push('Project: ' + (projectNameOverride || ctx.lastSession?.project || 'unknown'));
    if (ctx.lastSession?.contextSnapshot)
        parts.push('Working: ' + ctx.lastSession.contextSnapshot.slice(0, 60));
    if (ctx.triedApproaches.length > 0) {
        const a = ctx.triedApproaches[0];
        parts.push(`Avoid: ${a.approach} (${a.status})`);
    }
    const styleLine = ctx.yourStyle.split('\n')[0] || '';
    if (styleLine)
        parts.push('Style: ' + styleLine.slice(0, 80));
    return parts.join(' · ');
}
function formatForAntigravity(ctx, projectNameOverride) {
    const lines = [];
    const projectName = projectNameOverride || ctx.lastSession?.project || 'unknown';
    lines.push('## Cell Context — Structured');
    if (ctx.staleness?.warning)
        lines.push('> ⚠ ' + ctx.staleness.warning);
    lines.push('');
    lines.push('```yaml');
    lines.push(`project: ${projectName}`);
    lines.push(`tool_hint: ${ctx.toolHint || 'general'}`);
    if (ctx.lastSession) {
        lines.push(`last_session:`);
        lines.push(`  tool: ${ctx.lastSession.toolName}`);
        lines.push(`  when: ${ctx.lastSession.endTime || 'active'}`);
        if (ctx.lastSession.contextSnapshot)
            lines.push(`  context: "${ctx.lastSession.contextSnapshot}"`);
        if (ctx.lastSession.filesTouched.length > 0) {
            lines.push(`  files:`);
            ctx.lastSession.filesTouched.slice(0, 3).forEach(f => lines.push(`    - ${f}`));
        }
    }
    else if (ctx.lastLiveFile) {
        // Fallback: show most recent file save when no session is open
        const ago = ctx.lastLiveFile.createdAt ? formatRelativeTime(ctx.lastLiveFile.createdAt) : 'just now';
        const verb = ctx.lastLiveFile.eventType === 'file_save' ? 'saved' :
            ctx.lastLiveFile.eventType === 'file_create' ? 'created' :
                ctx.lastLiveFile.eventType === 'file_delete' ? 'deleted' : 'touched';
        lines.push(`last_live_file:`);
        lines.push(`  event: ${ctx.lastLiveFile.eventType}`);
        lines.push(`  file: "${ctx.lastLiveFile.filePath}"`);
        lines.push(`  when: ${ago}`);
        lines.push(`  note: "no session open — open one with cell_session_start for full context"`);
    }
    if (ctx.triedApproaches.length > 0) {
        lines.push(`tried_approaches:`);
        ctx.triedApproaches.slice(0, 3).forEach(a => {
            lines.push(`  - approach: "${a.approach}"`);
            lines.push(`    status: ${a.status}`);
        });
    }
    if (ctx.openQuestions.length > 0) {
        lines.push(`open_questions:`);
        ctx.openQuestions.slice(0, 3).forEach(q => {
            lines.push(`  - priority: ${q.priority}`);
            lines.push(`    question: "${q.question}"`);
        });
    }
    // Surface top blind spots and style as concise YAML keys so the AI can act
    // on them without falling back to git/filesystem.
    if (ctx.watchOut) {
        const watchItems = ctx.watchOut.split('\n').filter(Boolean).slice(0, 5);
        if (watchItems.length > 0) {
            lines.push(`blind_spots:`);
            watchItems.forEach(w => {
                const cleaned = w.replace(/^[→\-•\s]+/, '').slice(0, 100);
                lines.push(`  - "${cleaned}"`);
            });
        }
    }
    if (ctx.yourStyle) {
        const styleLine = ctx.yourStyle.split('\n').filter(Boolean).slice(0, 2).join(' | ').slice(0, 160);
        if (styleLine) {
            lines.push(`style: "${styleLine.replace(/^Stack:\s*/i, '').replace(/"/g, '\'')}"`);
        }
    }
    if (ctx.mostTouchedFiles.length > 0) {
        lines.push(`hot_files:`);
        ctx.mostTouchedFiles.slice(0, 3).forEach(f => {
            lines.push(`  - path: "${f.filePath}"`);
            lines.push(`    touches: ${f.touchCount}`);
        });
    }
    lines.push('```');
    return lines.join('\n');
}
function readProfile(db, projectPath) {
    try {
        const row = projectPath
            ? db.prepare('SELECT * FROM developer_profiles WHERE project = ? ORDER BY scanned_at DESC LIMIT 1').get(projectPath)
            : db.prepare('SELECT * FROM developer_profiles ORDER BY scanned_at DESC LIMIT 1').get();
        if (row) {
            return {
                name: row.project || '',
                project: row.project || '',
                naming_style: row.naming_style || '',
                quote_style: row.quote_style || '',
                semicolon_style: row.semicolon_style || '',
                indent_style: row.indent_style || '',
                async_style: row.async_style || '',
                error_handling: row.error_handling || '',
                function_style: row.function_style || '',
                import_style: row.import_style || '',
                export_style: row.export_style || '',
                comment_style: row.comment_style || '',
                architecture_style: row.architecture_style || '',
                test_pattern: row.test_pattern || '',
                top_patterns: safeJson(row.top_patterns),
                strengths: safeJson(row.strengths),
                improvements: safeJson(row.improvements),
                files_scanned: row.files_scanned || 0,
                total_lines: row.total_lines || 0,
                scanned_at: row.scanned_at || '',
            };
        }
    }
    catch (e) {
        logger_1.logger.warn('readProfile: ' + String(e));
    }
    return {};
}
function readBlindSpots(db, projectPath) {
    try {
        if (projectPath) {
            return db.prepare("SELECT pattern_type, pattern_value, count, trust_score FROM code_patterns WHERE category = 'blind_spots' AND project = ? ORDER BY trust_score DESC, count DESC LIMIT 10").all(projectPath);
        }
        return db.prepare("SELECT pattern_type, pattern_value, count, trust_score FROM code_patterns WHERE category = 'blind_spots' ORDER BY trust_score DESC, count DESC LIMIT 10").all();
    }
    catch {
        return [];
    }
}
function readTopPatterns(db, projectPath) {
    try {
        if (projectPath) {
            return db.prepare("SELECT pattern_type, pattern_value, category, count, trust_score FROM code_patterns WHERE project = ? AND category != 'blind_spots' ORDER BY trust_score DESC, count DESC LIMIT 15").all(projectPath);
        }
        return db.prepare("SELECT pattern_type, pattern_value, category, count, trust_score FROM code_patterns WHERE category != 'blind_spots' ORDER BY trust_score DESC, count DESC LIMIT 15").all();
    }
    catch {
        return [];
    }
}
function readRecentActivity(db, projectPath) {
    try {
        if (projectPath) {
            return db.prepare('SELECT * FROM scans WHERE project = ? ORDER BY completed_at DESC LIMIT 5').all(projectPath);
        }
        return db.prepare('SELECT * FROM scans ORDER BY completed_at DESC LIMIT 5').all();
    }
    catch {
        return [];
    }
}
function readSkills(db) {
    try {
        return db.prepare('SELECT * FROM skills WHERE language != "0" AND language != "1" AND language != "2" AND language != "3" AND language != "4" ORDER BY confidence DESC').all();
    }
    catch {
        return [];
    }
}
function readCollaborators(db) {
    try {
        return db.prepare('SELECT * FROM collaborators LIMIT 10').all();
    }
    catch {
        return [];
    }
}
function readToolStats(db, toolName) {
    try {
        return db.prepare('SELECT * FROM model_profiles WHERE model_name = ? LIMIT 1').get(toolName) || null;
    }
    catch {
        return null;
    }
}
function readStackDNA(db, projectPath) {
    try {
        const query = projectPath
            ? "SELECT pattern_value FROM code_patterns WHERE pattern_type = 'project_dna' AND project = ?"
            : "SELECT pattern_value FROM code_patterns WHERE pattern_type = 'project_dna'";
        const params = projectPath ? [projectPath] : [];
        const row = db.prepare(query).get(...(params));
        if (row?.pattern_value)
            return JSON.parse(row.pattern_value);
        return null;
    }
    catch {
        return null;
    }
}
function readPredictions(db, projectPath) {
    try {
        const errors = db.prepare("SELECT error_message, COUNT(*) as cnt FROM error_log GROUP BY error_message HAVING cnt > 1 ORDER BY cnt DESC LIMIT 5").all();
        return errors.map(e => `${e.error_message} — ${e.cnt}x repeated`);
    }
    catch {
        return [];
    }
}
function readLastSession(db, projectPath) {
    try {
        const query = projectPath
            ? 'SELECT * FROM sessions WHERE project = ? AND end_time IS NOT NULL ORDER BY end_time DESC LIMIT 1'
            : 'SELECT * FROM sessions WHERE end_time IS NOT NULL ORDER BY end_time DESC LIMIT 1';
        const params = projectPath ? [projectPath] : [];
        const row = db.prepare(query).get(...(params));
        if (!row)
            return undefined;
        return {
            id: Number(row.id),
            toolName: String(row.tool_name || ''),
            project: String(row.project || ''),
            startTime: String(row.start_time || ''),
            endTime: row.end_time ? String(row.end_time) : undefined,
            filesTouched: safeJson(String(row.files_touched)) || [],
            keyDecisions: safeJson(String(row.key_decisions)) || [],
            contextSnapshot: String(row.context_snapshot || ''),
        };
    }
    catch {
        return undefined;
    }
}
function readLastLiveEvent(db, projectPath) {
    try {
        const query = projectPath
            ? "SELECT * FROM live_events WHERE project = ? AND file_path IS NOT NULL AND file_path != '' ORDER BY id DESC LIMIT 1"
            : "SELECT * FROM live_events WHERE file_path IS NOT NULL AND file_path != '' ORDER BY id DESC LIMIT 1";
        const params = projectPath ? [projectPath] : [];
        const row = db.prepare(query).get(...params);
        if (!row)
            return undefined;
        return {
            filePath: String(row.file_path || ''),
            eventType: String(row.event_type || 'file_save'),
            createdAt: String(row.created_at || ''),
        };
    }
    catch {
        return undefined;
    }
}
function readTriedApproaches(db, projectPath) {
    try {
        const query = projectPath
            ? `SELECT approach, status, COUNT(*) as count, MAX(reason) as last_reason, MAX(created_at) as last_seen
         FROM session_approaches
         WHERE project = ?
         GROUP BY LOWER(approach)
         ORDER BY count DESC, last_seen DESC
         LIMIT 10`
            : `SELECT approach, status, COUNT(*) as count, MAX(reason) as last_reason, MAX(created_at) as last_seen
         FROM session_approaches
         GROUP BY LOWER(approach)
         ORDER BY count DESC, last_seen DESC
         LIMIT 10`;
        const params = projectPath ? [projectPath] : [];
        const rows = db.prepare(query).all(...(params));
        return rows.map(r => ({
            approach: r.approach,
            status: r.status,
            count: r.count,
            lastReason: r.last_reason,
            lastSeen: r.last_seen,
        }));
    }
    catch {
        return [];
    }
}
function readMostTouchedFiles(db, projectPath) {
    try {
        const query = projectPath
            ? `SELECT file_path, SUM(touch_count) as total_touches, COUNT(DISTINCT session_id) as session_count, MAX(last_touched) as last_touched
         FROM session_files
         WHERE project = ?
         GROUP BY file_path
         ORDER BY total_touches DESC, last_touched DESC
         LIMIT 10`
            : `SELECT file_path, SUM(touch_count) as total_touches, COUNT(DISTINCT session_id) as session_count, MAX(last_touched) as last_touched
         FROM session_files
         GROUP BY file_path
         ORDER BY total_touches DESC, last_touched DESC
         LIMIT 10`;
        const params = projectPath ? [projectPath] : [];
        const rows = db.prepare(query).all(...(params));
        return rows.map(r => ({
            filePath: r.file_path,
            touchCount: r.total_touches,
            sessionCount: r.session_count,
            lastTouched: r.last_touched,
        }));
    }
    catch {
        return [];
    }
}
function readOpenQuestions(db, projectPath) {
    try {
        const query = projectPath
            ? `SELECT * FROM session_questions
         WHERE project = ? AND resolved = 0
         ORDER BY CASE priority WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END, created_at DESC
         LIMIT 10`
            : `SELECT * FROM session_questions
         WHERE resolved = 0
         ORDER BY CASE priority WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END, created_at DESC
         LIMIT 10`;
        const params = projectPath ? [projectPath] : [];
        const rows = db.prepare(query).all(...(params));
        return rows.map(r => ({
            id: Number(r.id),
            question: String(r.question || ''),
            priority: String(r.priority || 'medium'),
            resolved: Boolean(r.resolved),
            answer: r.answer ? String(r.answer) : null,
            createdAt: String(r.created_at || ''),
        }));
    }
    catch {
        return [];
    }
}
function buildWhoYouAre(profile, skills, collaborators, stackDNA, blindSpots) {
    const lines = [];
    if (profile.project) {
        const files = profile.files_scanned || 0;
        const lines1 = profile.total_lines || 0;
        lines.push(`Project: ${profile.project} (${files} files, ${lines1} lines)`);
    }
    if (stackDNA && typeof stackDNA === 'object') {
        const s = stackDNA;
        const parts = [];
        if (s.languages && s.languages.length > 0)
            parts.push(`Languages: ${s.languages.join(', ')}`);
        if (s.frontend && s.frontend !== 'none')
            parts.push(`Frontend: ${s.frontend}`);
        if (s.backend && s.backend !== 'none')
            parts.push(`Backend: ${s.backend}`);
        if (s.database && s.database[0] !== 'none')
            parts.push(`DB: ${s.database.join(', ')}`);
        if (s.orm && s.orm !== 'none')
            parts.push(`ORM: ${s.orm}`);
        if (s.testing && s.testing[0] !== 'none')
            parts.push(`Test: ${s.testing.join(', ')}`);
        if (s.validation && s.validation !== 'none')
            parts.push(`Validation: ${s.validation}`);
        if (parts.length > 0)
            lines.push(parts.join(' · '));
    }
    const skillLanguages = skills.filter((s) => s.level !== 'learning' && s.level !== 'new').map((s) => s.language);
    if (skillLanguages.length > 0)
        lines.push(`Proficient: ${skillLanguages.join(', ')}`);
    if (collaborators.length > 0) {
        const names = collaborators.slice(0, 3).map((c) => c.name).filter(Boolean);
        lines.push(`Team: ${names.join(', ')} (${collaborators.length} total)`);
    }
    const strengths = profile.strengths || [];
    if (strengths.length > 0) {
        lines.push(`Strengths: ${strengths.slice(0, 3).join(' · ')}`);
    }
    if (blindSpots && blindSpots.length > 0) {
        const top = blindSpots.slice(0, 3).map(b => `${b.pattern_value || b.description || 'unknown'} (${b.count || 0}x)`).filter(Boolean);
        if (top.length > 0)
            lines.push(`⚠ Blind spots: ${top.join(' | ')}`);
    }
    if (lines.length === 0) {
        lines.push('Developer profile — run `cell scan` to build profile');
    }
    return lines.join('\n');
}
function buildRightNow(activity, profile, lastSession) {
    const lines = [];
    if (lastSession) {
        const ago = lastSession.endTime ? formatRelativeTime(lastSession.endTime) : 'in progress';
        lines.push(`Last session: ${ago} (${lastSession.toolName})`);
        if (lastSession.contextSnapshot) {
            lines.push(`Working on: ${lastSession.contextSnapshot}`);
        }
        if (lastSession.keyDecisions.length > 0) {
            lines.push(`Decisions: ${lastSession.keyDecisions.slice(0, 3).join(' · ')}`);
        }
        if (lastSession.filesTouched.length > 0) {
            lines.push(`Current file: ${lastSession.filesTouched[0]}`);
        }
    }
    else if (activity.length > 0) {
        const lastScan = activity[0];
        lines.push(`Last scan: ${lastScan.files_scanned || 0} files scanned`);
        if (lastScan.completed_at) {
            lines.push(`Last active: ${formatRelativeTime(lastScan.completed_at)}`);
        }
        if (lastScan.project) {
            lines.push(`Project: ${lastScan.project}`);
        }
    }
    else {
        lines.push('No recent activity detected');
        lines.push('Run `cell scan` to refresh');
    }
    if (profile.scanned_at) {
        lines.push(`Profile last built: ${formatRelativeTime(profile.scanned_at)}`);
    }
    return lines.join('\n');
}
function buildYourStyle(patterns, profile, skills) {
    const lines = [];
    const styleBits = [];
    if (profile.quote_style)
        styleBits.push(`Quotes: ${profile.quote_style}`);
    if (profile.semicolon_style)
        styleBits.push(`Semicolons: ${profile.semicolon_style}`);
    if (profile.indent_style)
        styleBits.push(`Indent: ${profile.indent_style}`);
    if (profile.naming_style)
        styleBits.push(`Naming: ${profile.naming_style}`);
    if (profile.async_style)
        styleBits.push(`Async: ${profile.async_style}`);
    if (profile.error_handling)
        styleBits.push(`Errors: ${profile.error_handling}`);
    if (profile.function_style)
        styleBits.push(`Functions: ${profile.function_style}`);
    if (profile.test_pattern)
        styleBits.push(`Tests: ${profile.test_pattern}`);
    if (styleBits.length > 0) {
        lines.push(styleBits.join(' · '));
    }
    const categories = new Map();
    for (const p of patterns) {
        const cat = String(p.category || '');
        categories.set(cat, (categories.get(cat) || 0) + 1);
    }
    const sortedCats = [...categories.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5);
    if (sortedCats.length > 0) {
        lines.push(`Top patterns: ${sortedCats.map(([c, n]) => `${c}(${n})`).join(', ')}`);
    }
    const doList = [];
    for (const p of patterns) {
        const rule = String(p.pattern_value || '');
        const cat = String(p.category || '');
        if (cat === 'typescript_strict' || rule.toLowerCase().includes('type')) {
            doList.push('DO: TypeScript strict mode');
        }
        if (cat === 'async' || rule.toLowerCase().includes('async') || profile.async_style === 'uses-async') {
            doList.push('DO: Use async/await, not .then()');
        }
        if (cat === 'null_safety' || rule.toLowerCase().includes('optional')) {
            doList.push('DO: Use optional chaining');
        }
        if (cat === 'destructuring' || rule.toLowerCase().includes('destructur')) {
            doList.push('DO: Use destructuring over index access');
        }
    }
    const unique = [...new Set(doList)];
    if (unique.length > 0) {
        lines.push('');
        lines.push('DO list:');
        unique.forEach(d => lines.push('  ' + d));
    }
    lines.push('');
    lines.push("DON'T list:");
    lines.push('  - Use var (use const/let)');
    lines.push('  - Skip try/catch on async');
    lines.push('  - Skip null checks on API responses');
    return lines.join('\n');
}
function buildWatchOut(blindSpots, profile) {
    const lines = [];
    if (blindSpots.length === 0) {
        lines.push('No blind spots detected yet.');
        lines.push('Run `cell scan` to detect error handling, null safety, and validation gaps');
        return lines.join('\n');
    }
    const top = blindSpots.slice(0, 5);
    if (top.length > 0) {
        const topItem = top[0];
        const topDesc = String(topItem.pattern_value || topItem.description || 'unknown');
        lines.push(`Top current risk: ${topDesc}`);
    }
    lines.push(`Top blind spots (${blindSpots.length} total):`);
    for (const s of top) {
        const desc = String(s.pattern_value || s.description || 'unknown');
        const count = s.count || 0;
        const trust = s.trust_score || 0;
        if (desc)
            lines.push(`  - [${count}x, trust ${trust}] ${desc}`);
    }
    if (top.length > 0) {
        const topItem = top[0];
        const topType = String(topItem.pattern_type || '');
        if (topType.includes('async_notry') || topType.includes('error_handling')) {
            lines.push('Recommended next fix: add try/catch to async paths');
        }
        else if (topType.includes('null')) {
            lines.push('Recommended next fix: add null checks before property access');
        }
        else if (topType.includes('any_type')) {
            lines.push('Recommended next fix: replace `any` with proper types');
        }
        else if (topType.includes('deep_nesting')) {
            lines.push('Recommended next fix: extract nested logic into helper functions');
        }
        else if (topType.includes('validation')) {
            lines.push('Recommended next fix: add input validation to API routes');
        }
    }
    if (profile.improvements && Array.isArray(profile.improvements) && profile.improvements.length > 0) {
        lines.push('');
        lines.push('Suggested improvements:');
        const improvements = profile.improvements;
        improvements.slice(0, 3).forEach((imp) => lines.push('  - ' + imp));
    }
    return lines.join('\n');
}
function buildPredictions(blindSpots, activity, toolStats) {
    const lines = [];
    const highTrustBlindSpots = blindSpots.filter((b) => b.trust_score >= 80).length;
    if (highTrustBlindSpots > 0) {
        lines.push(`⚠ ${highTrustBlindSpots} high-confidence blind spots likely to recur`);
    }
    if (toolStats) {
        const acceptRate = toolStats.acceptance_rate;
        if (acceptRate !== undefined) {
            lines.push(`Tool acceptance rate: ${Math.round(acceptRate * 100)}%`);
            if (acceptRate < 0.5) {
                lines.push('⚠ Low acceptance rate — consider different tool or prompt style');
            }
        }
    }
    if (activity.length > 0) {
        const lastScan = activity[0];
        if (lastScan.completed_at) {
            lines.push(`Last scan: ${formatRelativeTime(lastScan.completed_at)}`);
        }
    }
    if (lines.length === 0) {
        lines.push('No active predictions');
    }
    return lines.join('\n');
}
function buildToolHint(toolName) {
    const hints = {
        'cursor': 'Cursor — best for: component generation, quick refactors, boilerplate',
        'claude': 'Claude Code — best for: architecture, complex logic, system design',
        'claude-code': 'Claude Code — best for: architecture, complex logic, system design',
        'windsurf': 'Windsurf — best for: multi-file refactors, large codebase navigation',
        'copilot': 'GitHub Copilot — best for: inline completions, quick suggestions',
        'antigravity': 'Antigravity — best for: full-featured AI coding with context',
    };
    return hints[toolName.toLowerCase()] || `${toolName} — general AI coding tool`;
}
function formatRelativeTime(dateStr) {
    try {
        // SQLite datetime('now') returns UTC without TZ marker. Force UTC parse
        // so "5 hours ago" doesn't show for events that just happened in IST.
        const d = new Date(dateStr.endsWith('Z') || /[+-]\d{2}:?\d{2}$/.test(dateStr)
            ? dateStr
            : dateStr.replace(' ', 'T') + 'Z');
        const now = new Date();
        const diff = now.getTime() - d.getTime();
        const mins = Math.floor(diff / 60000);
        if (mins < 1)
            return 'just now';
        if (mins < 60)
            return `${mins}m ago`;
        const hours = Math.floor(mins / 60);
        if (hours < 24)
            return `${hours}h ago`;
        const days = Math.floor(hours / 24);
        return `${days}d ago`;
    }
    catch {
        return 'unknown';
    }
}
function safeJson(val) {
    if (!val)
        return null;
    try {
        return JSON.parse(val);
    }
    catch {
        return val;
    }
}
exports.DEFAULT_STALE_DAYS = 7;
exports.DEFAULT_EXPIRED_DAYS = 30;
function getStalenessStatus(timestamp, staleDays = exports.DEFAULT_STALE_DAYS, expiredDays = exports.DEFAULT_EXPIRED_DAYS) {
    if (!timestamp)
        return 'unknown';
    const t = new Date(timestamp).getTime();
    if (!Number.isFinite(t))
        return 'unknown';
    const ageMs = Date.now() - t;
    if (ageMs < 0)
        return 'fresh';
    const days = ageMs / (1000 * 60 * 60 * 24);
    if (days < staleDays)
        return 'fresh';
    if (days < expiredDays)
        return 'stale';
    return 'expired';
}
function daysSince(timestamp) {
    if (!timestamp)
        return null;
    const t = new Date(timestamp).getTime();
    if (!Number.isFinite(t))
        return null;
    const days = (Date.now() - t) / (1000 * 60 * 60 * 24);
    return Math.max(0, Math.round(days * 10) / 10);
}
function buildStalenessInfo(profile, recentActivity) {
    const profileTs = profile.scanned_at || undefined;
    const scanTs = recentActivity[0]?.completed_at || undefined;
    const profileLevel = getStalenessStatus(profileTs);
    const scanLevel = getStalenessStatus(scanTs);
    const daysSinceProfile = daysSince(profileTs);
    const daysSinceScan = daysSince(scanTs);
    const shouldRescan = profileLevel === 'stale' || profileLevel === 'expired' || scanLevel === 'stale' || scanLevel === 'expired';
    let warning = null;
    if (profileLevel === 'expired') {
        warning = `Profile is ${daysSinceProfile ?? '?'} days old — run \`cell scan\` to refresh (context may be outdated)`;
    }
    else if (profileLevel === 'stale') {
        warning = `Profile is ${daysSinceProfile ?? '?'} days old — consider running \`cell scan\` to keep context fresh`;
    }
    else if (scanLevel === 'expired' || scanLevel === 'stale') {
        warning = `Last scan is ${daysSinceScan ?? '?'} days old — run \`cell scan\` to refresh`;
    }
    return {
        profile: profileLevel,
        scan: scanLevel,
        daysSinceProfile,
        daysSinceScan,
        shouldRescan,
        warning,
    };
}
//# sourceMappingURL=prompt-builder.js.map