From d6b8f8b5ded2436875db1efd42d2aa7b9c0d4c51 Mon Sep 17 00:00:00 2001 From: bitkyc08-arch Date: Sat, 22 Aug 2026 13:30:17 +0900 Subject: [PATCH] devlog: round-3 live-probe evidence and lock (docs-only) --- .../200_round3_probe_plan.md | 58 +++++++++++++++++++ .../210_maxmode.md | 28 +++++++++ .../220_rotation.md | 15 +++++ .../230_issue2305.md | 27 +++++++++ .../240_client_version.md | 14 +++++ .../250_billed_usage.md | 13 +++++ .../260_re_classification_refinement.md | 31 ++++++++++ .../290_round3_lock.md | 31 ++++++++++ 8 files changed, 217 insertions(+) create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/200_round3_probe_plan.md create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/210_maxmode.md create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/220_rotation.md create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/230_issue2305.md create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/240_client_version.md create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/250_billed_usage.md create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/260_re_classification_refinement.md create mode 100644 devlog/_plan/260822_senpi_cursor_transfer/290_round3_lock.md diff --git a/devlog/_plan/260822_senpi_cursor_transfer/200_round3_probe_plan.md b/devlog/_plan/260822_senpi_cursor_transfer/200_round3_probe_plan.md new file mode 100644 index 0000000000..4b896ecf6c --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/200_round3_probe_plan.md @@ -0,0 +1,58 @@ +# 200 — Round-3 live-probe plan + +Round 2 (100-190) landed T04/T07/shutdown. The 190 lock deferred five rows +for lack of live evidence (T06 maxMode, T02 rotation, #2305 external +continuation, client version watch, T09 cacheRead clamp); T08/T10 stay +deferred for non-live reasons and #2334 stays NEEDS_HUMAN by design. A live +Cursor account now exists on the probe host (macmini, ocx preview), so this +cycle buys the evidence. + +## Probes + +1. **P-1 maxMode (T06).** Dump GetUsableModels with full ModelDetails — + which models report maxMode=true, and what contextTokenLimit pairs with + it. Compare a Run with RequestedModel.maxMode=true vs false on one + maxMode-capable model: does the server accept it, and does the reported + context window / usage change? Wire flag only lands if this shows a real + user-visible gain. +2. **P-2 rotation (T02 / #1527 suspect).** Drive a conversation toward the + bare 0-token resource_exhausted shape (large-context turns on a pinned + conversationId). If the server pins the rejection to the conversationId + (fresh id succeeds with identical payload), T02 rotation is justified; + implement bounded rotation + checkpoint rekey. If not reproducible within + quota bounds, record and keep deferred. +3. **P-3 issue #2305.** Reproduce the client-tool continuation returning + tool-call-like assistant text to Pi: drive a client-tool turn through the + external continuation path and capture what text frames come back. + Root-cause lives in rootPromptMessages / userMessageAction continuation + (the a69d291fb fix covered native Auto; #2305 is the external path). +4. **P-4 client version.** GetUsableModels + one Run with the current pinned + cli-2026.07.08-0c04a8a vs a newer senpi-observed string + (cli-2026.07.23-e383d2b): any catalog or behavior delta? Bump only if + probe shows the new string is accepted and changes nothing adverse. +5. **P-5 billed usage / cacheRead (T09).** Capture the billed turnEnded + usage int64s (inputTokens / outputTokens / cacheRead*) from the SAME live + Runs P-1 and P-4 already make (no extra quota): decode and record whether + cacheRead exceeds 3x input the way senpi's clamp assumes, and whether our + protobuf-events usage mapping already reports these fields sanely. Verdict + IMPLEMENT (clamp justified) / NOOP (values sane, clamp unnecessary) / + BLOCKED (fields absent on this plan tier). + +## Probe hygiene (binding, extends doc 100 boundary) + +- All transcripts REDACTED before entering devlog: no bearer tokens, no + account ids, no email, no checksum headers. Raw dumps stay in .tmp/ on the + probe host and are deleted after the docs lock. +- Quota respect: P-2 large-context attempts are capped (<= 5 runs); if the + account rate-limits, stop and record BLOCKED for that probe. +- No Safe Storage access, no client patching, no endpoints beyond what the + adapter already ships (Run, GetUsableModels, RunSSE fallback). + +## Outputs + +- 210_maxmode.md, 220_rotation.md, 230_issue2305.md, 240_client_version.md — + each with verdict IMPLEMENT / NOOP / BLOCKED / NEEDS_HUMAN and, for + IMPLEMENT, diff-level shape. +- 250_billed_usage.md — P-5 verdict for T09 (same contract). +- 290_round3_lock.md — ranked implementation order + updated senpi + superiority verdict. diff --git a/devlog/_plan/260822_senpi_cursor_transfer/210_maxmode.md b/devlog/_plan/260822_senpi_cursor_transfer/210_maxmode.md new file mode 100644 index 0000000000..fce0d1cfdd --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/210_maxmode.md @@ -0,0 +1,28 @@ +# 210 — P-1 maxMode probe (T06) + +## Evidence (macmini live, 2026-08-22, redacted) + +- GetUsableModels decoded: 204 entries; ModelDetails keys = + modelId, displayModelId, displayName, displayNameShort, aliases, maxMode. +- maxMode=true on exactly 28 ids — ALL of them opus "-fast" variants + (claude-opus-5-*-fast, claude-opus-4-8-*-fast, claude-opus-4-7-*-fast). + No contextTokenLimit field is present in this response shape. +- Run A/B on claude-opus-4-7-low-fast, tiny prompt: + - RequestedModel.maxMode=false -> bare Connect resource_exhausted. + - RequestedModel.maxMode=true -> same bare resource_exhausted. + The server ACCEPTED the flag both ways (no invalid_argument); the model is + plan-gated for this account regardless. + +## Verdict: BLOCKED (plan tier) + +maxMode only decorates -fast (paid burst) variants, and this account cannot +run them at all, so no user-visible gain is provable here. Wire flag stays +hardcoded false. Re-probe requires an account with -fast entitlement +(NEEDS_HUMAN to provision). + +## Side finding (feeds 260) + +A TINY prompt on a plan-gated model returns the same bare 0-token +resource_exhausted shape that #2320 (T01) now classifies as CONTEXT OVERFLOW. +Live proof that bare RE != always overflow: entitlement rejections share the +shape. See 260_re_classification_refinement.md. diff --git a/devlog/_plan/260822_senpi_cursor_transfer/220_rotation.md b/devlog/_plan/260822_senpi_cursor_transfer/220_rotation.md new file mode 100644 index 0000000000..d6f573bf34 --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/220_rotation.md @@ -0,0 +1,15 @@ +# 220 — P-2 rotation probe (T02 / #1527 suspect) + +## Evidence + +4 consecutive ~101K-token turns on one pinned conversationId +(composer-2.5-fast) all completed (OK1..OK4, usage.totalTokens ~101,111-147). +No 0-token resource_exhausted, no conversation poisoning within the capped +attempt budget (probe cap <= 5 runs, quota hygiene doc 200). + +## Verdict: NOT REPRODUCED — T02 stays deferred + +The senpi #998 pathology (server pinning a rejection to a conversationId) did +not manifest at this size on this plan. #1527 remains open without a local +reproduction; rotation-with-persistence stays deferred until a live +reproduction exists. No implementation this round. diff --git a/devlog/_plan/260822_senpi_cursor_transfer/230_issue2305.md b/devlog/_plan/260822_senpi_cursor_transfer/230_issue2305.md new file mode 100644 index 0000000000..62f0aadce3 --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/230_issue2305.md @@ -0,0 +1,27 @@ +# 230 — P-3 issue #2305: display-alias leak in assistant text + +## Root cause (code-grounded, ox-alpha lane + main-agent verification) + +OpenCodex has NO text-mode tool-call parser; assistant text passes through +verbatim: protobuf-events.ts textDelta (~:1245) -> message-mapper.ts -> +bridge.ts text_delta -> chat-completions client. Pi parses +"[TOOL_CALL]name[ARGS]{...}" text itself, so when a Cursor model emits the +textual pseudo-frame with the DISPLAY name (mcp_opencodex-responses_grep), +Pi sees an undeclared tool and the turn dies. Real tool-call FRAMES are +already normalized via mcpWireNameFromArgs -> normalizeCursorWireName +(protobuf-events.ts:278-281); text deltas bypass that. + +## Verdict: IMPLEMENT + +## Diff shape + +- protobuf-events.ts textDelta case: scrub via marker-scoped regex + \[TOOL_CALL\](mcp_opencodex-responses_[^\[\]]+)\[ARGS\] -> + normalizeCursorWireName inside markers only. Prose mentions stay untouched; + scope-guarded to the exact OCX_RESPONSES_TOOL_PROVIDER prefix. +- Streaming caveat: a marker can straddle two deltas. Start WITHOUT tail + buffering; add only if live traces show split markers (recorded risk). +- Tests: tests/cursor-protobuf-events.test.ts — marker normalized, prose + untouched, real frames unaffected. +- Precedent: a69d291fb (request-side [Tool Result] envelope strip) — same + failure family, response-side analogue. diff --git a/devlog/_plan/260822_senpi_cursor_transfer/240_client_version.md b/devlog/_plan/260822_senpi_cursor_transfer/240_client_version.md new file mode 100644 index 0000000000..45b304c659 --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/240_client_version.md @@ -0,0 +1,14 @@ +# 240 — P-4 client version probe + +## Evidence + +GetUsableModels accepted all three version strings with byte-identical +catalogs (204 entries): cli-2026.07.08-0c04a8a (ours), cli-2026.07.23-e383d2b +(senpi), cli-2026.02.13-41ac335 (our discovery pin). Live Run on the 07.08 +pin works (P-5 turns completed). + +## Verdict: NOOP (no forced bump) + +No behavioral delta proven. Optional freshness bump to 07.23 is safe by this +probe but buys nothing measurable; keep the pin, keep the drift watch from +190 (api2direct reports). diff --git a/devlog/_plan/260822_senpi_cursor_transfer/250_billed_usage.md b/devlog/_plan/260822_senpi_cursor_transfer/250_billed_usage.md new file mode 100644 index 0000000000..06a59f8c8e --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/250_billed_usage.md @@ -0,0 +1,13 @@ +# 250 — P-5 billed usage / cacheRead (T09) + +## Evidence + +Two live proxy turns (composer-2.5-fast) report sane Responses usage: +input_tokens 11085/11162, output 11/10, cached_tokens 0, no inflation, no +cacheRead > 3x input pathology. Transport-level runs report estimated usage +consistently (~101K totals on the big turns, matching payload size). + +## Verdict: NOOP for the clamp + +No evidence of senpi's billed-int64 pathology on this plan tier. T09 clamp +stays unimplemented; revisit only if live usage reports regress. diff --git a/devlog/_plan/260822_senpi_cursor_transfer/260_re_classification_refinement.md b/devlog/_plan/260822_senpi_cursor_transfer/260_re_classification_refinement.md new file mode 100644 index 0000000000..8933f31450 --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/260_re_classification_refinement.md @@ -0,0 +1,31 @@ +# 260 — bare resource_exhausted refinement (T01 follow-up, live-evidenced) + +## Problem + +#2320 classifies a bare 0-token resource_exhausted (no quota cue, no size +phrase) as CONTEXT OVERFLOW -> 400-class so Codex compacts. Live probe 210 +found a counterexample: a ~20-token prompt on a plan-gated model +(claude-opus-4-7-low-fast) returns the SAME bare shape. Misclassifying that +as overflow makes Codex compact a 20-token turn — wrong remedy, confusing UX, +and the retry can never succeed. + +## Design + +Classification needs a size prior: only classify bare RE as overflow when the +REQUEST was plausibly large relative to the model's context window; small +requests keep the 429-class quota/entitlement mapping. The adapter already +computes an input-token estimate (prepareCursorRunRequest +estimateInputTokens; estimateTokens lib). Shape: + +- cursor-errors.ts: classifyCursorError gains an optional context + { estimatedInputTokens?, contextWindow? }. +- live-transport/adapter passes the estimate it already has for the turn. +- Rule: bare RE + estimate >= OVERFLOW_MIN_FRACTION (0.5) * contextWindow -> + overflow (current behavior); otherwise -> existing rate-limit mapping. + Unknown estimate/window -> keep current overflow mapping (fail toward + compaction, today's behavior) so the refinement only ever REDUCES + false overflows it can prove. +- Tests: tests/cursor-errors.test.ts — tiny-estimate bare RE -> 429 class; + large-estimate -> overflow; no-estimate -> overflow (unchanged). + +## Verdict: IMPLEMENT (beyond-senpi refinement; senpi T01 shares this bug) diff --git a/devlog/_plan/260822_senpi_cursor_transfer/290_round3_lock.md b/devlog/_plan/260822_senpi_cursor_transfer/290_round3_lock.md new file mode 100644 index 0000000000..48f032f2e5 --- /dev/null +++ b/devlog/_plan/260822_senpi_cursor_transfer/290_round3_lock.md @@ -0,0 +1,31 @@ +# 290 — Round-3 lock + +Probes executed on macmini (live account, redacted transcripts in 210-250; +raw dumps deleted from probe host after lock per 200 hygiene). + +## Implementation order (this loop) + +1. **230 — #2305 text-marker normalization** (IMPLEMENT; clear defect, open + issue, code-grounded fix point). +2. **260 — bare-RE size prior** (IMPLEMENT; live-evidenced false-overflow + class; a refinement senpi's own T01 lacks). + +## Closed by probe (no code) + +- 210 maxMode: BLOCKED (plan tier) — flag accepted but -fast entitlement + absent; NEEDS_HUMAN to provision a -fast-capable account for re-probe. +- 220 rotation: NOT REPRODUCED at 4x101K; T02 stays deferred. +- 240 client version: NOOP — three version strings byte-identical catalogs. +- 250 billed usage: NOOP — no cacheRead pathology on this plan. + +## Updated senpi verdict + +With 230+260 landed, remaining senpi-ahead rows shrink to: rotation +persistence (unreproducible here), maxMode (plan-gated for both projects +without entitlement), agent-loop-level stop/exec ownership (out of adapter +scope; #2305's actual defect is ours to fix and is fixed). OpenCodex keeps +its unique-side advantages (interactionQuery, HTTP/1 fallback, SelectedImage +vision, bounded memory, T04 watchdog with senpi-matching thresholds, typed +exec errors, EOF fail-closed tests). Verdict: at parity or ahead on every +row that is provable on this plan tier; the two rows senpi still leads +require entitlement or a reproduction neither project can show today.