diff --git a/src/agents/pi-extensions/compaction-safeguard.ts b/src/agents/pi-extensions/compaction-safeguard.ts index a258c54f6be..b19238fe7e3 100644 --- a/src/agents/pi-extensions/compaction-safeguard.ts +++ b/src/agents/pi-extensions/compaction-safeguard.ts @@ -1,3 +1,5 @@ +import fs from "node:fs"; +import path from "node:path"; import type { AgentMessage } from "@mariozechner/pi-agent-core"; import type { ExtensionAPI, FileOperations } from "@mariozechner/pi-coding-agent"; import { @@ -11,6 +13,7 @@ import { resolveContextWindowTokens, summarizeInStages, } from "../compaction.js"; +import { extractSections } from "../../auto-reply/reply/post-compaction-context.js"; import { getCompactionSafeguardRuntime } from "./compaction-safeguard-runtime.js"; const FALLBACK_SUMMARY = "Summary unavailable due to context limits. Older messages were truncated."; @@ -158,6 +161,40 @@ function formatFileOperations(readFiles: string[], modifiedFiles: string[]): str return `\n\n${sections.join("\n\n")}`; } +/** + * Read and format critical workspace context for compaction summary. + * Extracts "Session Startup" and "Red Lines" from AGENTS.md. + * Limited to 2000 chars to avoid bloating the summary. + */ +async function readWorkspaceContextForSummary(): Promise { + const MAX_SUMMARY_CONTEXT_CHARS = 2000; + const workspaceDir = process.cwd(); + const agentsPath = path.join(workspaceDir, "AGENTS.md"); + + try { + if (!fs.existsSync(agentsPath)) { + return ""; + } + + const content = await fs.promises.readFile(agentsPath, "utf-8"); + const sections = extractSections(content, ["Session Startup", "Red Lines"]); + + if (sections.length === 0) { + return ""; + } + + const combined = sections.join("\n\n"); + const safeContent = + combined.length > MAX_SUMMARY_CONTEXT_CHARS + ? combined.slice(0, MAX_SUMMARY_CONTEXT_CHARS) + "\n...[truncated]..." + : combined; + + return `\n\n\n${safeContent}\n`; + } catch { + return ""; + } +} + export default function compactionSafeguardExtension(api: ExtensionAPI): void { api.on("session_before_compact", async (event, ctx) => { const { preparation, customInstructions, signal } = event; @@ -309,6 +346,12 @@ export default function compactionSafeguardExtension(api: ExtensionAPI): void { summary += toolFailureSection; summary += fileOpsSummary; + // Append workspace critical context (Session Startup + Red Lines from AGENTS.md) + const workspaceContext = await readWorkspaceContextForSummary(); + if (workspaceContext) { + summary += workspaceContext; + } + return { compaction: { summary, diff --git a/src/auto-reply/reply/post-compaction-context.ts b/src/auto-reply/reply/post-compaction-context.ts index 7811f732f2c..1c455e91893 100644 --- a/src/auto-reply/reply/post-compaction-context.ts +++ b/src/auto-reply/reply/post-compaction-context.ts @@ -49,7 +49,7 @@ export async function readPostCompactionContext(workspaceDir: string): Promise