session_load_context
Load previous work state at session start using progressive context levels: quick for TODOs, standard for recent summaries, or deep for full history.
Instructions
Load session context for a project using progressive context loading. Use this at the START of a new session to recover previous work state. Three levels available:
quick: Just the latest project state — keywords and open TODOs (~50 tokens)
standard: Project state plus recent session summaries and decisions (~200 tokens, recommended)
deep: Everything — full session history with all files changed, TODOs, and decisions (~1000+ tokens)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes | Project identifier to load context for. | |
| level | No | How much context to load: 'quick' (just TODOs), 'standard' (recommended — includes recent summaries), or 'deep' (full history). Default: standard. |
Implementation Reference
- The implementation of the `session_load_context` tool handler, which loads context for a project, performs reality drift detection, generates a morning briefing if necessary, and summarizes visual memory.
export async function sessionLoadContextHandler(args: unknown) { if (!isSessionLoadContextArgs(args)) { throw new Error("Invalid arguments for session_load_context"); } const { project, level = "standard" } = args; const validLevels = ["quick", "standard", "deep"]; if (!validLevels.includes(level)) { return { content: [{ type: "text", text: `Invalid level "${level}". Must be one of: ${validLevels.join(", ")}`, }], isError: true, }; } console.error(`[session_load_context] Loading ${level} context for project="${project}"`); const storage = await getStorage(); const data = await storage.loadContext(project, level, PRISM_USER_ID); if (!data) { return { content: [{ type: "text", text: `No session context found for project "${project}" at level ${level}.\n` + `This project has no previous session history. Starting fresh.`, }], isError: false, }; } const version = (data as any)?.version; const versionNote = version ? `\n\n🔑 Session version: ${version}. Pass expected_version: ${version} when saving handoff.` : ""; // ─── Reality Drift Detection (v2.0 Step 5) ─── // Check if the developer changed code since the last handoff save. let driftReport = ""; const meta = (data as any)?.metadata; if (meta?.last_commit_sha) { const currentGit = getCurrentGitState(); if (currentGit.isRepo) { if (meta.git_branch && currentGit.branch !== meta.git_branch) { // Branch switch — inform but don't panic driftReport = `\n\n⚠️ **CONTEXT SHIFT:** This memory was saved on branch ` + `\`${meta.git_branch}\`, but you are currently on branch \`${currentGit.branch}\`. ` + `Code may have diverged — review carefully before making changes.`; console.error( `[session_load_context] Context shift detected: ${meta.git_branch} → ${currentGit.branch}` ); } else if (currentGit.commitSha !== meta.last_commit_sha) { // Same branch, different commits — calculate drift const changes = getGitDrift(meta.last_commit_sha as string); if (changes) { driftReport = `\n\n⚠️ **REALITY DRIFT DETECTED**\n` + `Since this memory was saved (commit ${(meta.last_commit_sha as string).substring(0, 8)}), ` + `the following files were modified outside of agent sessions:\n\`\`\`\n${changes}\n\`\`\`\n` + `Please review these files if they overlap with your current task.`; console.error( `[session_load_context] Reality drift detected! ${changes.split("\n").length} files changed` ); } } else { console.error(`[session_load_context] No drift — repo matches saved state`); } } } // ─── Morning Briefing (v2.0 Step 7) ─── // If it's been more than 4 hours since the last briefing, generate a fresh one. // Otherwise, show the cached briefing from metadata. let briefingBlock = ""; const FOUR_HOURS_MS = 4 * 60 * 60 * 1000; const now = Date.now(); const lastGenerated = meta?.briefing_generated_at as number || 0; if (now - lastGenerated > FOUR_HOURS_MS) { try { // Only import when needed — keeps cold start fast when not generating const { generateMorningBriefing } = await import("../utils/briefing.js"); // Fetch recent ledger entries for context const recentRaw = await storage.getLedgerEntries({ project: `eq.${project}`, user_id: `eq.${PRISM_USER_ID}`, order: "created_at.desc", limit: "10", }); const recentEntries = (recentRaw as any[]).map(e => ({ type: e.type || "entry", summary: e.summary || e.content || "", })); const contextObj = data as any; const briefingText = await generateMorningBriefing( { project, lastSummary: contextObj.last_summary ?? contextObj.summary ?? null, pendingTodos: contextObj.pending_todo ?? contextObj.active_context ?? null, keyContext: contextObj.key_context ?? null, activeBranch: contextObj.active_branch ?? null, }, recentEntries ); briefingBlock = `\n\n[🌅 MORNING BRIEFING]\n${briefingText}`; // Cache the briefing in metadata so we don't regenerate for 4 hours // Fire-and-forget — never block the context response const updatedMeta = { ...(meta || {}), briefing_generated_at: now, morning_briefing: briefingText }; const handoffUpdate = { project, user_id: PRISM_USER_ID, metadata: updatedMeta, last_summary: contextObj.last_summary ?? null, pending_todo: contextObj.pending_todo ?? null, active_decisions: contextObj.active_decisions ?? null, keywords: contextObj.keywords ?? null, key_context: contextObj.key_context ?? null, active_branch: contextObj.active_branch ?? null, }; const currentVersion = (data as any)?.version; if (currentVersion) { storage.saveHandoff(handoffUpdate, currentVersion).catch(err => console.error(`[Morning Briefing] Cache save failed (non-fatal): ${err}`) ); } console.error(`[session_load_context] Morning Briefing generated for "${project}"`); } catch (err) { console.error(`[session_load_context] Morning Briefing failed (non-fatal): ${err}`); } } else if (meta?.morning_briefing) { // Show the cached briefing (generated within last 4 hours) briefingBlock = `\n\n[🌅 MORNING BRIEFING]\n${meta.morning_briefing}`; console.error(`[session_load_context] Showing cached Morning Briefing for "${project}"`); } // ─── Visual Memory Index (v2.0 Step 9) ─── // Show lightweight index of saved images — never loads actual image data let visualMemoryBlock = ""; const visuals = (data as any)?.metadata?.visual_memory || []; if (visuals.length > 0) { visualMemoryBlock = `\n\n[🖼️ VISUAL MEMORY]\nThe following reference images are available. Use session_view_image(id) to view them if needed:\n`; visuals.forEach((v: any) => { visualMemoryBlock += `- [ID: ${v.id}] ${v.description} (${v.timestamp?.split("T")[0] || "unknown"})\n`; }); } return { content: [{ type: "text", text: `📋 Session context for "${project}" (${level}):\n\n${JSON.stringify(data, null, 2)}${driftReport}${briefingBlock}${visualMemoryBlock}${versionNote}`, }], isError: false, }; } - Type definition and validation for the `session_load_context` tool arguments.
export function isSessionLoadContextArgs( args: unknown ): args is { project: string; level?: "quick" | "standard" | "deep" } { return ( - src/tools/sessionMemoryDefinitions.ts:102-115 (registration)Registration of the `session_load_context` tool definition.
export const SESSION_LOAD_CONTEXT_TOOL: Tool = { name: "session_load_context", description: "Load session context for a project using progressive context loading. " + "Use this at the START of a new session to recover previous work state. " + "Three levels available:\n" + "- **quick**: Just the latest project state — keywords and open TODOs (~50 tokens)\n" + "- **standard**: Project state plus recent session summaries and decisions (~200 tokens, recommended)\n" + "- **deep**: Everything — full session history with all files changed, TODOs, and decisions (~1000+ tokens)", inputSchema: { type: "object", properties: { project: { type: "string",