-
Notifications
You must be signed in to change notification settings - Fork 905
fix(cursor): single-line call_id codec + response.in_progress parity #2650
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
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
6ebf925
devlog(260826_cursor_responses_gap): plan + seed-thread failure catalog
0c2a8e1
devlog(260826_cursor_responses_gap): probe campaign + gap summary dec…
6fd9eb0
devlog(260826_cursor_responses_gap): curl-phase probe evidence P1-P12…
b909384
devlog(260826_cursor_responses_gap): subagent fleet evidence S1/S2, s…
64e69b0
devlog(260826_cursor_responses_gap): severity-ranked gap summary G1-G9
ab3708b
devlog(260826_cursor_responses_gap): ultra/k3/1M research ledger
ed81489
devlog(260826_cursor_responses_gap): implementation decade docs 030-0…
773d774
fix(cursor): single-line call_id codec + response.in_progress parity
73cc275
test(lab): shift streaming-turn phase selector for response.in_progress
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| # 260826 cursor responses gap — unit plan (P artifact, docs-only cycle) | ||
|
|
||
| Goal: document what the cursor adapter still lacks to serve as a real Codex | ||
| Responses backend, seeded by thread 01a03beb-a886-74f2-83be-5bf998f9fa4a | ||
| ("Test apply_patch 적용", cursor-routed Codex app session) and measured by a | ||
| live probe campaign against `cursor/grok-4.6` through the local proxy | ||
| (port 10100, opencodex 2.32.1-preview.20260825). | ||
|
|
||
| ## Loop-spec header | ||
|
|
||
| - Archetype: spec-satisfaction (documentation unit; verifier = docs exist + | ||
| probe evidence recorded + src/ untouched). | ||
| - Trigger: user request to analyze cursor incompleteness with repeated | ||
| grok-4.6 probing and record it in devlog. | ||
| - Goal: severity-ranked gap catalog with file:line citations + >=10 probe | ||
| evidence rows. | ||
| - Non-goals: fixing the adapter, provider config changes, issues/PRs, pushes. | ||
| - Verifier: `ls devlog/_plan/260826_cursor_responses_gap` (docs), | ||
| `git status --short src/` (must be empty), probe-count grep in 010 doc. | ||
| All three run and read the change target (this unit's files / src tree). | ||
| - Stop: all three docs written and consistent; bounds = ~40min probing, | ||
| <=30 live probes, <=3 retries per probe class. | ||
| - Memory artifact: this unit. | ||
| - Terminal outcomes: DONE / BLOCKED (cursor pool refuses all probes) / | ||
| BUDGET_EXHAUSTED (probe shortfall stated) / NEEDS_HUMAN. | ||
| - Escalation: cursor account/token actions (rotation, login) are user-owned. | ||
|
|
||
| ## Seed-thread symptom list (evidence base for 001) | ||
|
|
||
| From codex://threads/01a03beb-a886-74f2-83be-5bf998f9fa4a (full turn read): | ||
|
|
||
| 1. Every reasoning block restarts with "Continuing from previous | ||
| conversation / 이전 대화에서 이어서" — the model re-orients every tool | ||
| round-trip as if the conversation was replayed, repeats working-directory | ||
| checks 3+ times, and re-announces the same commentary. | ||
| 2. All commandExecution items report `durationMs: 0`. | ||
| 3. Model self-reports "previous tool results were garbled" and "the exec | ||
| tool only returned a working directory check" — tool output loss or | ||
| truncation on the wire. | ||
| 4. apply_patch first attempt failed: "first line lacked the required | ||
| `*** Begin Patch` header" (decorated/mangled envelope emitted by the | ||
| cursor-trained model). | ||
| 5. Repeated shell quoting failures (python3 -c with nested quotes) — model | ||
| behavior, but amplified by lost tool feedback. | ||
| 6. Task that should be ~3 tool calls took 179s and ~15 tool rounds. | ||
|
|
||
| ## File-change map (docs only) | ||
|
|
||
| - ADD 000_plan.md (this doc). | ||
| - ADD 001_seed_thread_failure_catalog.md — symptom -> code-path map with | ||
| file:line into src/adapters/cursor/* and src/server/responses/core.ts; | ||
| UNKNOWN rows carry the stated evidence gap. | ||
| - ADD 010_probe_campaign.md — decade doc for wp2: probe matrix (8 classes), | ||
| per-probe evidence rows appended during wp2. | ||
| - ADD 020_gap_summary.md — decade doc for wp3: severity-ranked gaps. | ||
| - OUT of scope: any file outside this unit directory. | ||
|
|
||
| ## Probe matrix (consumed by wp2) | ||
|
|
||
| | # | Class | Method | | ||
| |---|-------|--------| | ||
| | P1 | plain completion | curl /v1/responses stream=false | | ||
| | P2 | streaming | curl stream=true, inspect SSE event sequence | | ||
| | P3 | single tool call | curl with one function tool, check call fidelity | | ||
| | P4 | multi tool call | two tools, parallel-call handling | | ||
| | P5 | tool-result round trip | 2-turn: function_call_output back in input | | ||
| | P6 | apply_patch freeform | custom tool shaped like Codex apply_patch | | ||
| | P7 | multi-turn continuity | previous_response_id + history replay | | ||
| | P8 | reasoning handling | reasoning items in replayed input | | ||
| | P9 | parallel/concurrent | 3 simultaneous requests | | ||
| | P10 | native subagent | spawn_agent model=cursor/grok-4.6 real task | | ||
| | P11 | checkpoint reuse | >=3 turns, tool results interleaved, same thread — exercises trailing_tool_result invalidation (checkpoint-store.ts) | | ||
| | P12 | tool-output stress | large (>=64KB), multi-line, ANSI/unicode tool result payloads round-tripped | | ||
| | C1 | cross-provider control | replay P5/P7/P8 through xai/grok-4.6 (same base model, different adapter) | | ||
| | C2 | cross-model control | cursor/claude-opus-5 and cursor/gemini-3.7-flash through same adapter | | ||
| | S1 | subagent fleet (parallel) | parallel spawn_agent dispatches; sol medium reviewers + cursor/grok-4.6 workers side by side | | ||
| | S2 | subagent plugin surface | cursor-model subagents driving plugin/tool surfaces (computer-use screenshot-read, browser read, exec/apply_patch) — full tool-catalog exposure test | | ||
|
|
||
| Each probe records: request shape, HTTP/status, response/stream behavior, | ||
| usage block, pass/fail, raw snippet. Repeats within bounds count as extra | ||
| probes toward the >=10 minimum. | ||
|
|
||
| ### Audit fold-back (round 1, GO-WITH-FIXES blockers=4) | ||
|
|
||
| 1. (High) Control probes added: C1 cross-provider (xai/grok-4.6 live in | ||
| catalog, verified) and C2 cross-model — separates adapter gaps from | ||
| grok-4.6 training behavior. | ||
| 2. (High) Subagent fence: P10/S1/S2 subagent tasks are pinned read-only or | ||
| to `mktemp -d` scratch workspaces; no writes outside scratch + this | ||
| devlog unit. Plugin-surface tests (S2) use observation-only actions | ||
| (screenshot/read); no destructive or account-mutating plugin calls. | ||
| 3. (Medium) Code-path anchors corrected: primary surfaces are | ||
| protobuf-request.ts:225-260 (root replay flattening + reasoning drop for | ||
| external wire models), protobuf-events.ts:702/:896 (apply_patch grammar | ||
| repair + structured-edit conversion, #1017), checkpoint-store.ts:11-27 | ||
| (TTL/invalidation), tool-result-normalize.ts, native-exec-shell.ts:136. | ||
| message-mapper.ts / thread-continuity.ts are thin and demoted to | ||
| secondary references. durationMs:0 is plausibly Codex-client-side — | ||
| 001 carries it as UNKNOWN with the evidence gap stated. | ||
| 4. (Medium) Probe-count verifier is now concrete: | ||
| `rg -c '^\| (P|C|S)[0-9]' devlog/_plan/260826_cursor_responses_gap/010_probe_campaign.md` | ||
| must report >= 10 evidence rows (pass condition), and each row carries a | ||
| pass/fail column. | ||
|
|
||
| ### User scope addition (mid-A, 2026-08-26) | ||
|
|
||
| The user extended wp2: dispatch sol medium subagents in parallel, run cursor | ||
| models themselves as subagents, and exercise plugin surfaces (Computer use | ||
| et al.) across the board — captured as S1/S2 above. Rate-limit spend on the | ||
| user's Cursor account is bounded by the existing <=30-probe budget; probe | ||
| failures from quota/rotation are recorded as evidence, not retried past 3. | ||
|
|
||
| ## Accept criteria (testable) | ||
|
|
||
| - c1: every symptom row in 001 names file:line or UNKNOWN + gap. | ||
| - c2: >=10 probe rows in 010 spanning all classes P1-P10. | ||
| - c3: 020 ranks gaps by severity with evidence pointers. | ||
| - c4: numbered filenames only; `git status --short src/` empty at close. | ||
|
|
||
| ## Conditional paths | ||
|
|
||
| Docs-only cycle: no production conditional paths are added, so | ||
| C-ACTIVATION-GROUNDING-01 rows are N/A; probe classes themselves are the | ||
| activation scenarios for wp2 evidence. | ||
122 changes: 122 additions & 0 deletions
122
devlog/_plan/260826_cursor_responses_gap/001_seed_thread_failure_catalog.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| # 001 — Seed-thread failure catalog (thread 01a03beb-a886-74f2-83be-5bf998f9fa4a) | ||
|
|
||
| Seed: Codex app thread "Test apply_patch 적용", cwd | ||
| `/Users/jun/Downloads/hellobot-detail-studio`, single turn, 179.4s, | ||
| ~15 tool rounds for a task that natively takes ~3. Model route: | ||
| `cursor/grok-4.6` through the local proxy. Full turn read on 2026-08-26. | ||
|
|
||
| Verdict legend: ADAPTER = opencodex cursor adapter mechanism; MODEL = | ||
| grok-4.6/cursor-training behavior; CLIENT = Codex app/client-side; | ||
| UNKNOWN = evidence gap stated. | ||
|
|
||
| ## S1 — Per-round context re-orientation ("Continuing from previous conversation") | ||
|
|
||
| Evidence: every reasoning block in the seed thread restarts with | ||
| "Continuing from the previous conversation / 이전 대화에서 이어서"; the | ||
| model re-checked `pwd`/workspace state at least 4 separate times and | ||
| re-announced near-identical commentary each round. | ||
|
|
||
| Mechanism (ADAPTER, primary): | ||
|
|
||
| - src/adapters/cursor/protobuf-request.ts:225-260 — history replay for | ||
| external wire models flattens prior turns into root text blobs: | ||
| user/developer messages as text parts, assistant text via | ||
| `assistantRootText(message, !externalModel)` — i.e. for external models | ||
| (grok) hidden reasoning is intentionally NOT replayed — and tool results | ||
| as `[Tool Result]\n...` assistant-visible text only when | ||
| `cursorNeedsExternalToolContinuation` says so. Tool CALLS are never | ||
| replayed. The model therefore sees a text transcript, not its own | ||
| structured turn state, and treats each round as a resumed/foreign | ||
| conversation. | ||
| - src/adapters/cursor/checkpoint-store.ts:11-27 — checkpoint continuity | ||
| exists (TTL 15min, 64 entries, 16MB) but `trailing_tool_result` is an | ||
| invalidation reason: src/adapters/cursor/request-builder.ts:430-443 | ||
| (lineageMismatch) returns `trailing_tool_result` when the last message | ||
| is a toolResult and the checkpoint covers the whole message list — | ||
| exactly the state after every tool round-trip. When invalidated, | ||
| request-builder.ts:459-461 falls back to `continuationMode: | ||
| "full-replay"` — the flattened-text path above. Whether every | ||
| tool round actually falls back is the P11 probe question. | ||
|
Comment on lines
+31
to
+39
Contributor
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. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Use the corrected checkpoint root cause in both documents. The existing trailing-tool-result lineage path is not the primary defect. The corrected plan identifies refusal to commit the post-client-tool checkpoint as the root cause.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| - src/server/responses/core.ts:529-537 — conversation identity scoping; | ||
| core.ts:2436-2438 forces `_cursorIsolateConversation` for compaction | ||
| requests. Not the per-round mechanism, but governs when a conversation | ||
| id rotates (S1 amplifier when the client omits thread identity). | ||
|
|
||
| Model contribution (MODEL, secondary): grok-4.6 verbalizes the re-oriented | ||
| state ("Continuing...") instead of silently continuing; C1/C2 control | ||
| probes decide how much is model vs adapter. | ||
|
|
||
| ## S2 — durationMs: 0 on every commandExecution | ||
|
|
||
| Evidence: all commandExecution items in the seed thread report | ||
| `durationMs: 0` even for commands that clearly took time. | ||
|
|
||
| Verdict: CLIENT-leaning UNKNOWN. `durationMs` appears in adapter code only | ||
| in native-exec-desktop.ts / native-exec-tools.ts error paths; the seed | ||
| thread's value is recorded by the Codex app from turn events. Gap: we did | ||
| not capture the SSE event stream the app received, so whether opencodex | ||
| emits started/completed timestamps correctly on the cursor route is | ||
| unverified. Probe P2 (SSE inspection) + P10 (native subagent) carry this. | ||
| Related surface: src/adapters/cursor/native-exec-shell.ts:136 | ||
| (`executionTime`) for cursor-native exec, not the Codex client path. | ||
|
|
||
| ## S3 — "Garbled / lost tool outputs" | ||
|
|
||
| Evidence: model self-reports "previous tool results were garbled", "the | ||
| exec tool only returned a working directory check"; repeated identical | ||
| probes suggest earlier results never reached the model. | ||
|
|
||
| Mechanism (ADAPTER, primary suspects): | ||
|
|
||
| - protobuf-request.ts:248-258 — tool results replayed as flattened | ||
| `[Tool Result]` text with normalization | ||
| (src/adapters/cursor/tool-result-normalize.ts, #1920 empty-result | ||
| error reclassification). Any truncation/normalization loss here is | ||
| invisible to the client but visible to the model. | ||
| - The checkpoint-vs-full-replay fork (S1) means the model's view of tool | ||
| history differs by round; a round served from checkpoint and the next | ||
| from flattened replay do not present tool output identically. | ||
| - P12 (large/multi-line/ANSI payload stress) is the discriminator. | ||
|
|
||
| ## S4 — apply_patch envelope failure on first attempt | ||
|
|
||
| Evidence: seed thread reasoning: "The previous patch failed because its | ||
| first line lacked the required `*** Begin Patch` header." | ||
|
|
||
| Mechanism (ADAPTER by design, known limitation): | ||
|
|
||
| - src/adapters/cursor/tool-definitions.ts:269-312 — Cursor-trained models | ||
| cannot reliably emit Codex freeform patch grammar (#1017), so the | ||
| adapter advertises `edit_file`/`multi_edit` and converts them | ||
| (protobuf-events.ts:896 `translateStructuredEditCall`); freeform | ||
| apply_patch passes through a grammar-only repair | ||
| (protobuf-events.ts:702 `sanitizeCodexApplyPatch`) that strips fences, | ||
| converts git-style diffs, rewrites hunk headers. | ||
| - The seed failure shows the repair did not catch a decorated | ||
| `*** Begin Patch ***` variant on first emission — or the model emitted | ||
| the patch as plain tool-argument text on a path that bypasses | ||
| sanitize. Which envelope variant leaked is UNKNOWN (the raw failing | ||
| payload was not captured in thread items); P6 probes decorated | ||
| envelopes deliberately. | ||
|
|
||
| ## S5 — Shell quoting failure loops (python3 -c nesting) | ||
|
|
||
| Verdict: MODEL primarily (grok-4.6 quoting habits), amplified by S3 (lost | ||
| feedback prevented learning from the first failure). Adapter surface: | ||
| tool-definitions.ts:654-676 already injects guidance about host-shell-safe | ||
| commands; the seed thread shows the model ignoring or never seeing it | ||
| mid-conversation (S1 replay drops? — the system prompt is re-sent per | ||
| request-builder.ts:447, so this leans MODEL). | ||
|
|
||
| ## S6 — Task cost blowup (179s / ~15 rounds for a 3-round task) | ||
|
|
||
| Composite of S1+S3: every lost or re-oriented round doubles the work. Not | ||
| a separate mechanism; recorded for severity weighting in 020. | ||
|
|
||
| ## UNKNOWN register | ||
|
|
||
| | Item | Gap | Carried by | | ||
| |---|---|---| | ||
| | S2 timing emission | SSE event timestamps not captured | P2, P10 | | ||
| | S4 raw failing payload | thread items store outcome, not raw args | P6 | | ||
| | S1 checkpoint hit-rate | no live counter read | P11 | | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Make the probe acceptance contract consistent.
The acceptance text requires P1-P10, but the evidence table omits P10 and the verifier checks only the row count.
devlog/_plan/260826_cursor_responses_gap/000_plan.md#L100-L103: validate the required probe IDs and pass/fail fields, not only the P/C/S row count.devlog/_plan/260826_cursor_responses_gap/010_probe_campaign.md#L18-L40: add the missing P10 result, or revise the matrix and acceptance criterion to the actual probe set.📍 Affects 2 files
devlog/_plan/260826_cursor_responses_gap/000_plan.md#L100-L103(this comment)devlog/_plan/260826_cursor_responses_gap/010_probe_campaign.md#L18-L40🤖 Prompt for AI Agents