diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md
index cda0b2c65..b268db98d 100644
--- a/packages/coding-agent/CHANGELOG.md
+++ b/packages/coding-agent/CHANGELOG.md
@@ -8,6 +8,7 @@
### Fixed
+- Fixed split-turn compaction summaries being refused by Claude Fable 5.1 by clearly separating the conversation and using continuation-oriented instructions ([#9652](https://github.com/earendil-works/pi/issues/9652)).
- Fixed missing or invalid `--mode` values being silently ignored instead of reporting an error and exiting with a nonzero status ([#9045](https://github.com/earendil-works/pi/issues/9045)).
## [0.87.0] - 2026-09-21
diff --git a/packages/coding-agent/src/core/compaction/compaction.ts b/packages/coding-agent/src/core/compaction/compaction.ts
index ea45ea6e0..1757c535c 100644
--- a/packages/coding-agent/src/core/compaction/compaction.ts
+++ b/packages/coding-agent/src/core/compaction/compaction.ts
@@ -961,20 +961,20 @@ export function prepareCompaction(
// Main compaction function
// ============================================================================
-const TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.
+const TURN_PREFIX_SUMMARIZATION_PROMPT = `The messages above are earlier context from an ongoing conversation. Later messages are stored separately and do not need to be reconstructed.
-Summarize the prefix to provide context for the retained suffix:
+Create a concise checkpoint of the user's request and the progress shown above. This checkpoint will be placed before the later messages so the conversation can continue with the necessary context.
## Original Request
-[What did the user ask for in this turn?]
+[What did the user ask for?]
-## Early Progress
-- [Key decisions and work done in the prefix]
+## Progress So Far
+- [Key decisions and work completed in these messages]
-## Context for Suffix
-- [Information needed to understand the retained recent work]
+## Context Needed to Continue
+- [Information from these messages needed to understand the later work]
-Be concise. Focus on what's needed to understand the kept suffix.`;
+Only summarize information explicitly present above. Do not infer or recreate later messages.`;
/**
* Generate summaries for compaction using prepared data.
@@ -1115,7 +1115,7 @@ async function generateTurnPrefixSummary(
); // Smaller budget for turn prefix
const llmMessages = convertToLlm(messages);
const conversationText = serializeConversation(llmMessages);
- const promptText = `\n${conversationText}\n\n\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`;
+ const promptText = `# Conversation\n${conversationText}\n\n# Instructions\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`;
const response = await completeSummarization(
model,
diff --git a/packages/coding-agent/test/compaction-summary-reasoning.test.ts b/packages/coding-agent/test/compaction-summary-reasoning.test.ts
index ab4a721ee..ce8303cbf 100644
--- a/packages/coding-agent/test/compaction-summary-reasoning.test.ts
+++ b/packages/coding-agent/test/compaction-summary-reasoning.test.ts
@@ -146,8 +146,9 @@ describe("generateSummary reasoning options", () => {
expect(result.summary).toContain("previous checkpoint");
const requestContext = completeSimpleMock.mock.calls[0][1] as TranscriptContext;
const prompt = JSON.stringify(requestContext.messages);
- expect(prompt).toContain("This is the PREFIX of a turn that was too large to keep");
- expect(prompt).toContain("");
+ // Regression test for #9652: clear boundaries and continuation wording avoid the reasoning-extraction false positive.
+ expect(prompt).toContain("# Conversation\\n[User]: Summarize this.");
+ expect(prompt).toContain("# Instructions\\nThe messages above are earlier context from an ongoing conversation.");
});
it("rejects tool calls from conversation summaries", async () => {
diff --git a/packages/coding-agent/test/suite/agent-session-compaction.test.ts b/packages/coding-agent/test/suite/agent-session-compaction.test.ts
index 62dc2f10a..ef547736b 100644
--- a/packages/coding-agent/test/suite/agent-session-compaction.test.ts
+++ b/packages/coding-agent/test/suite/agent-session-compaction.test.ts
@@ -354,7 +354,8 @@ describe("AgentSession compaction characterization", () => {
expect(transformContext).not.toHaveBeenCalled();
expect(getCurrentSystemPrompt(requestContext?.messages ?? [])).not.toBe(harness.session.agent.state.systemPrompt);
expect(getCurrentTools(requestContext?.messages ?? [])).toEqual([]);
- expect(JSON.stringify(requestContext?.messages)).toContain("");
+ // Regression test for #9652: split-turn summaries use a clear Markdown conversation boundary.
+ expect(JSON.stringify(requestContext?.messages)).toContain("# Conversation\\n[User]: message to compact");
expect(requestOptions).toMatchObject({ cacheRetention: "none" });
expect(requestOptions?.sessionId).not.toBe("active-routing-session");
expect(requestOptions?.transport).toBeUndefined();