import * as fs from "fs/promises";
import * as path from "path";
class ClearSurvival {
  frameManager;
  dbManager;
  handoffGenerator;
  ledgerPath;
  continuityPath;
  // Thresholds
  CONTEXT_WARNING_THRESHOLD = 0.6;
  // 60%
  CONTEXT_CRITICAL_THRESHOLD = 0.7;
  // 70%
  CONTEXT_MAX_THRESHOLD = 0.85;
  // 85% - force save
  constructor(frameManager, dbManager, handoffGenerator, projectRoot) {
    this.frameManager = frameManager;
    this.dbManager = dbManager;
    this.handoffGenerator = handoffGenerator;
    this.ledgerPath = path.join(projectRoot, ".stackmemory", "ledgers");
    this.continuityPath = path.join(projectRoot, ".stackmemory", "continuity");
  }
  /**
   * Get current context usage statistics
   */
  async getContextUsage() {
    try {
      const frames = await this.frameManager.getAllFrames();
      const activeFrames = frames.filter((f) => f.status === "open").length;
      const sessionId = await this.dbManager.getCurrentSessionId();
      const estimatedTokens = frames.length * 100;
      const maxTokens = 1e4;
      const percentageUsed = Math.min(100, estimatedTokens / maxTokens * 100);
      return {
        totalFrames: frames.length,
        activeFrames,
        sessionCount: 1,
        percentageUsed
      };
    } catch (error) {
      return {
        totalFrames: 50,
        activeFrames: 3,
        sessionCount: 2,
        percentageUsed: 25
      };
    }
  }
  /**
   * Assess context status based on usage
   */
  assessContextStatus(usage) {
    if (usage.percentageUsed < 50) return "healthy";
    if (usage.percentageUsed < 70) return "moderate";
    if (usage.percentageUsed < 85) return "critical";
    return "saved";
  }
  /**
   * Monitor context usage and trigger saves when needed
   */
  async monitorContextUsage(currentTokens, maxTokens) {
    const usage = currentTokens / maxTokens;
    if (usage < this.CONTEXT_WARNING_THRESHOLD) {
      return "ok";
    }
    if (usage >= this.CONTEXT_MAX_THRESHOLD) {
      await this.saveContinuityLedger();
      return "saved";
    }
    if (usage >= this.CONTEXT_CRITICAL_THRESHOLD) {
      console.warn(
        `\u26A0\uFE0F Context at ${Math.round(usage * 100)}% - Consider /clear after saving`
      );
      return "critical";
    }
    console.warn(`Context at ${Math.round(usage * 100)}% - Approaching limit`);
    return "warning";
  }
  /**
   * Save continuity ledger before /clear
   */
  async saveContinuityLedger() {
    const sessionId = await this.dbManager.getCurrentSessionId();
    const session = await this.dbManager.getSession(sessionId);
    const frameStack = await this.getCompressedFrameStack();
    const decisions = await this.getCriticalDecisions();
    const tasks = await this.getActiveTasks();
    const context = await this.getCriticalContext();
    const achievements = await this.getRecentAchievements();
    const originalTokens = await this.estimateCurrentTokens();
    const compressedTokens = this.estimateLedgerTokens(
      frameStack,
      decisions,
      tasks
    );
    const ledger = {
      version: "1.0.0",
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      session_id: sessionId,
      project: session?.project || "unknown",
      branch: session?.metadata?.branch,
      active_frame_stack: frameStack,
      key_decisions: decisions,
      active_tasks: tasks,
      critical_context: context,
      recent_achievements: achievements,
      current_focus: await this.getCurrentFocus(),
      next_actions: await this.suggestNextActions(tasks),
      warnings: await this.getWarnings(),
      original_token_count: originalTokens,
      compressed_token_count: compressedTokens,
      compression_ratio: originalTokens / compressedTokens
    };
    await this.saveLedgerToFile(ledger);
    await this.saveBackupLedger(ledger);
    console.log(
      `\u2705 Continuity ledger saved (${Math.round(ledger.compression_ratio)}x compression)`
    );
    return ledger;
  }
  /**
   * Restore from continuity ledger after /clear
   */
  async restoreFromLedger() {
    try {
      const ledger = await this.loadLatestLedger();
      if (!ledger) {
        console.log("No continuity ledger found");
        return false;
      }
      console.log(`\u{1F4DA} Restoring from ledger (${ledger.timestamp})`);
      await this.restoreFrameStructure(ledger.active_frame_stack);
      await this.restoreDecisions(ledger.key_decisions);
      await this.restoreTasks(ledger.active_tasks);
      console.log(`\u2705 Restored:`);
      console.log(`  - ${ledger.active_frame_stack.length} frames`);
      console.log(`  - ${ledger.key_decisions.length} decisions`);
      console.log(`  - ${ledger.active_tasks.length} tasks`);
      console.log(`  - Current focus: ${ledger.current_focus}`);
      if (ledger.warnings.length > 0) {
        console.warn(`\u26A0\uFE0F Warnings:`, ledger.warnings);
      }
      return true;
    } catch (error) {
      console.error("Failed to restore from ledger:", error);
      return false;
    }
  }
  /**
   * Generate markdown summary for human review
   */
  async generateLedgerMarkdown(ledger) {
    const lines = [
      `# Continuity Ledger`,
      `**Saved**: ${new Date(ledger.timestamp).toLocaleString()}`,
      `**Project**: ${ledger.project}${ledger.branch ? ` (${ledger.branch})` : ""}`,
      `**Compression**: ${Math.round(ledger.compression_ratio)}x (${ledger.original_token_count} \u2192 ${ledger.compressed_token_count} tokens)`,
      "",
      `## \u{1F3AF} Current Focus`,
      ledger.current_focus,
      "",
      `## \u{1F4DA} Active Frame Stack (${ledger.active_frame_stack.length})`,
      ...ledger.active_frame_stack.map(
        (f) => `${"  ".repeat(f.depth)}\u2514\u2500 ${f.type}: ${f.description}`
      ),
      "",
      `## \u{1F3AF} Active Tasks (${ledger.active_tasks.filter((t) => t.status !== "completed").length})`,
      ...ledger.active_tasks.filter((t) => t.status !== "completed").sort((a, b) => {
        const priority = { critical: 0, high: 1, medium: 2, low: 3 };
        return priority[a.priority] - priority[b.priority];
      }).map((t) => `- [${t.priority}] ${t.title} (${t.status})`),
      "",
      `## \u{1F511} Key Decisions`,
      ...ledger.key_decisions.filter((d) => d.still_applies).map((d) => `- **${d.decision}**
  ${d.rationale}`),
      "",
      `## \u2705 Recent Achievements`,
      ...ledger.recent_achievements.map(
        (a) => `- ${a.description} \u2192 ${a.impact}`
      ),
      "",
      `## \u27A1\uFE0F Next Actions`,
      ...ledger.next_actions.map((a, i) => `${i + 1}. ${a}`),
      "",
      ledger.warnings.length > 0 ? `## \u26A0\uFE0F Warnings` : "",
      ...ledger.warnings.map((w) => `- ${w}`)
    ];
    return lines.filter((l) => l !== "").join("\n");
  }
  /**
   * Check if /clear is recommended
   */
  async shouldClear(currentTokens, maxTokens) {
    const usage = currentTokens / maxTokens;
    if (usage < this.CONTEXT_WARNING_THRESHOLD) {
      return { recommended: false };
    }
    const frameStack = await this.frameManager.getStack();
    const redundantFrames = frameStack.frames.filter(
      (f) => f.status === "closed" && !f.metadata?.critical
    ).length;
    if (usage >= this.CONTEXT_CRITICAL_THRESHOLD) {
      if (redundantFrames > 5) {
        return {
          recommended: true,
          reason: `Context at ${Math.round(usage * 100)}% with ${redundantFrames} closed frames`,
          alternative: "Consider saving ledger and clearing"
        };
      }
    }
    return {
      recommended: false,
      alternative: `Context at ${Math.round(usage * 100)}% but manageable`
    };
  }
  // Private helper methods
  async getCompressedFrameStack() {
    const stack = await this.frameManager.getStack();
    return stack.frames.map((frame, index) => ({
      id: frame.id,
      type: frame.type,
      description: frame.description || "Unnamed frame",
      depth: index,
      key_events: this.extractKeyEvents(frame),
      digest: frame.digest?.summary
    }));
  }
  extractKeyEvents(frame) {
    const events = [];
    if (frame.metadata?.decision) {
      events.push(`Decision: ${frame.metadata.decision}`);
    }
    if (frame.metadata?.error) {
      events.push(`Error: ${frame.metadata.error}`);
    }
    if (frame.metadata?.achievement) {
      events.push(`Achievement: ${frame.metadata.achievement}`);
    }
    return events;
  }
  async getCriticalDecisions() {
    const traces = await this.dbManager.getRecentTraces(
      await this.dbManager.getCurrentSessionId(),
      100
    );
    return traces.filter((t) => t.type === "decision").map((t) => ({
      id: t.id,
      decision: t.content.decision || "",
      rationale: t.content.rationale || "",
      impact: this.assessImpact(t),
      still_applies: !t.metadata?.superseded
    })).filter((d) => d.impact !== "low");
  }
  assessImpact(trace) {
    const content = JSON.stringify(trace.content).toLowerCase();
    if (content.includes("architecture") || content.includes("critical")) {
      return "critical";
    }
    if (content.includes("important") || content.includes("significant")) {
      return "high";
    }
    if (content.includes("minor") || content.includes("small")) {
      return "low";
    }
    return "medium";
  }
  async getActiveTasks() {
    const frames = await this.dbManager.getRecentFrames(
      await this.dbManager.getCurrentSessionId(),
      50
    );
    return frames.filter((f) => f.type === "task").map((f) => ({
      id: f.id,
      title: f.description || "Untitled task",
      status: this.getTaskStatus(f),
      priority: this.getTaskPriority(f),
      context: f.metadata?.context || ""
    }));
  }
  getTaskStatus(frame) {
    if (frame.status === "closed" && frame.metadata?.completed) {
      return "completed";
    }
    if (frame.metadata?.blocked) return "blocked";
    if (frame.status === "open") return "in_progress";
    return "pending";
  }
  getTaskPriority(frame) {
    const priority = frame.metadata?.priority;
    if (["critical", "high", "medium", "low"].includes(priority)) {
      return priority;
    }
    return "medium";
  }
  async getCriticalContext() {
    const context = [];
    const session = await this.dbManager.getSession(
      await this.dbManager.getCurrentSessionId()
    );
    if (session?.metadata?.key_facts) {
      context.push(...session.metadata.key_facts);
    }
    const traces = await this.dbManager.getRecentTraces(
      await this.dbManager.getCurrentSessionId(),
      50
    );
    const discoveries = traces.filter((t) => t.metadata?.important || t.type === "discovery").map((t) => t.content.summary || t.content.description).filter(Boolean).slice(0, 5);
    context.push(...discoveries);
    return context;
  }
  async getRecentAchievements() {
    const frames = await this.dbManager.getRecentFrames(
      await this.dbManager.getCurrentSessionId(),
      20
    );
    return frames.filter((f) => f.status === "closed" && f.metadata?.achievement).map((f) => ({
      description: f.metadata.achievement,
      impact: f.metadata.impact || "completed task",
      timestamp: f.closedAt || f.createdAt
    })).slice(0, 5);
  }
  async getCurrentFocus() {
    const stack = await this.frameManager.getStack();
    const activeFrame = stack.frames.find((f) => f.status === "open");
    if (!activeFrame) {
      return "No active focus";
    }
    return `${activeFrame.type}: ${activeFrame.description || "In progress"}`;
  }
  async suggestNextActions(tasks) {
    const suggestions = [];
    const inProgress = tasks.filter((t) => t.status === "in_progress");
    if (inProgress.length > 0) {
      suggestions.push(`Continue: ${inProgress[0].title}`);
    }
    const highPriority = tasks.filter(
      (t) => t.status === "pending" && t.priority === "high"
    );
    if (highPriority.length > 0) {
      suggestions.push(`Start: ${highPriority[0].title}`);
    }
    const blocked = tasks.filter((t) => t.status === "blocked");
    if (blocked.length > 0) {
      suggestions.push(`Unblock: ${blocked[0].title}`);
    }
    return suggestions.slice(0, 3);
  }
  async getWarnings() {
    const warnings = [];
    const tasks = await this.getActiveTasks();
    const blocked = tasks.filter((t) => t.status === "blocked");
    if (blocked.length > 0) {
      warnings.push(`${blocked.length} tasks blocked`);
    }
    const critical = tasks.filter(
      (t) => t.priority === "critical" && t.status !== "completed"
    );
    if (critical.length > 0) {
      warnings.push(`${critical.length} critical tasks pending`);
    }
    return warnings;
  }
  async estimateCurrentTokens() {
    const frames = await this.frameManager.getStack();
    const traces = await this.dbManager.getRecentTraces(
      await this.dbManager.getCurrentSessionId(),
      100
    );
    const frameTokens = frames.frames.length * 200;
    const traceTokens = traces.length * 100;
    return frameTokens + traceTokens;
  }
  estimateLedgerTokens(frames, decisions, tasks) {
    return frames.length * 50 + decisions.length * 30 + tasks.length * 20;
  }
  async saveLedgerToFile(ledger) {
    await fs.mkdir(this.continuityPath, { recursive: true });
    const latestPath = path.join(
      this.continuityPath,
      "CONTINUITY_CLAUDE-latest.json"
    );
    await fs.writeFile(latestPath, JSON.stringify(ledger, null, 2), "utf-8");
    const markdown = await this.generateLedgerMarkdown(ledger);
    const mdPath = path.join(
      this.continuityPath,
      "CONTINUITY_CLAUDE-latest.md"
    );
    await fs.writeFile(mdPath, markdown, "utf-8");
  }
  async saveBackupLedger(ledger) {
    await fs.mkdir(this.ledgerPath, { recursive: true });
    const timestamp = ledger.timestamp.replace(/[:.]/g, "-");
    const backupPath = path.join(this.ledgerPath, `ledger-${timestamp}.json`);
    await fs.writeFile(backupPath, JSON.stringify(ledger, null, 2), "utf-8");
  }
  async loadLatestLedger() {
    try {
      const latestPath = path.join(
        this.continuityPath,
        "CONTINUITY_CLAUDE-latest.json"
      );
      const content = await fs.readFile(latestPath, "utf-8");
      return JSON.parse(content);
    } catch (error) {
      return null;
    }
  }
  async restoreFrameStructure(frames) {
    for (const summary of frames) {
      await this.frameManager.push({
        type: summary.type,
        description: summary.description,
        metadata: {
          restored_from_ledger: true,
          original_id: summary.id,
          key_events: summary.key_events,
          digest: summary.digest
        }
      });
    }
  }
  async restoreDecisions(decisions) {
    for (const decision of decisions) {
      if (decision.still_applies) {
        await this.dbManager.addAnchor({
          type: "decision",
          content: {
            decision: decision.decision,
            rationale: decision.rationale,
            impact: decision.impact
          },
          metadata: {
            restored_from_ledger: true,
            original_id: decision.id
          }
        });
      }
    }
  }
  async restoreTasks(tasks) {
    for (const task of tasks) {
      if (task.status !== "completed") {
        await this.frameManager.push({
          type: "task",
          description: task.title,
          metadata: {
            status: task.status,
            priority: task.priority,
            context: task.context,
            restored_from_ledger: true,
            original_id: task.id
          }
        });
      }
    }
  }
}
export {
  ClearSurvival
};
//# sourceMappingURL=clear-survival.js.map
