Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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.
28 changes: 28 additions & 0 deletions devlog/_plan/260822_senpi_cursor_transfer/210_maxmode.md
Original file line number Diff line number Diff line change
@@ -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.
15 changes: 15 additions & 0 deletions devlog/_plan/260822_senpi_cursor_transfer/220_rotation.md
Original file line number Diff line number Diff line change
@@ -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.
27 changes: 27 additions & 0 deletions devlog/_plan/260822_senpi_cursor_transfer/230_issue2305.md
Original file line number Diff line number Diff line change
@@ -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.
14 changes: 14 additions & 0 deletions devlog/_plan/260822_senpi_cursor_transfer/240_client_version.md
Original file line number Diff line number Diff line change
@@ -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).
13 changes: 13 additions & 0 deletions devlog/_plan/260822_senpi_cursor_transfer/250_billed_usage.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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)
31 changes: 31 additions & 0 deletions devlog/_plan/260822_senpi_cursor_transfer/290_round3_lock.md
Original file line number Diff line number Diff line change
@@ -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.
Loading