Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Bug] Cursor replay clips completed-call arguments at 2 KiB despite spare aggregate budget #4516

Description

@stephen-drew

Client or integration

Codex App

Area

Provider adapter

Summary

Separate linked defect requested in #3506 (comment).

A completed call can contain a value beyond the 2 KiB argument prefix. When its result confirms success without repeating that value, the Cursor replay roots omit the value even with almost the entire 512 KiB replay budget unused. The result survives, but the model cannot recover the omitted argument from those roots.

Expected: after admitting retained history and result output, use spare aggregate bytes to retain complete recent invocations where they fit. Preserve result priority, retained history, call identity/order, checkpoint-carried bytes, the 192-root/512-KiB bounds and UTF-8 accounting. Keep bounded prefixes when the complete invocation cannot fit. Do not remove the per-call admission cap outright.

This is the independently reproduced argument-loss problem, not a claim that it causes the four under-2-KiB rejected patches in #3506. Please keep that broader issue separate and open.

Reproduction

  1. In an OpenCodex checkout with its normal Bun dependencies installed, save the fixture below as .tmp/cursor-continuity/upstream-argument-fixture.ts.
  2. Run the baseline commands below. The fixture passes through the real Responses parser, Cursor request builder, protobuf encoder and KV root hydration. It does not contact a provider or execute a tool.
  3. The synthetic successful call is 4,693 UTF-8 bytes. Its unique marker occurs after the prefix cutoff; neither the user message nor successful tool output contains it. Observe markerPresent=false while resultPreserved=true.
  4. In a disposable checkout, apply the candidate encoder diff below, then run with --expect-retained. The marker and exact original arguments, including Unicode and JavaScript replacement literals, must round-trip. --checkpoint repeats this with a non-empty synthetic checkpoint and the tool result in the replay suffix.
  5. The script prints the full synthetic input and hydrated roots. These are offline reconstructions, not a live Cursor payload capture or a model response.
bun .tmp/cursor-continuity/upstream-argument-fixture.ts
bun .tmp/cursor-continuity/upstream-argument-fixture.ts --checkpoint
# After applying the candidate to a disposable checkout:
bun .tmp/cursor-continuity/upstream-argument-fixture.ts --expect-retained
bun .tmp/cursor-continuity/upstream-argument-fixture.ts --checkpoint --expect-retained

The optional --source argument substitutes only the encoder source in the isolated Bun process. We used it to compare the exact baseline and focused candidate without changing installed runtime files or the existing development candidate.

Version

Installed OpenCodex 2.52.0; reported Codex Desktop task runtime 0.153.4. Fresh offline fixture and regression environment: OpenCodex checkout 2.50.0 commit 2d4d7a2, Bun 1.4.2.

The official baseline encoder from that commit is byte-identical to the currently installed 2.52.0 encoder: SHA-256 c5d009802d7b1154697ac6a3823cff3cf70e07db2afbffde484bead322af3e74. The surrounding parser/builder dependencies in this offline run are from the stated 2.50.0 checkout; this is not an assertion that all dependencies across the releases are identical.

The focused candidate encoder SHA-256 is d962f8e1334e09047b8bab30bdd054fff52e9b4e0536836153afc6342af354eb. It adds only the spare-budget expansion block to that official baseline, excluding our earlier brief/history retention patches. It is not installed.

Operating system

Windows 11 25H2, x64.

Provider and model

cursor / grok-4.6; the fixture requests xhigh. This records the requested selection, not independently verified backend effort. Fresh runs below make zero provider requests.

Logs or error output

Fresh deterministic results:

Encoder Mode Marker retained Result retained Roots Root bytes
Baseline full replay false true 4 6011
Candidate full replay true true 4 9054
Baseline synthetic checkpoint plus suffix false true 2 2421
Candidate synthetic checkpoint plus suffix true true 2 5464

The candidate passed 27 tests / 0 failures / 76 assertions in cursor-tool-result-invocation.test.ts with only that encoder substituted. This includes the three proposed regression cases below: exact successful-call retention, newest-first expansion under budget pressure without dropping earlier results, and checkpoint-covered call lookup. The standalone fixture additionally checks UTF-8 root sizes, root count and exact Unicode/literal argument round-trip. These are focused checks for a candidate, not a full release qualification.

Historical, separate live synthetic probes on 11 September 2026: bounded argument replay produced MISSING; complete arguments in the same text-role format produced exact recall; the earlier combined candidate also produced exact recall. Those used different synthetic random markers and an earlier local encoder base. They support the isolated recall defect but are not fresh live validation of the focused candidate attached here. No new live capture or provider request was made for this report.

Screenshots and supporting files

All contents below are synthetic or repository code. No production task history, protobuf, checkpoint, local account data or credentials are attached.

Standalone fixture (Bun TypeScript)
// Save as .tmp/cursor-continuity/upstream-argument-fixture.ts in an OpenCodex checkout.
// Offline synthetic reconstruction only. No provider, credentials or real tool execution.
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';

const sourceIndex = process.argv.indexOf('--source');
const encoderPath = resolve(import.meta.dir, '../../src/adapters/cursor/protobuf-request.ts');
const source = readFileSync(sourceIndex >= 0 ? process.argv[sourceIndex + 1] : encoderPath, 'utf8');
Bun.plugin({ name: 'synthetic-encoder-only', setup(build) {
  build.onLoad({ filter: /protobuf-request\.ts$/ }, args => {
    assert.equal(resolve(args.path), encoderPath);
    return { loader: 'ts', contents: source };
  });
}});
const { parseRequest } = await import('../../src/responses/parser');
const { createCursorRequest } = await import('../../src/adapters/cursor/request-builder');
const { prepareCursorRunRequest } = await import('../../src/adapters/cursor/protobuf-request');
const { handleCursorNativeKv, releaseCursorBlobRequestScope, storeCursorBlob } = await import('../../src/adapters/cursor/native-exec');
const { create, fromBinary, toBinary } = await import('@bufbuild/protobuf');
const { AgentClientMessageSchema, KvServerMessageSchema, GetBlobArgsSchema, ConversationStateStructureSchema } = await import('../../src/adapters/cursor/gen/agent_pb');

const rejected = process.argv.includes('--rejected-patch');
const checkpoint = process.argv.includes('--checkpoint');
const marker = 'SYNTHETIC_TAIL_71e463b9';
const call = rejected
  ? 'text(await tools.apply_patch(`*** Begin Patch ***\n*** Update File: fixture.txt\n@@\n-old\n+new\n*** End Patch`));'
  : '// synthetic padding\n'.repeat(220) + 'write_value("' + marker + '", "界🙂", "$&", "$$", "$`", "$\'")';
const output = rejected
  ? "apply_patch verification failed: invalid patch: The first line of the patch must be '*** Begin Patch'"
  : 'Success. Updated fixture.txt.';
assert(!output.includes(marker));
const input = {
  model: 'cursor/grok-4.6',
  reasoning: { effort: 'xhigh' },
  tools: [{ type: 'custom', name: 'exec', description: 'Synthetic tool. No real files or execution.', format: { type: 'text' } }],
  input: [
    { role: 'user', content: rejected ? 'Correct the rejected patch formatting.' : 'Return the value from the end of the completed call. Return MISSING if absent.' },
    { type: 'custom_tool_call', name: 'exec', call_id: 'synthetic_call', input: call },
    { type: 'custom_tool_call_output', call_id: 'synthetic_call', output: [{ type: 'input_text', text: output }] },
  ],
};
const request = createCursorRequest(parseRequest(input));
request.conversationId = 'offline-synthetic-fixture';
request.contextUsageStoreCheckpoints = false;
if (checkpoint) {
  const carried = storeCursorBlob(new TextEncoder().encode(JSON.stringify({ role: 'user', content: [{ type: 'text', text: 'Synthetic covered prefix.' }] })));
  request.checkpointBytes = toBinary(ConversationStateStructureSchema, create(ConversationStateStructureSchema, { rootPromptMessagesJson: [carried] }));
  request.continuationMode = 'checkpoint';
  request.checkpointSuffixStart = 2;
}
const prepared = prepareCursorRunRequest(request);
const wire = fromBinary(AgentClientMessageSchema, prepared.bytes);
assert.equal(wire.message.case, 'runRequest');
const roots = (wire.message as any).value.conversationState.rootPromptMessagesJson.map((blobId: Uint8Array) => {
  const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { id: 1, message: { case: 'getBlobArgs', value: create(GetBlobArgsSchema, { blobId }) } }), prepared.blobRequestScope));
  assert.equal(reply.message.case, 'kvClientMessage');
  const kv = (reply.message as any).value.message;
  assert.equal(kv.case, 'getBlobResult');
  return JSON.parse(new TextDecoder().decode(kv.value.blobData));
});
releaseCursorBlobRequestScope(prepared.blobRequestScope);
const rootText = roots.map((root: any) => typeof root.content === 'string' ? root.content : (root.content ?? []).map((item: any) => item.text ?? '').join('\n')).join('\n');
const rootBytes = roots.reduce((total: number, root: any) => total + Buffer.byteLength(JSON.stringify(root)), 0);
assert(rootText.includes(output), 'Tool feedback was lost');
assert(roots.length <= 192 && rootBytes <= 512 * 1024, 'Replay bounds exceeded');
if (checkpoint) assert(rootText.includes('Synthetic covered prefix.'), 'Checkpoint root absent');
const markerPresent = rootText.includes(marker);
if (process.argv.includes('--expect-retained')) {
  assert(markerPresent, 'Completed-call tail was lost');
  const line = rootText.split('\n').find(line => line.startsWith('invoked: exec with '));
  assert(line, 'Invocation absent');
  const args = JSON.parse(line.slice('invoked: exec with '.length));
  assert.equal(args.input, call, 'Arguments did not round-trip exactly');
}
console.log(JSON.stringify({
  evidence: 'Offline reconstruction from a synthetic input, not a live payload capture or model response',
  encoderSha256: new Bun.CryptoHasher('sha256').update(source).digest('hex'),
  mode: checkpoint ? 'synthetic checkpoint plus suffix' : 'full replay',
  scenario: rejected ? 'rejected patch' : 'completed-call argument retention',
  providerRequests: 0, realToolExecutions: 0,
  callBytes: Buffer.byteLength(call), markerPresent, resultPreserved: rootText.includes(output),
  rootCount: roots.length, rootBytes, input, hydratedRoots: roots,
}, null, 2));
Focused candidate encoder diff
diff --git a/src/adapters/cursor/protobuf-request.ts b/src/adapters/cursor/protobuf-request.ts
--- a/src/adapters/cursor/protobuf-request.ts
+++ b/src/adapters/cursor/protobuf-request.ts
@@ -694,6 +694,38 @@ function rootPromptMessages(
     historyMessageStart = firstKept?.messageIndex ?? (messages.length);
   }
 
+  // Reserve history and result output first, then spend only unused root bytes on complete
+  // invocations, newest first. The 2 KiB admission prefix alone can hide a successful write's
+  // final value even in a tiny conversation. Expansion must never evict another retained root
+  // or recreate output already truncated by the history budget.
+  if (externalModel && replayedCalls) {
+    let spareBytes = CURSOR_EXTERNAL_ROOT_BYTE_LIMIT - carriedRoots.byteLength
+      - selected.reduce((sum, entry) => sum + entry.byteLength, 0);
+    for (let index = selected.length - 1; index >= 0 && spareBytes > 0; index--) {
+      const entry = selected[index]!;
+      if (entry.role !== "toolResult" || entry.messageIndex === undefined || entry.outputElided) continue;
+      const message = messages[entry.messageIndex];
+      if (message?.role !== "toolResult") continue;
+      const call = callBefore(replayedCalls, decodeCursorCallId(message.toolCallId), knownCallsOffset + entry.messageIndex);
+      if (!call) continue;
+      const fullArgs = serializeToolCallArguments(call.arguments);
+      if (fullArgs === undefined) continue;
+      const fullArgsBytes = encoder.encode(fullArgs).byteLength;
+      if (fullArgsBytes <= CURSOR_INVOCATION_ARGUMENTS_BYTE_LIMIT
+        || fullArgsBytes - CURSOR_INVOCATION_ARGUMENTS_BYTE_LIMIT > spareBytes) continue;
+      const payload = JSON.parse(entry.serialized) as { role: "assistant"; content: [{ type: "text"; text: string }] };
+      const boundedLine = `\n${toolInvocationLine(call)}\n`;
+      if (!payload.content[0].text.includes(boundedLine)) continue;
+      const text = payload.content[0].text.replace(boundedLine, () => `\ninvoked: ${namespacedToolName(call.namespace, call.name)} with ${fullArgs}\n`);
+      const expanded = rootBlobCandidate(toolResultRootPayload(text), "toolResult", { messageIndex: entry.messageIndex, text });
+      const extraBytes = expanded.byteLength - entry.byteLength;
+      if (extraBytes <= spareBytes) {
+        selected[index] = expanded;
+        spareBytes -= extraBytes;
+      }
+    }
+  }
+
   return {
     ids: selected.map(entry => storeCursorBlob(entry.data, requestScope)),
     byteLength: selected.reduce((sum, entry) => sum + entry.byteLength, 0),
Three regression tests added to the existing invocation suite
diff --git a/tests/providers/cursor/cursor-tool-result-invocation.test.ts b/tests/providers/cursor/cursor-tool-result-invocation.test.ts
index aa3b9d16d..1397956eb 100644
--- a/tests/providers/cursor/cursor-tool-result-invocation.test.ts
+++ b/tests/providers/cursor/cursor-tool-result-invocation.test.ts
@@ -131,6 +131,54 @@ function resultRoot(bytes: Uint8Array): string | undefined {
  * decode the real wire payload, since roots are what Cursor builds the model prompt from.
  */
 describe("cursor replayed tool results name their invocation", () => {
+  test("spare replay space preserves the complete successful call", () => {
+    const input = '// fixture preparation\n'.repeat(250) + 'write_verified_value("COMPLETED_VALUE", "$&", "$$", "$`", "$\'")';
+    const messages: OcxMessage[] = [
+      { role: "user", content: "Return the value written by the completed call.", timestamp: 1 },
+      { role: "assistant", content: [{ type: "toolCall", id: CALL_ID, name: "exec", arguments: { input } }], timestamp: 2 },
+      { role: "toolResult", toolCallId: CALL_ID, toolName: "exec", content: "Write completed successfully.", isError: false, timestamp: 3 },
+    ];
+    const root = resultRoot(encode(messages, "grok-4.6-high"));
+    expect(root).toContain("COMPLETED_VALUE");
+    expect(root).toContain("Write completed successfully.");
+    expect(root).not.toContain("[arguments truncated]");
+    const invocation = root!.split("\n").find(line => line.startsWith("invoked: exec with "))!;
+    expect(JSON.parse(invocation.slice("invoked: exec with ".length))).toEqual({ input });
+  });
+
+  test("spare replay space restores the newest call without evicting prior results", () => {
+    const oldInput = 'x'.repeat(12000) + 'OLDER_VALUE';
+    const newInput = 'y'.repeat(12000) + 'LATEST_VALUE';
+    const messages: OcxMessage[] = [
+      { role: "user", content: "Both writes are complete.", timestamp: 1 },
+      { role: "assistant", content: [{ type: "toolCall", id: "old_call", name: "exec", arguments: { input: oldInput } }], timestamp: 2 },
+      { role: "toolResult", toolCallId: "old_call", toolName: "exec", content: "OLDER_OUTPUT", isError: false, timestamp: 3 },
+      { role: "assistant", content: [{ type: "toolCall", id: "new_call", name: "exec", arguments: { input: newInput } }], timestamp: 4 },
+      { role: "toolResult", toolCallId: "new_call", toolName: "exec", content: "LATEST_OUTPUT", isError: false, timestamp: 5 },
+    ];
+    const bytes = encodeCursorRunRequest({ modelId: "grok-4.6-high", conversationId: "spare-space", system: ['s'.repeat(512 * 1024 - 20 * 1024)], rawMessages: messages, messages: [{ role: "tool", content: "LATEST_OUTPUT" }] });
+    const text = rootTexts(bytes).join("\n");
+    expect(text).toContain("LATEST_VALUE");
+    expect(text).not.toContain("OLDER_VALUE");
+    expect(text).toContain("OLDER_OUTPUT");
+    expect(text).toContain("LATEST_OUTPUT");
+    expect(text).toContain("Both writes are complete.");
+  });
+
+  test("spare replay space restores a checkpoint-covered call in its result suffix", () => {
+    const input = 'q'.repeat(6000) + 'CHECKPOINT_CALL_TAIL';
+    const messages: OcxMessage[] = [
+      { role: "user", content: "Complete the write.", timestamp: 1 },
+      { role: "assistant", content: [{ type: "toolCall", id: CALL_ID, name: "exec", arguments: { input } }], timestamp: 2 },
+      { role: "toolResult", toolCallId: CALL_ID, toolName: "exec", content: "CHECKPOINT_RESULT", isError: false, timestamp: 3 },
+    ];
+    const bytes = encodeCheckpoint(messages, "grok-4.6-high", 2);
+    const text = rootTexts(bytes).join("\n");
+    expect(text).toContain("covered by checkpoint");
+    expect(text).toContain("CHECKPOINT_CALL_TAIL");
+    expect(text).toContain("CHECKPOINT_RESULT");
+  });
+
   test("the result envelope names the tool and arguments that produced it", () => {
     const root = resultRoot(encode(history(), "grok-4.6-high"));
     expect(root).toBeDefined();
Exact hydrated roots BEFORE, full replay (synthetic offline reconstruction)
[
  {
    "role": "system",
    "content": "You are a helpful assistant."
  },
  {
    "role": "system",
    "content": "Cursor tool calls: available tool names are exactly `exec`. Use the current tool catalog as ground truth and call only those exact names with their listed argument keys. This turn does not expose neighboring-agent tool names `Read`, `Grep`, `Glob`, `Bash`, `LS`; do not call or suggest them unless the catalog lists them. `exec` is Codex code mode: its body is JavaScript evaluated in a V8 isolate, not a shell command and not Node. Shell, file edits, and MCP are nested helpers called INSIDE that body as `await tools.<name>(...)`, for example `await tools.exec_command({cmd: \"ls\"})`. Read the tool description and the isolate global `ALL_TOOLS` (not `tools.ALL_TOOLS`) for helpers this turn provides; absence from the top-level catalog or from `exec`'s description is not absence. Those nested helpers are not themselves top-level tools, so do not call `exec_command` or `shell_command` at the top level here. Nested `tools.apply_patch(input)` is host-executed: the string must begin exactly with `*** Begin Patch` and end with `*** End Patch`, each marker line being three asterisks, one space, the two words, then end of line with no further asterisks. OpenCodex does not rewrite JavaScript inside exec, so extra asterisks on a marker line are rejected by Codex before the file is touched. Nothing in the isolate is echoed automatically: a bare trailing `await tools.<name>(...)` or final expression value is DISCARDED, and the cell reports empty output. Pass anything you need to read to `text(...)` (or `notify(...)`) in the same cell — for example `text(JSON.stringify(await tools.exec_command({cmd: 'ls'})))` — and treat an empty result as your own missing `text(...)` call rather than a failed command or lost context. There is no `require`, no `module`, and no filesystem or network globals; reach the host only through the nested helpers. Host contract for the nested helpers: `tools.apply_patch(patch)` takes exactly one string, never an object such as `{input: ...}`; the patch text opens with the bare marker line `*** Begin Patch` and closes with the bare marker line `*** End Patch`, written without a code fence, prose, or extra asterisks on those lines (blank lines or indentation around the markers are tolerated; a decorated or missing marker is rejected). The isolate has no `import`, `require`, or module loader; use the globals the exec tool description lists (for example `tools`, `text`, `notify`, `store`/`load`, `ALL_TOOLS`). For a command that may outlive `yield_time_ms`, let `tools.exec_command` return a `session_id` and poll it on later calls with `tools.write_stdin({session_id, chars: \"\"})` instead of blocking a shell in a sleep loop. NEVER attempt Cursor-native Shell, Read, Grep, List, or any tool absent from the catalog — they are not executed in this environment and every probe wastes a turn. The exec code cell (with its nested helpers) is the ONLY execution surface; go to it directly on the FIRST attempt and do not narrate switching surfaces. Cursor product features (Chronicle, screen recording, Notes, Plans, background agents) are available only if this turn's catalog lists a matching tool; do not offer or promise them otherwise. For independent read-only tool-count or batch requests, prefer one response containing multiple tool calls before waiting for results when the runtime supports parallel tool calls. Do not count or report a tool call unless a tool result was actually returned."
  },
  {
    "role": "user",
    "content": [
      {
        "type": "text",
        "text": "Return the value from the end of the completed call. Return MISSING if absent."
      }
    ]
  },
  {
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "[Tool Result]\n[tool_result]\ncall_id: synthetic_call\nname: exec\ninvoked: exec with {\"input\":\"// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic…[arguments truncated]\nis_error: false\noutput:\nSuccess. Updated fixture.txt."
      }
    ]
  }
]
Exact hydrated roots AFTER, full replay (synthetic offline reconstruction)
[
  {
    "role": "system",
    "content": "You are a helpful assistant."
  },
  {
    "role": "system",
    "content": "Cursor tool calls: available tool names are exactly `exec`. Use the current tool catalog as ground truth and call only those exact names with their listed argument keys. This turn does not expose neighboring-agent tool names `Read`, `Grep`, `Glob`, `Bash`, `LS`; do not call or suggest them unless the catalog lists them. `exec` is Codex code mode: its body is JavaScript evaluated in a V8 isolate, not a shell command and not Node. Shell, file edits, and MCP are nested helpers called INSIDE that body as `await tools.<name>(...)`, for example `await tools.exec_command({cmd: \"ls\"})`. Read the tool description and the isolate global `ALL_TOOLS` (not `tools.ALL_TOOLS`) for helpers this turn provides; absence from the top-level catalog or from `exec`'s description is not absence. Those nested helpers are not themselves top-level tools, so do not call `exec_command` or `shell_command` at the top level here. Nested `tools.apply_patch(input)` is host-executed: the string must begin exactly with `*** Begin Patch` and end with `*** End Patch`, each marker line being three asterisks, one space, the two words, then end of line with no further asterisks. OpenCodex does not rewrite JavaScript inside exec, so extra asterisks on a marker line are rejected by Codex before the file is touched. Nothing in the isolate is echoed automatically: a bare trailing `await tools.<name>(...)` or final expression value is DISCARDED, and the cell reports empty output. Pass anything you need to read to `text(...)` (or `notify(...)`) in the same cell — for example `text(JSON.stringify(await tools.exec_command({cmd: 'ls'})))` — and treat an empty result as your own missing `text(...)` call rather than a failed command or lost context. There is no `require`, no `module`, and no filesystem or network globals; reach the host only through the nested helpers. Host contract for the nested helpers: `tools.apply_patch(patch)` takes exactly one string, never an object such as `{input: ...}`; the patch text opens with the bare marker line `*** Begin Patch` and closes with the bare marker line `*** End Patch`, written without a code fence, prose, or extra asterisks on those lines (blank lines or indentation around the markers are tolerated; a decorated or missing marker is rejected). The isolate has no `import`, `require`, or module loader; use the globals the exec tool description lists (for example `tools`, `text`, `notify`, `store`/`load`, `ALL_TOOLS`). For a command that may outlive `yield_time_ms`, let `tools.exec_command` return a `session_id` and poll it on later calls with `tools.write_stdin({session_id, chars: \"\"})` instead of blocking a shell in a sleep loop. NEVER attempt Cursor-native Shell, Read, Grep, List, or any tool absent from the catalog — they are not executed in this environment and every probe wastes a turn. The exec code cell (with its nested helpers) is the ONLY execution surface; go to it directly on the FIRST attempt and do not narrate switching surfaces. Cursor product features (Chronicle, screen recording, Notes, Plans, background agents) are available only if this turn's catalog lists a matching tool; do not offer or promise them otherwise. For independent read-only tool-count or batch requests, prefer one response containing multiple tool calls before waiting for results when the runtime supports parallel tool calls. Do not count or report a tool call unless a tool result was actually returned."
  },
  {
    "role": "user",
    "content": [
      {
        "type": "text",
        "text": "Return the value from the end of the completed call. Return MISSING if absent."
      }
    ]
  },
  {
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "[Tool Result]\n[tool_result]\ncall_id: synthetic_call\nname: exec\ninvoked: exec with {\"input\":\"// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\n// synthetic padding\\nwrite_value(\\\"SYNTHETIC_TAIL_71e463b9\\\", \\\"界🙂\\\", \\\"$&\\\", \\\"$$\\\", \\\"$`\\\", \\\"$'\\\")\"}\nis_error: false\noutput:\nSuccess. Updated fixture.txt."
      }
    ]
  }
]

Related #3506 diagnostic: the same fixture accepts --rejected-patch and --rejected-patch --checkpoint. Fresh baseline runs preserve the exact rejection text in both modes (4,227 and 677 root bytes respectively). This is a negative control for feedback loss, not a reproduction of the live repetition. A historical minimal live correction probe also corrected the formatting, so no failing synthetic model-response pair is claimed. Exact live capture instrumentation remains separate from this report.

Redacted configuration

{
  "client": "Codex App",
  "provider": "cursor",
  "model": "grok-4.6",
  "fixture": "offline; no credentials, accounts, network or real tool execution"
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingproviderProvider adapters, OpenAI-compat presets, upstream API quirks

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions