diff --git a/docs/claude-instructions-cache-stabilize/PAPER_OCXFIX.pdf b/docs/claude-instructions-cache-stabilize/PAPER_OCXFIX.pdf
new file mode 100644
index 0000000000..5206d30d1f
Binary files /dev/null and b/docs/claude-instructions-cache-stabilize/PAPER_OCXFIX.pdf differ
diff --git a/docs/claude-instructions-cache-stabilize/README.md b/docs/claude-instructions-cache-stabilize/README.md
new file mode 100644
index 0000000000..ab331a10f4
--- /dev/null
+++ b/docs/claude-instructions-cache-stabilize/README.md
@@ -0,0 +1,36 @@
+# Claude instructions cache stabilize (OCXFIX)
+
+OpenCodex inbound conversion puts Claude Code system text into OpenAI Responses
+`instructions`. Claude Code then appends a growing `…`
+footer (and occasional TaskCreate nudges) on every turn. That prefix churn
+causes prompt-cache misses on Muse/Go.
+
+This change strips those dynamic footers from `instructions` and reattaches the
+latest notice as a trailing `input` message so the cacheable prefix stays stable.
+
+Relocation is opt-in: `translateAnthropicRequest` / `anthropicToResponsesTranslation`
+take `stabilizePromptCache?: boolean` (default **false**). Ordinary Anthropic
+callers keep a matching suffix in `instructions`. The Claude Code `/v1/messages`
+inbound path passes `true`. The matcher is `N tokens left`
+plus the exact TaskCreate paragraph(s) (legacy and Claude Code 2.1.263+ wording); it is not gated on `metadata.user_id`.
+Outside opt-in, the Desktop `prompt_cache_key` fallback hashes raw `systemParts`.
+When opted in, that fallback hashes the same string as `body.instructions`.
+
+## Paper
+
+See [PAPER_OCXFIX.pdf](./PAPER_OCXFIX.pdf) (Warexpor).
+
+Measured cache-hit rates on Muse Spark 1.3 via OpenCode Go / OpenCodex:
+
+| Slice | Baseline mean | OCXFIX mean |
+| --- | ---: | ---: |
+| Claude Code (n=75) | 0.168384 | 0.864374 |
+| Claude S/T4 (n=5) | 0.134922 | 0.982700 |
+| Grok Build (n=75) | 0.966526 | 0.941345 |
+
+Cause: Anthropic→Responses conversion stores Claude system text in `instructions`;
+Claude Code appends growing `` (and rare TaskCreate nudges), so
+`instructions_sha` changes every turn. Grok traffic has no `instructions` field
+and is the control.
+
+Code: `src/claude/inbound-cache-stabilize.ts`, wired from `src/claude/inbound.ts`.
diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json
index 0ff7d4861c..ef04b588e2 100644
--- a/scripts/test-layout/layout.json
+++ b/scripts/test-layout/layout.json
@@ -304,6 +304,7 @@
"claude-desktop-remote-hub.test.ts": "claude-integration",
"claude-dotenv-provenance-transport.test.ts": "claude-integration",
"claude-gateway-cache.test.ts": "claude-integration",
+ "claude-inbound-cache-stabilize.test.ts": "claude-integration",
"claude-inbound-debug.test.ts": "claude-integration",
"claude-inbound.test.ts": "claude-integration",
"claude-management-api.test.ts": "claude-integration",
diff --git a/src/claude/inbound-cache-stabilize.ts b/src/claude/inbound-cache-stabilize.ts
new file mode 100644
index 0000000000..194445981e
--- /dev/null
+++ b/src/claude/inbound-cache-stabilize.ts
@@ -0,0 +1,149 @@
+/**
+ * Claude Code appends growing `…` footers (and
+ * occasional TaskCreate nudges) into system text that becomes Responses
+ * `instructions`. That churn breaks Muse/Go prefix cache on the instructions
+ * prefix even when tools stay stable. Strip dynamics from instructions;
+ * surface the latest notice on `input` instead.
+ *
+ * Relocation is identified by harness shape: only a trailing, unfenced,
+ * canonical notice at the end of instructions is moved. An unmatched fence
+ * opener covers through EOF. No match → the original string is returned
+ * byte-for-byte. The matcher is content identity only; `translateAnthropicRequest`
+ * must pass `stabilizePromptCache: true` before this helper runs. Claude Code
+ * writes `N tokens left`.
+ *
+ * TaskCreate nudge text has drifted across Claude Code builds; match the
+ * known exact paragraphs (legacy + 2.1.263 "tracking progress" form) as
+ * trailing alternatives so a mid-session nudge cannot pin older footers
+ * above it and flip `instructions` after a previously stable peel.
+ */
+
+const TRAILING_TOTAL_RE =
+ /(?:^|(?:\r?\n)+)[ \t]*(\d+\s+tokens left<\/total_tokens>)[ \t]*(?:\r?\n)*$/;
+
+/** Legacy Claude Code TaskCreate reminder (pre-"tracking progress"). */
+const TASKCREATE_NUDGE_LEGACY =
+ "The task tools haven't been used recently. If you're working on tasks that would benefit from tracking, consider using TaskCreate to add them. Only use these if relevant to the current work. This is just a gentle reminder - ignore if not applicable.";
+
+/**
+ * Claude Code 2.1.263+ TaskCreate reminder observed on hitrate S/T4
+ * (FREEZE-DIFF + tip0847 pilots). Mentions TaskUpdate and stale-list cleanup.
+ */
+const TASKCREATE_NUDGE_CC_2_1_263 =
+ "The task tools haven't been used recently. If you're working on tasks that would benefit from tracking progress, consider using TaskCreate to add new tasks and TaskUpdate to update task status (set to in_progress when starting, completed when done). Also consider cleaning up the task list if it has become stale. Only use these if relevant to the current work. This is just a gentle reminder - ignore if not applicable.";
+
+const TRAILING_NUDGE_RE = new RegExp(
+ `(?:^|(?:\\r?\\n)+)[ \\t]*(${escapeRegExp(TASKCREATE_NUDGE_LEGACY)}|${escapeRegExp(TASKCREATE_NUDGE_CC_2_1_263)})[ \\t]*(?:\\r?\\n)*$`,
+);
+
+function escapeRegExp(value: string): string {
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+}
+
+interface FenceRange {
+ start: number;
+ end: number;
+}
+
+const FENCE_OPEN_RE = /^( {0,3})(`{3,}|~{3,})/;
+const FENCE_CLOSE_RE = /^( {0,3})(`{3,}|~{3,})[ \t]*$/;
+
+/**
+ * Markdown fence ranges. An unmatched opener covers through EOF: unfinished
+ * fenced examples are code content, not a harness suffix. A closer must be a
+ * standalone fence line (no info string) of the same character and at least
+ * the opener's length.
+ */
+function fencedRanges(source: string): FenceRange[] {
+ const ranges: FenceRange[] = [];
+ let offset = 0;
+ let openAt: number | null = null;
+ let openFence = "";
+ while (offset <= source.length) {
+ const nl = source.indexOf("\n", offset);
+ const lineEnd = nl === -1 ? source.length : nl;
+ const line = source.slice(offset, lineEnd).replace(/\r$/, "");
+ if (openAt === null) {
+ const open = FENCE_OPEN_RE.exec(line);
+ if (open) {
+ openAt = offset;
+ openFence = open[2]!;
+ }
+ } else {
+ const close = FENCE_CLOSE_RE.exec(line);
+ if (
+ close
+ && close[2]![0] === openFence[0]
+ && close[2]!.length >= openFence.length
+ ) {
+ ranges.push({ start: openAt, end: lineEnd });
+ openAt = null;
+ openFence = "";
+ }
+ }
+ if (nl === -1) break;
+ offset = nl + 1;
+ }
+ if (openAt !== null) ranges.push({ start: openAt, end: source.length });
+ return ranges;
+}
+
+function isInsideFence(ranges: readonly FenceRange[], index: number): boolean {
+ return ranges.some(range => index >= range.start && index < range.end);
+}
+
+function peelOne(
+ rest: string,
+ ranges: readonly FenceRange[],
+): { rest: string; total?: string; nudge?: string } | null {
+ const total = rest.match(TRAILING_TOTAL_RE);
+ if (total?.[1]) {
+ const matchStart = rest.length - total[0].length;
+ const tagAt = matchStart + total[0].indexOf(total[1]);
+ if (!isInsideFence(ranges, tagAt)) {
+ return { rest: rest.slice(0, rest.length - total[0].length), total: total[1] };
+ }
+ }
+ const nudge = rest.match(TRAILING_NUDGE_RE);
+ if (nudge?.[1]) {
+ const matchStart = rest.length - nudge[0].length;
+ const tagAt = matchStart + nudge[0].indexOf(nudge[1]);
+ if (!isInsideFence(ranges, tagAt)) {
+ return { rest: rest.slice(0, rest.length - nudge[0].length), nudge: nudge[1] };
+ }
+ }
+ return null;
+}
+
+export function stabilizeClaudeInstructionsForPromptCache(
+ instructions: string,
+): { instructions: string; dynamicNotice: string | null } {
+ if (!instructions) {
+ return { instructions: "", dynamicNotice: null };
+ }
+
+ const ranges = fencedRanges(instructions);
+ let rest = instructions;
+ let latestTotal: string | null = null;
+ let latestNudge: string | null = null;
+ let peeled = false;
+ for (;;) {
+ const next = peelOne(rest, ranges);
+ if (!next) break;
+ peeled = true;
+ rest = next.rest;
+ if (next.total && latestTotal === null) latestTotal = next.total;
+ if (next.nudge && latestNudge === null) latestNudge = next.nudge;
+ }
+
+ if (!peeled) {
+ return { instructions, dynamicNotice: null };
+ }
+
+ const noticeParts: string[] = [];
+ if (latestTotal) noticeParts.push(latestTotal);
+ if (latestNudge) noticeParts.push(latestNudge);
+ const dynamicNotice = noticeParts.length > 0 ? noticeParts.join("\n\n") : null;
+
+ return { instructions: rest, dynamicNotice };
+}
diff --git a/src/claude/inbound.ts b/src/claude/inbound.ts
index c2e3ded9b2..eddac06ac8 100644
--- a/src/claude/inbound.ts
+++ b/src/claude/inbound.ts
@@ -17,6 +17,7 @@ export { resolveInboundModel, effortForThinkingBudget, effortFromOutputConfig, e
import { AnthropicRequestError, isRec, type Rec } from "./inbound-records";
import { resolveInboundModel, effortForThinkingBudget, effortFromOutputConfig, formatFromOutputConfig } from "./inbound-model-options";
import { systemToInstructions, toolsToResponses, toolChoiceToResponses } from "./inbound-content-options";
+import { stabilizeClaudeInstructionsForPromptCache } from "./inbound-cache-stabilize";
import { decodeReasoningEnvelope, encodeReasoningEnvelope, OCX_REASONING_PREFIX } from "../responses/reasoning-envelope";
import { createTranslatorBudget, type TranslatorBudget } from "../lib/translator-budget";
@@ -287,12 +288,25 @@ export interface ClaudeInboundTranslation {
cacheKeySource: ClaudeCacheKeySource;
}
+/**
+ * Translator-level opt-in for Claude Code harness footer relocation.
+ * Default is off: a matching textual suffix is not permission to change its role.
+ * The `/v1/messages` inbound path passes true. Do not infer this from metadata.user_id.
+ */
+export interface ClaudeInboundTranslateOptions {
+ stabilizePromptCache?: boolean;
+}
+
/**
* Translate an Anthropic Messages request body into a /v1/responses request body.
* Throws AnthropicRequestError (-> 400 invalid_request_error) on malformed input.
*/
-export function anthropicToResponsesBody(raw: unknown, cc?: OcxClaudeCodeConfig): Rec {
- return anthropicToResponsesTranslation(raw, cc).body;
+export function anthropicToResponsesBody(
+ raw: unknown,
+ cc?: OcxClaudeCodeConfig,
+ options?: ClaudeInboundTranslateOptions,
+): Rec {
+ return anthropicToResponsesTranslation(raw, cc, undefined, options).body;
}
/**
@@ -300,16 +314,26 @@ export function anthropicToResponsesBody(raw: unknown, cc?: OcxClaudeCodeConfig)
* OUT-OF-BODY tuple (audit 133 R3#1 — an in-body marker would leak upstream through
* the native Responses forward and 400).
*/
-export function anthropicToResponsesTranslation(raw: unknown, cc?: OcxClaudeCodeConfig, budget?: TranslatorBudget): ClaudeInboundTranslation {
+export function anthropicToResponsesTranslation(
+ raw: unknown,
+ cc?: OcxClaudeCodeConfig,
+ budget?: TranslatorBudget,
+ options?: ClaudeInboundTranslateOptions,
+): ClaudeInboundTranslation {
const activeBudget = budget ?? createTranslatorBudget();
try {
- return translateAnthropicRequest(raw, cc, activeBudget);
+ return translateAnthropicRequest(raw, cc, activeBudget, options);
} finally {
if (!budget) activeBudget.dispose();
}
}
-function translateAnthropicRequest(raw: unknown, cc: OcxClaudeCodeConfig | undefined, budget: TranslatorBudget): ClaudeInboundTranslation {
+function translateAnthropicRequest(
+ raw: unknown,
+ cc: OcxClaudeCodeConfig | undefined,
+ budget: TranslatorBudget,
+ options?: ClaudeInboundTranslateOptions,
+): ClaudeInboundTranslation {
if (!isRec(raw)) throw new AnthropicRequestError("request body must be a JSON object");
if (typeof raw.model !== "string" || raw.model.length === 0) {
throw new AnthropicRequestError("model is required");
@@ -345,7 +369,32 @@ function translateAnthropicRequest(raw: unknown, cc: OcxClaudeCodeConfig | undef
stream: raw.stream === true,
};
- if (systemParts.length > 0) body.instructions = systemParts.join("\n\n");
+ const joinedSystem = systemParts.length > 0 ? systemParts.join("\n\n") : "";
+ const stabilizePromptCache = options?.stabilizePromptCache === true;
+ // Desktop fallback hashes raw systemParts unless the caller opted into
+ // harness cleanup. Opt-in then hashes the same string as body.instructions.
+ let cacheSystem: string | string[] = systemParts;
+ if (joinedSystem) {
+ if (stabilizePromptCache) {
+ // Claude Code appends growing N tokens left
+ // footers (and occasional TaskCreate nudges) into system text. That churn
+ // breaks Muse/Go prefix cache on the Responses instructions prefix even
+ // when tools stay stable. Relocation is caller-opted, not inferred from
+ // a matching suffix or metadata.user_id.
+ const stabilized = stabilizeClaudeInstructionsForPromptCache(joinedSystem);
+ if (stabilized.instructions) body.instructions = stabilized.instructions;
+ if (stabilized.dynamicNotice) {
+ input.push({
+ type: "message",
+ role: "user",
+ content: [{ type: "input_text", text: stabilized.dynamicNotice }],
+ });
+ }
+ cacheSystem = stabilized.instructions;
+ } else {
+ body.instructions = joinedSystem;
+ }
+ }
const tools = toolsToResponses(raw.tools);
if (tools) body.tools = tools;
@@ -383,11 +432,14 @@ function translateAnthropicRequest(raw: unknown, cc: OcxClaudeCodeConfig | undef
// Exact-prefix matching still isolates content; the key only steers routing
// affinity. Callers must NOT synthesize a session_id header from this fallback
// (audit 133 R2#3).
+ // Outside opt-in, hash the raw systemParts array (pre-stabilize Desktop
+ // key). Opt-in hashes the same string used for body.instructions so the
+ // key tracks the cacheable prefix after peel.
body.prompt_cache_key = createHash("sha256")
.update(canonicalJson({
version: 2,
model: body.model,
- system: systemParts,
+ system: cacheSystem,
tools: Array.isArray(body.tools) ? body.tools : [],
}))
.digest("hex").slice(0, 32);
diff --git a/src/server/claude-messages.ts b/src/server/claude-messages.ts
index 8c3e37eea8..f672f9f911 100644
--- a/src/server/claude-messages.ts
+++ b/src/server/claude-messages.ts
@@ -755,7 +755,9 @@ async function handleClaudeMessagesWithBudget(
};
delete anthropicBody.thinking;
}
- const translation = anthropicToResponsesTranslation(anthropicBody, config.claudeCode, translatorBudget);
+ const translation = anthropicToResponsesTranslation(anthropicBody, config.claudeCode, translatorBudget, {
+ stabilizePromptCache: true,
+ });
internalBody = translation.body;
// The Anthropic translator builds its body from model/input/store/stream plus sampling
// fields only, so the caller intent is applied to the TRANSLATED body rather than the
diff --git a/tests/claude-integration/claude-inbound-cache-stabilize.test.ts b/tests/claude-integration/claude-inbound-cache-stabilize.test.ts
new file mode 100644
index 0000000000..c3b5dade5f
--- /dev/null
+++ b/tests/claude-integration/claude-inbound-cache-stabilize.test.ts
@@ -0,0 +1,360 @@
+import { describe, expect, test } from "bun:test";
+import { readFileSync } from "node:fs";
+import { stabilizeClaudeInstructionsForPromptCache } from "../../src/claude/inbound-cache-stabilize";
+import { anthropicToResponsesTranslation } from "../../src/claude/inbound";
+import { repoPath } from "../helpers/repo-root";
+
+const TASKCREATE_NUDGE = [
+ "The task tools haven't been used recently. If you're working on tasks that would benefit from tracking, consider using TaskCreate to add them.",
+ "Only use these if relevant to the current work. This is just a gentle reminder - ignore if not applicable.",
+].join(" ");
+
+/** Claude Code 2.1.263+ wording (hitrate tip0847 / FREEZE-DIFF S/T4). */
+const TASKCREATE_NUDGE_CC_2_1_263 = [
+ "The task tools haven't been used recently. If you're working on tasks that would benefit from tracking progress, consider using TaskCreate to add new tasks and TaskUpdate to update task status (set to in_progress when starting, completed when done).",
+ "Also consider cleaning up the task list if it has become stale.",
+ "Only use these if relevant to the current work. This is just a gentle reminder - ignore if not applicable.",
+].join(" ");
+
+function footer(used: number): string {
+ return `${used} tokens left`;
+}
+
+function translate(
+ system: string,
+ options?: { user_id?: string; stabilizePromptCache?: boolean },
+) {
+ return anthropicToResponsesTranslation(
+ {
+ model: "m",
+ max_tokens: 1,
+ system,
+ messages: [{ role: "user", content: "hi" }],
+ ...(options?.user_id ? { metadata: { user_id: options.user_id } } : {}),
+ },
+ undefined,
+ undefined,
+ options?.stabilizePromptCache === undefined
+ ? undefined
+ : { stabilizePromptCache: options.stabilizePromptCache },
+ );
+}
+
+function translateHarness(system: string, metadata?: { user_id: string }) {
+ return anthropicToResponsesTranslation(
+ {
+ model: "m",
+ max_tokens: 1,
+ system,
+ messages: [{ role: "user", content: "hi" }],
+ ...(metadata ? { metadata } : {}),
+ },
+ undefined,
+ undefined,
+ { stabilizePromptCache: true },
+ );
+}
+
+function userTurns(body: { input: unknown }) {
+ return body.input as Array>;
+}
+
+describe("stabilizeClaudeInstructionsForPromptCache", () => {
+ test("empty input is a no-op", () => {
+ expect(stabilizeClaudeInstructionsForPromptCache("")).toEqual({
+ instructions: "",
+ dynamicNotice: null,
+ });
+ });
+
+ test("stable instructions without dynamics pass through", () => {
+ const instructions = "You are Claude Code.\n\nPrefer terse answers.";
+ expect(stabilizeClaudeInstructionsForPromptCache(instructions)).toEqual({
+ instructions,
+ dynamicNotice: null,
+ });
+ });
+
+ test("no-match whitespace is returned byte-for-byte", () => {
+ const instructions = "You are Claude Code.\n\n\nPrefer terse answers.\n";
+ expect(stabilizeClaudeInstructionsForPromptCache(instructions)).toEqual({
+ instructions,
+ dynamicNotice: null,
+ });
+ });
+
+ test("whitespace-only system without a footer is unchanged", () => {
+ const instructions = " \n\n ";
+ expect(stabilizeClaudeInstructionsForPromptCache(instructions)).toEqual({
+ instructions,
+ dynamicNotice: null,
+ });
+ });
+
+ test("three trailing total_tokens footers keep only the latest in the notice", () => {
+ const stable = "You are Claude Code.";
+ const first = footer(1000);
+ const second = footer(4000);
+ const third = footer(8000);
+ const result = stabilizeClaudeInstructionsForPromptCache(
+ [stable, first, second, third].join("\n\n"),
+ );
+ expect(result.instructions).toBe(stable);
+ expect(result.instructions).not.toContain("");
+ expect(result.dynamicNotice).toBe(third);
+ });
+
+ test("real Claude Code 15000000 tokens left trailing footer peels", () => {
+ const stable = "You are Claude Code.";
+ const harness = footer(15_000_000);
+ const result = stabilizeClaudeInstructionsForPromptCache(`${stable}\n\n${harness}`);
+ expect(result.instructions).toBe(stable);
+ expect(result.dynamicNotice).toBe("15000000 tokens left");
+ });
+
+ test("bare numeric total_tokens without tokens left is not a harness footer", () => {
+ const docs = "You are Claude Code.\n\n123";
+ const result = stabilizeClaudeInstructionsForPromptCache(docs);
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBeNull();
+ });
+
+ test("mid-document total_tokens stays; only the trailing harness footer relocates", () => {
+ const result = stabilizeClaudeInstructionsForPromptCache(
+ `System.\n${footer(1)}\nMore system.\n${footer(3)}`,
+ );
+ expect(result.instructions).toBe(`System.\n${footer(1)}\nMore system.`);
+ expect(result.dynamicNotice).toBe(footer(3));
+ });
+
+ test("TaskCreate nudge is stripped from instructions and kept in the notice", () => {
+ const stable = "You are Claude Code.";
+ const result = stabilizeClaudeInstructionsForPromptCache(
+ `${stable}\n\n${TASKCREATE_NUDGE}`,
+ );
+ expect(result.instructions).toBe(stable);
+ expect(result.instructions).not.toContain("TaskCreate");
+ expect(result.dynamicNotice).toBe(TASKCREATE_NUDGE);
+ });
+
+ test("Claude Code 2.1.263 TaskCreate nudge peels and unpins older tokens-left footers", () => {
+ const stable = "You are Claude Code.";
+ const older = footer(15_000_000);
+ const mid = footer(14_980_071);
+ const latest = footer(14_997_176);
+ const result = stabilizeClaudeInstructionsForPromptCache(
+ [stable, older, mid, TASKCREATE_NUDGE_CC_2_1_263, latest].join("\n\n"),
+ );
+ expect(result.instructions).toBe(stable);
+ expect(result.instructions).not.toContain("");
+ expect(result.instructions).not.toContain("TaskCreate");
+ expect(result.dynamicNotice).toBe(`${latest}\n\n${TASKCREATE_NUDGE_CC_2_1_263}`);
+ });
+
+ test("latest footer and latest nudge both surface in the notice", () => {
+ const stable = "Stay stable.";
+ const older = footer(10);
+ const latest = footer(50);
+ const result = stabilizeClaudeInstructionsForPromptCache(
+ [stable, older, TASKCREATE_NUDGE, latest].join("\n\n"),
+ );
+ expect(result.instructions).toBe(stable);
+ expect(result.dynamicNotice).toBe(`${latest}\n\n${TASKCREATE_NUDGE}`);
+ });
+
+ test("legacy and 2.1.263 nudges both leave the same stable instructions prefix", () => {
+ const stable = "Stay stable.";
+ const a = stabilizeClaudeInstructionsForPromptCache(
+ [stable, footer(1), TASKCREATE_NUDGE, footer(2)].join("\n\n"),
+ );
+ const b = stabilizeClaudeInstructionsForPromptCache(
+ [stable, footer(1), TASKCREATE_NUDGE_CC_2_1_263, footer(9)].join("\n\n"),
+ );
+ expect(a.instructions).toBe(stable);
+ expect(b.instructions).toBe(stable);
+ });
+
+ test("inline documentation of total_tokens tags stays in instructions", () => {
+ const docs = "The harness may emit a 123 footer; do not invent one.";
+ const result = stabilizeClaudeInstructionsForPromptCache(docs);
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBeNull();
+ });
+
+ test("TaskCreate mentioned in docs is not treated as the harness nudge", () => {
+ const docs = "The task tools haven't been used recently. You may mention TaskCreate in docs without the reminder.";
+ const result = stabilizeClaudeInstructionsForPromptCache(docs);
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBeNull();
+ });
+
+ test("fenced standalone total_tokens example stays byte-for-byte", () => {
+ const docs = ["You are a docs bot.", "```", footer(123), "```", ""].join("\n");
+ const result = stabilizeClaudeInstructionsForPromptCache(docs);
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBeNull();
+ });
+
+ test("docs plus a real trailing footer keep the docs and move only the latest footer", () => {
+ const docs = "Describe 0 in the protocol guide.";
+ const latest = footer(8000);
+ const result = stabilizeClaudeInstructionsForPromptCache(
+ [docs, footer(1), latest].join("\n\n"),
+ );
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBe(latest);
+ });
+
+ test("fenced example plus a trailing harness footer moves only the footer", () => {
+ const docs = ["Docs:", "```", footer(123), "```"].join("\n");
+ const latest = footer(8000);
+ const result = stabilizeClaudeInstructionsForPromptCache(`${docs}\n\n${latest}`);
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBe(latest);
+ });
+
+ test("unclosed fence through EOF is not a harness suffix", () => {
+ const docs = ["You are a docs bot.", "```", footer(123)].join("\n");
+ const result = stabilizeClaudeInstructionsForPromptCache(docs);
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBeNull();
+ });
+
+ test("a fence line with an info string does not close an open fence", () => {
+ const docs = ["```", footer(123), "```xml"].join("\n");
+ const result = stabilizeClaudeInstructionsForPromptCache(docs);
+ expect(result.instructions).toBe(docs);
+ expect(result.dynamicNotice).toBeNull();
+ });
+});
+
+describe("anthropicToResponsesTranslation cache-stabilize wire-in", () => {
+ test("ordinary caller with the exact unfenced suffix keeps instructions and input unchanged", () => {
+ const latest = footer(15_000_000);
+ const system = ["You are Claude Code.", latest].join("\n\n");
+ const { body } = translate(system);
+ expect(body.instructions).toBe(system);
+ expect(userTurns(body)).toEqual([
+ { type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] },
+ ]);
+ });
+
+ test("ordinary caller with the exact TaskCreate paragraph keeps instructions and input unchanged", () => {
+ const system = ["You are Claude Code.", TASKCREATE_NUDGE].join("\n\n");
+ const { body } = translate(system);
+ expect(body.instructions).toBe(system);
+ expect(userTurns(body)).toEqual([
+ { type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] },
+ ]);
+ });
+
+ test("opted-in harness relocates the latest total_tokens footer onto a trailing input user message", () => {
+ const first = footer(1000);
+ const latest = footer(8000);
+ const { body } = translateHarness(["You are Claude Code.", first, latest].join("\n\n"));
+ expect(body.instructions).toBe("You are Claude Code.");
+ expect(String(body.instructions)).not.toContain("");
+ const input = userTurns(body);
+ const last = input[input.length - 1]!;
+ expect(last).toEqual({
+ type: "message",
+ role: "user",
+ content: [{ type: "input_text", text: latest }],
+ });
+ expect(input.some(item => item.role === "user" && item !== last)).toBe(true);
+ });
+
+ test("opted-in peel does not require metadata.user_id", () => {
+ const latest = footer(14_980_071);
+ const { body } = translateHarness(["You are Claude Code.", latest].join("\n\n"));
+ expect(body.instructions).toBe("You are Claude Code.");
+ const input = userTurns(body);
+ expect(input[input.length - 1]).toEqual({
+ type: "message",
+ role: "user",
+ content: [{ type: "input_text", text: latest }],
+ });
+ });
+
+ test("fenced standalone total_tokens example is a translator no-op when opted in", () => {
+ const system = ["You are a docs bot.", "```", footer(123), "```", ""].join("\n");
+ const { body } = translateHarness(system);
+ expect(body.instructions).toBe(system);
+ expect(userTurns(body)).toEqual([
+ { type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] },
+ ]);
+ });
+
+ test("open fence to EOF with a trailing total_tokens tag is not relocated", () => {
+ const system = ["You are a docs bot.", "```", footer(123)].join("\n");
+ const { body } = translateHarness(system);
+ expect(body.instructions).toBe(system);
+ expect(userTurns(body)).toEqual([
+ { type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] },
+ ]);
+ });
+
+ test("real footer after a closed fence still relocates when opted in", () => {
+ const docs = ["Docs:", "```", footer(123), "```"].join("\n");
+ const latest = footer(8000);
+ const { body } = translateHarness(`${docs}\n\n${latest}`);
+ expect(body.instructions).toBe(docs);
+ const input = userTurns(body);
+ expect(input[input.length - 1]).toEqual({
+ type: "message",
+ role: "user",
+ content: [{ type: "input_text", text: latest }],
+ });
+ });
+
+ test("whitespace-only system without a footer is preserved byte-for-byte", () => {
+ const system = " \n\n ";
+ const { body } = translate(system);
+ expect(body.instructions).toBe(system);
+ expect(userTurns(body)).toEqual([
+ { type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] },
+ ]);
+ });
+
+ test("Claude Code session prompt_cache_key is unchanged across trailing footers", () => {
+ const stable = "You are Claude Code.";
+ const keyOf = (system: string) =>
+ translateHarness(system, { user_id: "user-abc" }).body.prompt_cache_key as string;
+ const stableKey = keyOf(stable);
+ expect(stableKey).toMatch(/^[0-9a-f]{32}$/);
+ expect(keyOf([stable, footer(1000), footer(8000)].join("\n\n"))).toBe(stableKey);
+ expect(keyOf([stable, footer(99999)].join("\n\n"))).toBe(stableKey);
+ });
+
+ test("outside opt-in, Desktop prompt_cache_key hashes raw systemParts including footers", () => {
+ const stable = "You are Claude Code.";
+ const keyOf = (system: string) => translate(system).body.prompt_cache_key as string;
+ const stableKey = keyOf(stable);
+ expect(stableKey).toMatch(/^[0-9a-f]{32}$/);
+ expect(keyOf(stable)).toBe(stableKey);
+ expect(keyOf([stable, footer(8000)].join("\n\n"))).not.toBe(stableKey);
+ });
+
+ test("opted-in Desktop prompt_cache_key hashes stabilized instructions, not total_tokens footers", () => {
+ const stable = "You are Claude Code.";
+ const keyOf = (system: string) => translateHarness(system).body.prompt_cache_key as string;
+ const stableKey = keyOf(stable);
+ expect(stableKey).toMatch(/^[0-9a-f]{32}$/);
+ expect(keyOf([stable, footer(1000), footer(8000)].join("\n\n"))).toBe(stableKey);
+ expect(keyOf([stable, footer(99999)].join("\n\n"))).toBe(stableKey);
+ });
+
+ test("outside opt-in, a no-match Desktop key differs from the opted-in instructions-string key", () => {
+ const system = "You are Claude Code.\n\nPrefer terse answers.";
+ const rawKey = translate(system).body.prompt_cache_key as string;
+ const optedInKey = translateHarness(system).body.prompt_cache_key as string;
+ expect(rawKey).toMatch(/^[0-9a-f]{32}$/);
+ expect(optedInKey).toMatch(/^[0-9a-f]{32}$/);
+ expect(rawKey).not.toBe(optedInKey);
+ });
+
+ test("Claude Code /v1/messages inbound opts into prompt-cache stabilize", () => {
+ const source = readFileSync(repoPath("src/server/claude-messages.ts"), "utf8");
+ expect(source).toContain("stabilizePromptCache: true");
+ });
+});
diff --git a/tests/fixtures/test-layout-expected.json b/tests/fixtures/test-layout-expected.json
index 98907bd26a..a213efebf0 100644
--- a/tests/fixtures/test-layout-expected.json
+++ b/tests/fixtures/test-layout-expected.json
@@ -139,6 +139,7 @@
"claude-desktop-remote-hub.test.ts": "claude-integration",
"claude-dotenv-provenance-transport.test.ts": "claude-integration",
"claude-gateway-cache.test.ts": "claude-integration",
+ "claude-inbound-cache-stabilize.test.ts": "claude-integration",
"claude-inbound-debug.test.ts": "claude-integration",
"claude-inbound.test.ts": "claude-integration",
"claude-management-api.test.ts": "claude-integration",