Skip to content

[WRONG BRANCH] fix(claude): opt-in peel and unclosed-fence-through-EOF on main - #3

Merged
cursor[bot] merged 1 commit into
mainfrom
cursor/feat-claude-instructions-cache-stabilize-bda6
Sep 10, 2026
Merged

cursor[bot] merged 1 commit into
mainfrom
cursor/feat-claude-instructions-cache-stabilize-bda6

Conversation

@Warexpor

@Warexpor Warexpor commented Sep 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

Port the Claude instructions cache-stabilize review fixes from upstream tip dd6df0b (cursor/feat-claude-instructions-cache-stabilize-915b) onto Warexpor main, without touching SOCKS5 or other fork-only work.

This replaces the older mega-merge stabilize (canonical standalone-line regex, unconditional peel, Desktop hashing stabilized instructions) with the Ingwannu review behavior:

  1. Trailing unfenced harness notices only; no-match returns the original instructions byte-for-byte.
  2. Unclosed ``` / ~~~ openers cover through EOF (not discarded).
  3. Peel is opt-in to Claude Code metadata.user_id; without it, raw system join is kept and Desktop prompt_cache_key hashes raw systemParts.
  4. Translator-level regressions for fenced examples, open-fence-to-EOF, closed-fence-then-footer, gated vs ungated.

Files taken verbatim from dd6df0b:

  • src/claude/inbound-cache-stabilize.ts
  • src/claude/inbound.ts (stabilize wire + claudeCodeHarness gate + prompt_cache_key)
  • tests/claude-integration/claude-inbound-cache-stabilize.test.ts

SOCKS5 (src/lib/socks5-fetch.ts, socks tests, proxy-env) is unchanged.

Verification

  • bun test tests/claude-integration/claude-inbound-cache-stabilize.test.ts tests/claude-integration/claude-inbound.test.ts — 68 pass / 0 fail (23 stabilize + 45 inbound)
  • bun run typecheck — green (bun x tsc --noEmit)
  • bun test tests/server/socks5-fetch.test.ts — 14 pass / 0 fail (SOCKS5 untouched)

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.
Open in Web Open in Cursor 

Port review-grade stabilize from dd6df0b onto Warexpor main:

- Relocation runs only when metadata.user_id identifies Claude Code
- Unmatched fence openers cover through EOF
- No-match returns the original instructions byte-for-byte
- Desktop hashes raw systemParts; it does not peel

SOCKS5 outbound is unchanged.

Co-authored-by: Warexpor <warexpor@gmail.com>
@github-actions

Copy link
Copy Markdown

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Sep 10, 2026
@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

⏳ DRAFT

  • wrong target branch (main); retarget to dev.

What to do

  • Retarget this PR to dev — all contributions go to dev.

Its title has been prefixed with [WRONG BRANCH].
Automatic draft conversion failed (token cannot change draft status). Please convert this pull request to a draft manually. The required enforce-target check will keep failing until every issue above is resolved.

@github-actions github-actions Bot changed the title fix(claude): opt-in peel and unclosed-fence-through-EOF on main [WRONG BRANCH] fix(claude): opt-in peel and unclosed-fence-through-EOF on main Sep 10, 2026
@Warexpor
Warexpor marked this pull request as ready for review September 10, 2026 08:15
@cursor
cursor Bot merged commit 1a459be into main Sep 10, 2026
29 of 30 checks passed
lidge-jun added a commit that referenced this pull request Sep 15, 2026
…d hardened (lidge-jun#4285)

* feat(devin): add experimental Cognition (Devin/Windsurf) adapter

Carries the adapter from lidge-jun#4078 onto current dev and places the test in its
layout domain (tests/providers/devin-adapter.test.ts) with the layout map and
membership fixture updated.

Co-authored-by: Sayo <hi@sayo.wtf>

* fix(devin): harden the cloud-direct adapter before it ships

Four independent reviews of the carried lidge-jun#4078 adapter found one credential-leak
blocker, one abort blocker, and a set of routing and lifecycle defects.

Credentials: RegisterUser and GetUserJwt copied raw upstream bodies into
Error.message, which reaches CLI output, the adapter error event, and /api/logs.
A Connect error can quote the request, and the request holds the sign-in token or
the api_key; redactSecretString does not match a bare JWT. Every auth and chat
error now reports status, an allowlisted Connect code, and a trace id only. The
four credential-bearing POSTs stop following redirects, and the api-server host
is checked against a Cognition allowlist before it reaches a URL - including on
the way into auth.json, so an EU or FedStart tenant host survives a reload
instead of being dropped by the Copilot-only validator.

Routing: the adapter posted to the static registry baseUrl, so an EU or FedStart
account signed in and then sent every RPC to a server it is not provisioned on.
The signed-in account's tenant now decides the host.

Cancellation: after headers arrived nothing observed the caller's signal, so a
client cancel drained until the idle timer fired and then surfaced as
truncated_stream, while the adapter emitted neither done nor error and left the
bridge to synthesize adapter_eof. The body is cancelled on abort and the turn
reports the cancellation.

Also: a natural completion no longer reports stopReason "stop", which was
costing every clean turn its final_answer phase; sampling options reach the
cloud instead of its 128k/0.7 defaults; thinking stays out of replayed assistant
content; usage survives an error; gzip frames are bounded on output as well as
input; dotted model ids normalize to the catalog spelling; the session cache is
bounded; and logout clears the cached user_jwt whose payload carries the api_key.

Co-authored-by: Sayo <hi@sayo.wtf>

* test(devin): assemble the userinfo URL so the privacy scanner does not read it as an email

* feat(devin): pin the client version to the shipped release and accept the real token shape

Evidence from a live free-tier account and the shipped Devin Desktop 3.9.19
bundle. Details in devlog/_plan/260911_devin_two_providers/003_live_evidence.md.

The sign-in token is not a JWT. A real sign-in returns a 47-character
ott$<base64url> one-time value and RegisterUser accepts it, so the JWT-shape
gate would have rejected every real login. The paste parser now recognises one
opaque credential-shaped word rather than a token format.

RegisterUser returned api_server_url https://server.self-serve.windsurf.com for
an ordinary free account, which is what the tenant-routing fix in the previous
commit exists for: the hardcoded server.codeium.com was wrong for this account
before anyone reached an enterprise tenant.

The api-server allowlist gains the staging and beta hosts the shipped bundle
names, and the client version default moves from 2.0.0 - which predates the
Devin rebrand - to the 3.9.19 the desktop client reports, overridable through
OPENCODEX_DEVIN_CLIENT_VERSION.

Co-authored-by: Sayo <hi@sayo.wtf>

* docs(devin): carry the upstream MIT notice on the derived cloud-direct files

A similarity check against rsvedant/opencode-windsurf-auth puts wire.ts at 1.000,
index.ts at 0.988, chat.ts at 0.912, metadata.ts at 0.863, auth.ts at 0.835 and
catalog.ts at 0.753 - same module split, same comments, same field layout. These
files are a derivative of that repository's src/cloud-direct/, which is MIT
licensed, Copyright (c) 2026 Vedant, and the carry arrived with no notice at all.

The full permission notice sits in the module entry point and the other five
files carry a short attribution header pointing at it, which is what MIT asks
for in a distributed source tree.

Co-authored-by: Sayo <hi@sayo.wtf>

* docs(devin): record that the cloud chat path is unverified on a free account

* fix(devin): explain the opaque cloud denial instead of guessing at it

* docs(devin): restore the cloud provider rows and adapter sections on the new dev

devin-cli landed on dev as lidge-jun#4288, so this branch now carries only the cloud provider. The provider rows, the login line, and the adapters reference sections for devin are re-added on top of the current docs, and every locale still leads with the measured result that its chat path is unverified.

* fix(devin): restore the invalid_argument matcher the rebuild dropped

The rebuild re-applied the last commit's documentation by hand and its chat.ts
hunk went with it, so the runtime explanation was back to keying only on
permission_denied while the measured free account returns invalid_argument - the
one trailer it needed to fire for.

Also from the rebuild audit: the conformance test no longer names devin-cli in
guards the RUN_TURN_ONLY_WIRES set already skips, the two layout maps list the
devin test files alphabetically, and structure/adapters/registry.md records why
the cloud devin wire is a direct registry entry alongside devin-cli.

* feat(devin): fix the request encoding that made every chat turn fail

The cloud provider could not complete a single turn on any account. A paid
account settled what it was not: all 229 catalogue models came back enabled and
GetChatMessage failed exactly as it had on the free tier, so entitlement was
never the cause.

Importing the working reference's zero-dependency builder and sending its request
through our own transport returned HTTP 200 and a real stream, which put the
fault in our encoder rather than the wire. Diffing the two encoded messages field
by field left one difference: in CompletionConfiguration, #2 is the output cap
and #3 is the context window, and we had them swapped. A caller asking for 32
output tokens wrote 32 into the context-window field, and Cognition answered with
an opaque invalid_argument. Fields #6 and lidge-jun#11 are not part of the message at all.

A temperature of exactly 0 is refused with that same opaque error. Deterministic
output is the ordinary case for a coding client, so it is clamped to the smallest
accepted value rather than silently replaced with the service default.

Three transport facts had to hold together, which is why testing them one at a
time looked fruitless: the credential is the session token doubled and dash-joined
in an Authorization: Basic header while the body keeps one copy, the request
envelope is uncompressed, and Metadata lidge-jun#31 carries a 732-character fingerprint
whose length the service checks. The metadata identity is its own seven-field
shape rather than the desktop client's telemetry set, the request carries the
verified tag set, and the short-lived user_jwt is now opt-in because the chat path
does not need it.

Verified live on a paid account: six combinations, two hosts by three models, all
returning PONG with a finish reason and usage. A regression test pins the tag map
so the swap cannot return silently.

Co-authored-by: Sayo <hi@sayo.wtf>

* fix(devin): stop the opaque-denial message asserting a retracted explanation

The error string still told the user entitlement was proved and that the request
fields had been ruled out. That was the hypothesis this work retracted: the same
sentence came back for every turn until the CompletionConfiguration tag map was
corrected, and a temperature of exactly 0 still produces it. It now points at the
request first and names the test that pins the accepted field layout, and only
then at the account's model access.

Also from the pre-merge review: the comments claiming the hosted chat path needs
the user_jwt, the stale 128k output-default comment, the promptId that is now
optional because lidge-jun#22 is omitted on a first turn, and an English docs line that
claimed tool calls were verified when the live evidence is chat and usage across
three models.

---------

Co-authored-by: Sayo <hi@sayo.wtf>
Warexpor pushed a commit that referenced this pull request Oct 12, 2026
…ge-jun#6091) (lidge-jun#6172)

* fix(devin): resolve models through catalog family metadata

Parse ClientModelConfig lidge-jun#23 ModelInfo, lidge-jun#30 ModelFamilyMetadata and lidge-jun#31
default flag. A family id with no effort now selects the family's default
member (swe-1-7 -> swe-1-7-medium, not the Max row), an effort moves only
the effort axis to the nearest rung, Fast Mode and 1M Context follow only
explicit requests, and resolution never leaves the family. The suffix
fallback's variant scan matches the collapsed base instead of a string
prefix, so claude-opus-5 no longer lands on claude-opus-5-5-*.

The picker collapses by family, reads ladders from the effort axis, and
advertises the family default as defaultReasoningEffort; swe-1-6-fast
stays its own row. swe-1-6 is marked text-only (live: it drops images
silently) so the vision fallback applies.

Uncapped turns send the selected row's catalog maxOutputTokens instead of
8192. CompletionConfiguration #3 is max_newlines, now a fixed value; the
input-ceiling plumbing that fed it a context window is removed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 09b9e6d)

* fix(devin): round a missing effort rung up, never down

An effort a family lacks now selects the lowest rung at or above it, then
the highest below. Nearest-rung sent `high` on SWE-1.7 (Medium, Max) to
Medium; it now selects the Max row. A disabled default rounds up the same
way and falls back down only when nothing above it is enabled.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit ed6449e)

* fix(devin): keep a named disabled row and never lower effort for a toggle

A disabled exact uid asked for with an effort that still selects it (swe-2-max
at max) is now sent as named, so the preflight reports that row's refusal
instead of quietly serving swe-2-high. Family selection now ranks "effort not
lowered" ahead of the non-effort axes: a Fast anchor asked for at a rung the
Fast rows lack falls back to the regular row at or above that rung, and an
unranked member counts as lower. none is exempt, so Thinking-off still wins.

Co-authored-by: Sayo <hi@sayo.wtf>

* fix(devin): advertise minimal family effort

Co-authored-by: Sayo <hi@sayo.wtf>

* fix(devin): publish effective family default effort

Co-authored-by: Sayo <hi@sayo.wtf>

---------

Co-authored-by: Sayo <hi@sayo.wtf>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants