-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(cursor): report decoded checkpoint shape so coverage is answerable from logs #4283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e7ab14f
3784658
b3b3e92
f529134
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # wp5 — making the coverage question answerable | ||
|
|
||
| Branch A landed, so the native wire-model gate now depends on one question: do the captured | ||
| bytes actually cover the tool call, or did they merely arrive after it? | ||
|
|
||
| ## Why this could not be settled by reading harder | ||
|
|
||
| `capturedAfterClientTool` is set from arrival order (`cursor.ts:312`), and | ||
| `conversationCheckpointUpdate` is classified liveness-only (`live-transport.ts:1221`). Every | ||
| diagnostic this adapter emits about a checkpoint reports its size in bytes, and a byte count | ||
| cannot distinguish a snapshot that contains the suspended call from one that does not. | ||
|
|
||
| The schema can. `ConversationStateStructure.pendingToolCalls` is documented upstream as | ||
| "raw JSON stringified tool-call content parts awaiting execution" — a non-zero count on a | ||
| suspended turn is the coverage evidence, and the strings themselves are request content that | ||
| must never be logged. | ||
|
|
||
| ## What landed | ||
|
|
||
| `cursorCheckpointShape` in `checkpoint-store.ts`: decodes a snapshot and returns **counts | ||
| only** for `turns`, `turnsOld`, `rootPromptMessages`, `todos`, `pendingToolCalls`. Failure | ||
| returns `undefined`; it never throws into the request path. Wired into | ||
| `checkpoint-commit-refused` as `capturedShape`, behind `isDebugEnabled()` so the decode does | ||
| not run on a normal request. | ||
|
|
||
| That converts the remaining question from "build an instrumented binary and decode bytes by | ||
| hand" into "read one log line". | ||
|
|
||
| ## What is NOT answered yet, and why | ||
|
|
||
| The live read needs this code running on a machine with a Cursor login. Attempts to shortcut | ||
| it with a standalone harness failed: driving the adapter outside the server never reaches the | ||
| credential initialisation the proxy does at startup (`getAccountSet` reports not-logged-in | ||
| even after `loadAuthStore`, which points at the keyring path rather than `auth.json`). | ||
|
|
||
| Running a second proxy would have worked, but only by either copying the credential store or | ||
| sharing the running instance's `OPENCODEX_HOME` and clobbering its pid and admin-token files. | ||
| Neither is worth it for a question that answers itself one release later. | ||
|
|
||
| **So wp5 is split.** The instrument is done. The live read is a follow-up: after this ships, | ||
| run a forced tool call on a Cursor account with `ocx debug provider on` and read | ||
| `capturedShape.pendingToolCalls` off `checkpoint-commit-refused`. | ||
|
|
||
| - `pendingToolCalls > 0` → the snapshot covers the call; the native gate can be removed with | ||
| the ordering proof upgraded to a coverage proof. | ||
| - `pendingToolCalls === 0` → arrival is not coverage, the current gate is correct, and the | ||
| native half of #4245 is not fixable this way. Record it and close. | ||
|
|
||
| Either answer is a real outcome. What was not acceptable was guessing, which is what the | ||
| original triage did and what this unit has now avoided four separate times. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,9 +24,11 @@ import { | |
| import { | ||
| commitCursorCheckpoint, | ||
| cursorCheckpointRefHash, | ||
| cursorCheckpointShape, | ||
| invalidateCursorCheckpoint, | ||
| } from "./cursor/checkpoint-store"; | ||
| import { debugProviderDiagnostic } from "../lib/debug"; | ||
| import { isDebugEnabled } from "../lib/debug-settings"; | ||
| import { createAdapterTierMetadata } from "../providers/fastwire"; | ||
| import { estimateTokens } from "../lib/token-estimate"; | ||
| import { rememberCursorThreadConversation } from "./cursor/thread-continuity"; | ||
|
|
@@ -208,6 +210,10 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda | |
| externalModel: isCursorExternalWireModel(activeRequest.modelId), | ||
| storeCheckpoints: activeRequest.contextUsageStoreCheckpoints !== false, | ||
| capturedBytes: lastTransport?.captured?.byteLength ?? 0, | ||
| // Byte length says nothing about coverage. `pendingToolCalls` does: it is what | ||
| // distinguishes a snapshot that knows about the suspended call from one that merely | ||
| // arrived after it (#4245). Counts only; the decode is skipped unless debug is on. | ||
| capturedShape: isDebugEnabled() ? cursorCheckpointShape(lastTransport?.captured) : undefined, | ||
|
Comment on lines
+213
to
+216
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This changes checkpoint diagnostics within the AGENTS.md reference: src/AGENTS.md:L10-L11 Useful? React with 👍 / 👎. |
||
| }); | ||
| return; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the stale source location.
capturedAfterClientToolis assigned insrc/adapters/cursor.tsat Line 318, notcursor.ts:312. Update this reference so the diagnostic evidence remains traceable.🤖 Prompt for AI Agents