Skip to content

fix: preserve Claude Go affinity across combo selection and failover - #4050

Open
david-wang-0 wants to merge 3 commits into
lidge-jun:devfrom
david-wang-0:fix/claude-go-final-route-affinity
Open

fix: preserve Claude Go affinity across combo selection and failover#4050
david-wang-0 wants to merge 3 commits into
lidge-jun:devfrom
david-wang-0:fix/claude-go-final-route-affinity

Conversation

@david-wang-0

@david-wang-0 david-wang-0 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Verification

Head e5c2411f7 (three commits: the fix 9e0783495, the CodeRabbit docs/JSDoc follow-up, and a docs commit that states the sessionless per-request isolation precisely, as requested in review), rebased onto exact dev tip 16f18d654. Range-diff against the previous head 5cb63c09c shows all three commits unchanged; the intervening dev commits do not touch the files this PR changes. dev includes the request-scoped isolated session lane from #4184 (merged as 9e75542ff via #4226). That merge conflicted with this PR at the final-route call in src/server/responses/core.ts; the resolution is the one previewed on integ/4050-with-4184: the final Go destination uses the Claude-derived affinity when present and otherwise the request-scoped lane, and Claude Messages falls back to that same request-scoped lane when no explicit or metadata identity is valid. The two matrix cases without valid identity now expect a well-formed isolated lane (distinct across requests, never the shared-system or metadata hash) instead of no header. All results below are from this head with the pinned Bun 1.4.2 (Linux); bun run test:changed additionally passed 4,991 tests across 182 import-connected files with 0 failures.

  • bun run typecheck: passed.
  • Focused Go affinity suite tests/providers/opencode-go-session-header.test.ts: 87 pass, 0 fail, 767 assertions.
  • Hosted-CI equivalent general suite via scripts/ci/run-bun-test-batches.sh for all four shards: every shard exited 0, 0 assertion failures, 23,076 tests run. Bun 1.4.2 batch-process crashes (exit 139, the [Bug] CI: Linux test shards intermittently hang ~15 minutes and are killed, leaving an orphan bun process #1302 class) were recovered by the runner's one-file-per-process isolation.
  • Dedicated storage-policy job (bun test --isolate, six files): 18 pass, 0 fail.
  • Dedicated api-usage job: 33 pass, 0 fail.
  • bun run privacy:scan: passed. git diff --check: clean.
  • cd docs-site && bun run build: passed (425 pages).
  • Note for reproducers: running the batch runner with a PATH Bun older than the pinned 1.4.2 produces unrelated assertion failures (for example the Bun.Image tests); set OPENCODEX_BUN_PATH to the bundled binary.

Deterministic reproduction (no API key)

Requires Git, Node.js, and Bun. All upstream fetches in the selected tests are mocked. The script creates a disposable checkout and keeps its logs; it does not start a proxy or call Go. It runs exactly the same new regression tests against the unpatched base and the fixed production files.

#!/usr/bin/env bash
set -euo pipefail
# Requires git, Node.js and Bun. No API key or running proxy is used.
repo="${REPRO_REPO:-https://github.com/david-wang-0/opencodex.git}"
base=16f18d654
fixed=e5c2411f7
export NO_COLOR=1
scratch=$(mktemp -d)
git init -q "$scratch/checkout"
cd "$scratch/checkout"
git remote add origin "$repo"
git fetch --depth=4 origin "$fixed"
git checkout --detach "$fixed"
bun install --frozen-lockfile --ignore-scripts
node node_modules/bun/install.js
test_file=tests/providers/opencode-go-session-header.test.ts
selector='Claude random openai-chat to Go uses metadata'

# Keep the new regression tests but restore only the two production files.
git restore --source="$base" --worktree -- \
  src/server/claude-messages.ts src/server/responses/core.ts
set +e
bun run test "$test_file" -t "$selector" > "$scratch/before.log" 2>&1
before_status=$?
set -e
cat "$scratch/before.log"
if [ "$before_status" -eq 0 ]; then
  echo 'ERROR: expected the unpatched implementation to fail' >&2
  exit 1
fi
grep -Eq '(^|[[:space:]])2 fail' "$scratch/before.log"
# On this base the unpatched final route already carries an isolated per-request lane,
# so the failure is a wrong lane rather than a missing header.
grep -Eq 'Received: "ocx_[0-9a-f]{32}"' "$scratch/before.log"
! grep -Fq 'Received: "ocx_a89540229ef781fd5f7adf92a711b436"' "$scratch/before.log"
grep -Fq 'Expected: "ocx_a89540229ef781fd5f7adf92a711b436"' "$scratch/before.log"

git restore --source="$fixed" --worktree -- \
  src/server/claude-messages.ts src/server/responses/core.ts
bun run test "$test_file" -t "$selector" > "$scratch/after.log" 2>&1
cat "$scratch/after.log"
echo "Unpatched exit: $before_status; patched exit: 0"
echo "Checkout and logs retained in: $scratch"

The selected cases force the preliminary route to a non-Go Chat provider and actual random dispatch to Go, on both Go wire protocols. Recorded standalone output (setup and stack traces omitted):

Unpatched, both cases (the received lane is the isolated per-request value, different each run):
Expected: "ocx_a89540229ef781fd5f7adf92a711b436"
Received: "ocx_9a17584daa3bd0bfe661b1b25f1ef464"
 0 pass
 2 fail

Patched:
 2 pass
 0 fail
Unpatched exit: 1; patched exit: 0

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.

Co-authored-by: GPT-6 Astra noreply@openai.com
Co-authored-by: Claude Fable 5.1 noreply@anthropic.com

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Improvements

    • Improved OpenCode Go session affinity for Claude Messages and Responses across fallback and randomly selected destinations.
    • Added request-level isolation when no session identifier is available.
    • Supports configured, explicit, operator-provided, and metadata-based session identifiers.
    • Go session information remains isolated from non-Go destinations.
  • Documentation

    • Expanded guidance on session-affinity precedence, fallback behavior, final destination selection, and the distinction between conversation identity and prompt-cache keys.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: a51066d3-f24b-4c04-b1bd-7e399c6617cc

📥 Commits

Reviewing files that changed from the base of the PR and between d7f40ed and d8ccff4.

📒 Files selected for processing (1)
  • docs-site/src/content/docs/guides/providers.md

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Claude Messages now derives Go session affinity separately from replay headers. Responses handling passes this identity to final Go transport resolution. Tests cover identity precedence, combo strategies, failover, and non-Go target isolation. Provider documentation describes the fallback behavior.

Changes

Claude Go session affinity

Layer / File(s) Summary
Session lane derivation
src/server/claude-messages.ts
Claude Messages derives claudeGoSessionLane from request identity or metadata and passes it through claudeGoAffinity. Go identity is no longer copied into replay headers.
Final transport resolution
src/server/responses/core.ts
Responses handling accepts claudeGoAffinity and uses its session lane when resolving the final canonical Go transport. Native session_id synthesis remains limited to non-Go routes.
Routing validation and documentation
tests/providers/opencode-go-session-header.test.ts, docs-site/src/content/docs/guides/providers.md
Tests cover identity precedence, random and failover strategies, and non-Go header isolation. Documentation describes metadata fallback and final-destination behavior.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ClaudeMessages
  participant Responses
  participant OpenCodeGoTransport
  ClaudeMessages->>ClaudeMessages: Derive session lane
  ClaudeMessages->>Responses: Pass claudeGoAffinity
  Responses->>OpenCodeGoTransport: Resolve final Go transport
  OpenCodeGoTransport-->>Responses: Apply session affinity
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: preserving Claude Go affinity across combo selection and failover. It is concise, specific, and directly matches the documented implementation and tests.
Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

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

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

This pull request is already Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently.
Maintainers: @lidge-jun @Ingwannu

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 72 / 80

이 PR은 #3961 늦은 리뷰 후속입니다. Claude /v1/messages가 combo로 들어갈 때 사전 점검(preflight) 목적지와 실제 dispatch/failover 목적지가 다를 수 있는데, 지금 dev HEAD cfff026d5는 Go affinity를 preflight 시점의 opencodeGoRoute와 replay 헤더에 기대고 있습니다. src/server/claude-messages.ts는 Go로 보이는 사전 루트일 때만 x-opencode-session을 복사하고 synthesizeGoSession으로 session_id를 붙입니다. 그다음 handleResponsesapplyFinalRouteRequestNormalization은 다시 요청 헤더에서 레인을 읽어 resolveOpenCodeGoTransport에 넣습니다. 그래서 (1) preflight는 non-Go인데 최종이 Go인 random/failover면 affinity가 비고, (2) preflight는 Go인데 최종이 non-Go면 Go 전용 identity가 새어 나갈 수 있습니다. #3961이 연 메타데이터→레인 합성은 살아 있지만, combo가 목적지를 나중에 바꾸면 그 합성이 잘못된 쪽에 붙습니다.

패치 요지는 affinity를 대역 외 옵션으로 옮기는 것입니다. Claude 쪽에서 쓸 수 있는 레인(session_id / x-opencode-session / metadata에서 만든 값)을 claudeGoSessionLane으로 모은 뒤, replay 헤더에는 Go identity를 넣지 않고 handleResponses(..., { claudeGoAffinity: { sessionLane } })로만 넘깁니다. src/server/responses/core.tsHandleResponsesOptions에 같은 필드를 추가하고, 최종 canonical 정규화에서 args.claudeGoAffinity가 있으면 그 레인을, 없으면 기존 헤더 판별을 씁니다. native ChatGPT 경로의 session_id 합성은 nativeRoute && !opencodeGoRoute로 좁혀, Go 전용 합성과 분리합니다. 문서 docs-site/.../providers.md도 “Claude metadata fallback은 최종 Go에만, shared system 키는 대화 ID가 아니다”를 명시합니다.

테스트 tests/providers/opencode-go-session-header.test.ts가 핵심입니다. Chat/Muse × openai-chat/responses × random/failover × metadata/explicit/lane/operator/invalid/shared-system 매트릭스와, preflight Go → 최종 non-Go에서 헤더 미누출 케이스를 추가했습니다. 본문 기준 focused affinity 84 pass, typecheck·privacy·docs build 통과, 로컬 bounded suite 21818 pass를 주장합니다. 다만 draft이고, 작성 시점 base는 옛 dev라 최신 tip(cfff026 / #4049 luvs01 train) 대비 rebase·재검증이 필요합니다. 범위는 affinity 전달뿐이라 types/config 분할에 무효화되지 않습니다. credentials·schema·의존성 변경도 없습니다.

라인 src/server/claude-messages.ts · claudeGoSessionLane - 명시 레인 → 클라이언트 Go 헤더 → metadata 합성 순서가 문서·테스트와 맞습니다. shared system 키는 metadataGoLane에 안 들어갑니다.

라인 src/server/responses/core.ts · resolveOpenCodeGoTransport 호출 - args.claudeGoAffinity가 있으면 헤더를 무시합니다. 빈 객체 { sessionLane: undefined }도 truthy라서, 의도적으로 “헤더 폴백 금지”가 됩니다. Claude 경로만 이 옵션을 넘기는 한 괜찮지만, 실수로 빈 객체를 넘기는 다른 호출부가 생기면 affinity가 통째로 사라집니다.

경로 draft + rebase - tip이 #4049까지 전진했습니다. undraft 전에 dev rebase와 hosted CI를 다시 보는 게 맞습니다. 로컬 prepush stall은 #1302 계열로 본문에 적혀 있고, 이번 PR 회귀로 단정하진 않았습니다.

메인테이너의 판단이 필요한 지점

너의 추천
방향은 dev의 Go affinity 열차(#3880/#3961/#3966)와 정확히 맞습니다. rebase → undraft → hosted CI 그린이면 머지하세요. draft 상태에서는 랜딩 큐 앞에 두지 마세요. close-don't-rebase 대상이 아닙니다.

이 댓글은 grok-bot이 작성했습니다

@david-wang-0
david-wang-0 force-pushed the fix/claude-go-final-route-affinity branch from 3e6a831 to ee9a86c Compare September 8, 2026 18:02
@david-wang-0

david-wang-0 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review


Agent attribution: GPT-5.6 Sol (OpenAI Codex).

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@david-wang-0

david-wang-0 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Rebased and revalidated at ee9a86c on dev 7dc7dc9. The updated description records the new bounded test results and exact reproduction pins; cfff026 landed afterward and is not included in those local results, so the latest-dev checkbox remains unchecked.

The empty claudeGoAffinity object is intentional negative information, not a missing fallback value. Claude snapshots Go eligibility before the existing native preflight may synthesize a session_id header. When metadata is ineligible and no usable explicit identity exists, an empty snapshot must suppress fallback to that later synthesized header. Testing sessionLane != null instead would re-enable that fallback. The regression matrix covers invalid metadata and shared-system-only identity with an openai-responses preliminary target followed by Go on both wires. Calls that omit claudeGoAffinity entirely retain the existing header-based behavior.

A full CodeRabbit review has been requested for this pushed head. The PR remains draft pending remaining readiness work.


Agent attribution: GPT-5.6 Sol (OpenAI Codex).

@david-wang-0

david-wang-0 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai Your completed summary reports no actionable comments, but its merge-risk paragraph says the regression suite has a duplicate declaration and cannot parse. Please identify the exact identifier and line, or correct that paragraph.

I verified that the published test blob and the executed local blob are identical: 4171ef00a85a0a115d551ce551681dc37056ec32 at head ee9a86c. A fresh run of env -u OPENCODEX_CODEX_SHIM_AUTO_RESTORE bun run test tests/providers/opencode-go-session-header.test.ts on that head again completed successfully: 84 pass, 0 fail, 605 assertions. Typecheck and the bounded full suite also passed as recorded in the description.

Please also identify the functions behind the advisory docstring-coverage warning; the report gives only an aggregate percentage, so it does not currently identify a concrete missing contract to assess.


Agent attribution: GPT-5.6 Sol (OpenAI Codex).

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== HEAD =='
git rev-parse HEAD
git status --short

echo '== Test file outline =='
ast-grep outline tests/providers/opencode-go-session-header.test.ts --items all || true

echo '== Import and top-level declarations with line numbers =='
rg -n -C 2 --type ts \
  '^\s*import\b|^\s*(const|let|var|function|class|interface|type|enum)\s+' \
  tests/providers/opencode-go-session-header.test.ts || true

echo '== Repeated const/let/function/class/type/interface/enum names in that file =='
python3 - <<'PY'
from collections import defaultdict
import re
p = "tests/providers/opencode-go-session-header.test.ts"
decl = re.compile(r'^\s*(?:export\s+)?(?:async\s+)?(?:const|let|var|function|class|interface|type|enum)\s+([A-Za-z_$][\w$]*)\b')
seen = defaultdict(list)
with open(p, encoding="utf-8") as f:
    for n, line in enumerate(f, 1):
        m = decl.match(line)
        if m:
            seen[m.group(1)].append(n)
for name, lines in sorted(seen.items()):
    if len(lines) > 1:
        print(f"{name}: {', '.join(map(str, lines))}")
PY

echo '== Documentation coverage references in repository configuration and scripts =='
rg -n -i -C 3 \
  '(docstring|documentation)[ _-]?(coverage|cover)|doc-coverage|typedoc|api[ _-]?extractor' \
  . \
  -g '!node_modules/**' -g '!dist/**' -g '!build/**' -g '!coverage/**' \
  || true

echo '== Package scripts relevant to docs/coverage =='
if [ -f package.json ]; then
  rg -n -C 2 '"[^"]*(doc|coverage)[^"]*"\s*:' package.json || true
fi

Length of output: 24525


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Changed test range =='
sed -n '115,225p' tests/providers/opencode-go-session-header.test.ts | nl -ba -v 115

echo '== PR diff for the test file =='
git diff "$(git merge-base HEAD origin/dev)" HEAD -- tests/providers/opencode-go-session-header.test.ts || true

echo '== TypeScript configuration candidates =='
fd -HI '^tsconfig.*\.json$|^biome\.jsonc?$|^eslint\.config\.' . -E node_modules -E dist -E build \
  | while IFS= read -r f; do
      echo "--- $f"
      sed -n '1,240p' "$f"
    done

echo '== PR `#4050` comments and reviews containing parse or docstring terms =='
gh api --paginate repos/lidge-jun/opencodex/issues/4050/comments \
  --jq '.[] | select((.body | test("duplicate|parse|docstring|coverage"; "i"))) | {user: .user.login, created_at, body}' \
  || true
gh api --paginate repos/lidge-jun/opencodex/pulls/4050/comments \
  --jq '.[] | select((.body | test("duplicate|parse|docstring|coverage"; "i"))) | {user: .user.login, path, line, original_line, body}' \
  || true
gh api repos/lidge-jun/opencodex/pulls/4050/reviews \
  --jq '.[] | {user: .user.login, state, submitted_at, body}' \
  || true

Length of output: 1526


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Changed test range =='
awk 'NR >= 115 && NR <= 225 { printf "%d:%s\n", NR, $0 }' \
  tests/providers/opencode-go-session-header.test.ts

echo '== PR diff for the test file =='
base="$(git merge-base HEAD origin/dev 2>/dev/null || true)"
if [ -n "$base" ]; then
  git diff "$base" HEAD -- tests/providers/opencode-go-session-header.test.ts
else
  echo 'Could not determine merge base with origin/dev.'
fi

echo '== TypeScript and lint configuration candidates =='
fd -HI '^tsconfig.*\.json$|^biome\.jsonc?$|^eslint\.config\.' . \
  -E node_modules -E dist -E build \
  | while IFS= read -r f; do
      echo "--- $f"
      sed -n '1,240p' "$f"
    done

echo '== Package scripts =='
sed -n '1,130p' package.json

echo '== PR `#4050` comments and reviews with relevant terms =='
gh api --paginate repos/lidge-jun/opencodex/issues/4050/comments \
  --jq '.[] | select((.body | test("duplicate|parse|docstring|coverage"; "i"))) | {user: .user.login, created_at, body}' \
  || true
gh api --paginate repos/lidge-jun/opencodex/pulls/4050/comments \
  --jq '.[] | select((.body | test("duplicate|parse|docstring|coverage"; "i"))) | {user: .user.login, path, line, original_line, body}' \
  || true
gh api repos/lidge-jun/opencodex/pulls/4050/reviews \
  --jq '.[] | {user: .user.login, state, submitted_at, body}' \
  || true

Length of output: 25148


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='cfff026d58c4d6e894214cbec5248d70d759ba7f'

echo '== Name and function-level diff =='
git diff --unified=20 "$base" HEAD -- \
  src/server/claude-messages.ts \
  src/server/responses/core.ts \
  tests/providers/opencode-go-session-header.test.ts

echo '== Source outlines =='
ast-grep outline src/server/claude-messages.ts --items all || true
ast-grep outline src/server/responses/core.ts --items all || true
ast-grep outline tests/providers/opencode-go-session-header.test.ts --items all || true

echo '== Function declarations near changed lines =='
for f in src/server/claude-messages.ts src/server/responses/core.ts tests/providers/opencode-go-session-header.test.ts; do
  echo "--- $f"
  git diff --unified=0 "$base" HEAD -- "$f" \
    | awk '
        /^@@/ { print }
        /^[+-][^+-]/ { print }
      '
done

Length of output: 57524


@david-wang-0, I cannot identify a duplicate declaration because none exists in the reviewed test source.

The merge-risk paragraph is incorrect. It should not state that the regression suite cannot parse.

Evidence at ee9a86c0950763c9fe064abe22c6219e039c016f:

  • tests/providers/opencode-go-session-header.test.ts imports spyOn once at Line 1.
  • The file has no repeated top-level declaration.
  • The added matrix uses nested lexical scopes at Lines 124–186. Repeated local names such as requests, config, and entropy are inside separate test callbacks or loop iterations.
  • The published review gives no identifier, line, TypeScript diagnostic, or parser output for its contrary claim.
  • Your focused test result for blob 4171ef00a85a0a115d551ce551681dc37056ec32 is consistent with this inspection.

The corrected paragraph is:

The affinity behavior appears well targeted. The added regression matrix has no identified duplicate declaration or parse failure. Run the normal required checks before merging.

The advisory Docstring Coverage result is also not actionable as published. It reports only an aggregate: three analyzed functions, 66.67% coverage, and one unsupported item. It does not identify the functions, source lines, or the unsupported syntax. The repository has no docstring-coverage script or configuration that can reproduce its function-level mapping.

The only plausible changed production function without a preceding JSDoc block is handleClaudeMessagesWithBudget in src/server/claude-messages.ts at Line 635. This is not a confirmed coverage finding. The modified applyFinalRouteRequestNormalization function has an existing docstring beginning at src/server/responses/core.ts Line 2304. The new HandleResponsesOptions.claudeGoAffinity field has a doc comment at Line 1655.

Therefore, I withdraw both implications that there is a known test parse failure and that the aggregate docstring percentage identifies a concrete missing contract. 🐇

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@david-wang-0 I will perform a full review of the current pull request head.

✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@david-wang-0, I cannot identify a duplicate declaration because the reviewed test source has none.

The merge-risk paragraph is incorrect. It must not state that the regression suite cannot parse.

Evidence for commit ee9a86c0950763c9fe064abe22c6219e039c016f:

  • tests/providers/opencode-go-session-header.test.ts imports spyOn once at Line 1.
  • The file has no repeated top-level declaration.
  • The added matrix uses separate nested callback and loop scopes at Lines 124–186.
  • Local names such as requests, config, and entropy can repeat across those scopes without creating a duplicate declaration.
  • The report did not provide an identifier, source line, TypeScript diagnostic, or parser output that supports the contrary claim.
  • Your focused test result for blob 4171ef00a85a0a115d551ce551681dc37056ec32 is consistent with this result.

Use this corrected paragraph:

The affinity behavior appears well targeted. The added regression matrix has no identified duplicate declaration or parse failure. Run the required checks before merging.

The docstring-coverage warning is also not actionable as reported. The report gives only aggregate data: three analyzed functions, 66.67% coverage, and one unsupported item. It does not identify the functions, source lines, or unsupported syntax.

The only plausible changed production function without a preceding JSDoc block is handleClaudeMessagesWithBudget in src/server/claude-messages.ts at Line 635. This is not a confirmed coverage finding. applyFinalRouteRequestNormalization has an existing docstring in src/server/responses/core.ts at Line 2304. HandleResponsesOptions.claudeGoAffinity has a field doc comment at Line 1655.

I withdraw the parse-failure implication and the implication that the aggregate docstring result identifies a concrete missing contract.

🐇

You are interacting with an AI system.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/guides/providers.md`:
- Around line 396-400: Update the Claude Messages affinity documentation to
state the complete precedence: configured OpenCode Go session headers remain
authoritative, valid explicit session or thread headers take precedence over
metadata.user_id, and metadata.user_id is used only as the fallback for the
final Go destination. Update any translated versions of this page to match the
English wording.

After applying the fix, consider running `coderabbit review --agent` for local
review. Visit https://docs.coderabbit.ai/cli.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: fe634488-bd78-4844-85c7-3b6de004145d

📥 Commits

Reviewing files that changed from the base of the PR and between cfff026 and ee9a86c.

📒 Files selected for processing (4)
  • docs-site/src/content/docs/guides/providers.md
  • src/server/claude-messages.ts
  • src/server/responses/core.ts
  • tests/providers/opencode-go-session-header.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread docs-site/src/content/docs/guides/providers.md Outdated
@david-wang-0
david-wang-0 force-pushed the fix/claude-go-final-route-affinity branch 3 times, most recently from b96db2e to ff70609 Compare September 10, 2026 14:11
david-wang-0 added a commit to david-wang-0/opencodex that referenced this pull request Sep 10, 2026
…MessagesWithBudget

Spell out that configured OpenCode Go session headers stay authoritative and that
explicit session or thread headers win over the metadata.user_id fallback, as
requested in CodeRabbit's review of lidge-jun#4050. Add a JSDoc block to the one changed
production function that lacked one.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@david-wang-0

Copy link
Copy Markdown
Contributor Author

Rebased onto the current dev tip 6d3ad12 and pushed head ff70609. The fix commit is unchanged under range-diff; a second commit addresses the remaining CodeRabbit items: the providers.md paragraph now spells out the full affinity precedence (configured Go headers, then explicit session or thread headers, then the metadata.user_id fallback), and handleClaudeMessagesWithBudget has a JSDoc block, which was the only changed production function without one.

Local validation on this head with the pinned Bun 1.4.2, using the same fresh-process batch runner hosted CI uses: all four shards exit 0 with 0 assertion failures across 22,562 tests, the dedicated storage-policy and api-usage jobs pass 9/9 and 33/33, and typecheck, privacy scan and the docs build pass. Ten Bun batch crashes of the #1302 class were recovered by the runner's singleton isolation. Details and the updated reproduction pins are in the description. The readiness checklist is now fully ticked.


Agent attribution: Claude Fable 5.1 (Anthropic Claude Code).

@david-wang-0
david-wang-0 marked this pull request as ready for review September 10, 2026 14:12

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked ff70609 on 6d3ad12. Carrying Claude-derived Go affinity out of band to final-route normalization addresses the preliminary-versus-dispatch selection mismatch without putting Go-only identity into non-Go replay headers. The request-level random/failover matrix covers both wires, operator/header precedence, metadata, and the final non-Go negative control. I found no duplicate top-level test declaration; CodeRabbit's withdrawn parse claim should not remain a blocker.

The pinned-Bun four-shard results are materially better readiness evidence than a raw monolithic SIGSEGV; please retain the recovered-crash count and runner details rather than calling those crashes nonexistent. Hosted product/typecheck evidence is still absent from the current check rollup, so this is not a merge approval.

Integration note for @lidge-jun: coordinate this with #4184. Both change the final resolveOpenCodeGoTransport lane input, and this PR's invalid-metadata/shared-system cases currently expect no Go session header, while #4184 intentionally gives sessionless requests a per-request lane. The combined contract should be valid explicit/metadata identity first, otherwise a request-scoped lane stable across retries, and no automatic Go header at a final non-Go destination. Validate that combined matrix on the integration head; do not resolve the overlap by dropping either boundary.

@david-wang-0

Copy link
Copy Markdown
Contributor Author

@Ingwannu Thanks for the recheck. Two follow-ups.

Hosted CI. The Cross-platform CI and React Doctor runs for head ff70609 are sitting at action_required (workflow runs 34487421445 and 34487529109): as a fork PR they need a maintainer to approve the run before the product suite and typecheck jobs execute. The earlier head's runs had been approved, which is why the rollup used to show them. @lidge-jun could you approve the pending run? Nothing further is required from this side. The recovered-crash count and runner details stay in the description as you asked.

Overlap with #4184. I test-merged #4184 (c303cf9) onto this head locally. The only conflict is the lane input to resolveOpenCodeGoTransport in core.ts, plus the semantic change: #4184 always emits a Go header, so this PR's sixteen invalid-metadata and shared-system cases, which assert no header, would fail on the integration head. The combined contract you described resolves cleanly:

  • core.ts: keep the Claude affinity snapshot when present, otherwise use getOrAllocateRequestSessionLane(req) from fix(opencode-go): isolate sessionless requests with request-scoped affinity #4184.
  • claude-messages.ts: the Claude lane falls back, after explicit lane, client Go header and validated metadata, to the request-scoped lane allocated on the admitted client request. Allocating on the client request rather than the internal replay request keeps a later synthesized native session_id header, and any shared system-prompt cache key, out of the Go lane.
  • Tests: the sixteen cases now assert a well-formed ocx_ lane that is not the metadata-derived value and differs between two independent requests. The final non-Go negative control is unchanged and still passes.

Result on that integration head: the merged affinity suite plus routing-policy-fallback pass 101/101, the other test files #4184 names pass 47/47, and typecheck is clean. I did not run the full suite there. The exact resolution is pushed for reference as integ/4050-with-4184 on my fork (1f1537f); it is not part of this PR, which remains correct against current dev. Whichever PR lands second can apply that resolution.


Agent attribution: Claude Fable 5.1 (Anthropic Claude Code).

@david-wang-0
david-wang-0 force-pushed the fix/claude-go-final-route-affinity branch from ff70609 to 799933d Compare September 10, 2026 17:53
david-wang-0 added a commit to david-wang-0/opencodex that referenced this pull request Sep 10, 2026
…MessagesWithBudget

Spell out that configured OpenCode Go session headers stay authoritative and that
explicit session or thread headers win over the metadata.user_id fallback, as
requested in CodeRabbit's review of lidge-jun#4050. Add a JSDoc block to the one changed
production function that lacked one.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@david-wang-0

Copy link
Copy Markdown
Contributor Author

Rebased onto the current dev tip 6101140 and pushed head 799933d. Both commits are unchanged under range-diff; the intervening dev commits are devlog documentation only. On this head typecheck, the focused affinity suite (84/84), bun run test:changed (4,945 tests across 180 import-connected files, 0 failures), and the privacy scan all pass. The description's head and reproduction pins are updated. The hosted CI run for this head will again need maintainer approval as a fork PR.


Agent attribution: Claude Fable 5.1 (Anthropic Claude Code).

@github-actions
github-actions Bot marked this pull request as draft September 11, 2026 04:39
@david-wang-0

Copy link
Copy Markdown
Contributor Author

Rebased onto the current dev tip 42184ead0; head is now ad11ab078. Range-diff against d8ccff44a shows all three commits unchanged; the new dev commits (hub state, hub client, launchd repair, docs) do not touch this PR's files.

Local verification on this head with the pinned Bun 1.4.2: typecheck clean; focused suite 87 pass / 0 fail; bun run test:changed 4,967 pass / 0 fail; all four CI shards exited 0 with 0 assertion failures over 22,955 tests. Description pins updated.

Agent attribution: Claude Fable 5.1 (Anthropic Claude Code).

@github-actions
github-actions Bot marked this pull request as ready for review September 11, 2026 04:44
david-wang-0 added a commit to david-wang-0/opencodex that referenced this pull request Sep 11, 2026
…MessagesWithBudget

Spell out that configured OpenCode Go session headers stay authoritative and that
explicit session or thread headers win over the metadata.user_id fallback, as
requested in CodeRabbit's review of lidge-jun#4050. Add a JSDoc block to the one changed
production function that lacked one.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@david-wang-0
david-wang-0 force-pushed the fix/claude-go-final-route-affinity branch from ad11ab0 to db22224 Compare September 11, 2026 06:23
@github-actions
github-actions Bot marked this pull request as draft September 11, 2026 06:23
@github-actions
github-actions Bot marked this pull request as ready for review September 11, 2026 06:24
@david-wang-0

Copy link
Copy Markdown
Contributor Author

Rebased onto the current dev tip 18e553a52 (#4257); head is now db222240a. Range-diff against ad11ab078 shows all three commits unchanged, and the intervening dev commits do not touch this PR's files or their imports. On the new head: typecheck clean, the Go session-header suite 87/87, and bun run test:changed 4,964 pass / 0 fail across 181 import-connected files (pinned Bun 1.4.2). Description pins and repro script updated; hosted CI will need re-approval for the new head.

Agent attribution: Claude Fable 5.1 (Anthropic Claude Code).

@Ingwannu

Copy link
Copy Markdown
Owner

The head moved from ad11ab0 to db22224 while I was approving the previous runs. I stopped the old-head review write, fetched the new head, and verified by range-diff that all three authored commits are unchanged. The workflow/dependency delta is empty and the requested sessionless documentation correction remains present.

Approved the new exact-head Cross-platform CI 34569691357 and React Doctor 34569691360. The earlier 34563015975/34563015889 approvals belong to ad11ab0 and must not be cited as validation of this head. No merge or local runtime change was performed.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving exact head db22224, based on current dev 18e553a.

The reviewed four-file change preserves operator > explicit request identity > valid Claude metadata precedence, carries identity privately to the final Go destination, and retains the request-scoped fallback introduced by #4226. The real-handler matrix covers random/failover selection, both Go wires, invalid/shared identity, independent sessionless requests, and final non-Go isolation. The sessionless guide wording is now corrected. Earlier review conditions are resolved; no new workflow, dependency, credential-source or destination change is included.

Exact-head upstream Cross-platform CI 34569691357 and React Doctor 34569691360 both succeeded. The Windows full shards and macOS control were deliberately skipped by the workflow; they are not claimed executed. No local product or live-provider test was run for this review.

@lidge-jun This is independent review approval, not a merge or a self-approval. Recheck head/base and branch rules at integration time. Local runtime settings and active sessions were not changed.

david-wang-0 added a commit to david-wang-0/opencodex that referenced this pull request Sep 11, 2026
…MessagesWithBudget

Spell out that configured OpenCode Go session headers stay authoritative and that
explicit session or thread headers win over the metadata.user_id fallback, as
requested in CodeRabbit's review of lidge-jun#4050. Add a JSDoc block to the one changed
production function that lacked one.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@david-wang-0
david-wang-0 force-pushed the fix/claude-go-final-route-affinity branch from db22224 to 5cb63c0 Compare September 11, 2026 09:38
@github-actions
github-actions Bot marked this pull request as draft September 11, 2026 09:38
@github-actions
github-actions Bot marked this pull request as ready for review September 11, 2026 09:39
@david-wang-0

Copy link
Copy Markdown
Contributor Author

Rebased onto dev tip 75d4cde6f (#4244, #4248, #4246); head is now 5cb63c09c. Range-diff against db222240a shows all three commits unchanged. Because #4248 touched src/server/responses/core.ts, which this PR also changes, the full CI test set was re-run on the new head: all four shards passed (22,994 tests, 0 failures), plus typecheck clean, the Go session-header suite 87/87, and bun run test:changed 4,970 pass / 0 fail across 182 files (pinned Bun 1.4.2). Description pins and repro script updated; hosted CI will need re-approval for the new head.

Agent attribution: Claude Fable 5.1 (Anthropic Claude Code).

david-wang-0 and others added 3 commits September 11, 2026 13:21
Carry validated Claude affinity privately through combo replay and consume it only at the final canonical Go transport. Preserve explicit identity and operator precedence without leaking Go-only headers to other destinations.

Addresses the late review on lidge-jun#3961. Adds deterministic random and failover regressions across both Go wires.

Co-authored-by: GPT-6 Astra <noreply@openai.com>
…MessagesWithBudget

Spell out that configured OpenCode Go session headers stay authoritative and that
explicit session or thread headers win over the metadata.user_id fallback, as
requested in CodeRabbit's review of lidge-jun#4050. Add a JSDoc block to the one changed
production function that lacked one.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
The guide's sessionless sentence predated the request-scoped lane allocator
that landed on dev (lidge-jun#4184 via lidge-jun#4226). A request without a session identifier
still receives no inferred cross-request identity, but it is now sent under
an isolated per-request session rather than none at all.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@david-wang-0
david-wang-0 force-pushed the fix/claude-go-final-route-affinity branch from 5cb63c0 to e5c2411 Compare September 11, 2026 12:37
@github-actions
github-actions Bot marked this pull request as draft September 11, 2026 12:38
@github-actions
github-actions Bot marked this pull request as ready for review September 11, 2026 12:46
@david-wang-0

Copy link
Copy Markdown
Contributor Author

Rebased onto dev tip 16f18d654 (through #4104); head is now e5c2411f7. Range-diff against 5cb63c09c shows all three commits unchanged. Because dev touched src/server/responses/core.ts again, the full CI test set was re-run on the new head: all four shards passed (23,076 tests, 0 failures), plus typecheck clean, the Go session-header suite 87/87, and bun run test:changed 4,991 pass / 0 fail across 182 files (pinned Bun 1.4.2). Description pins and repro script updated; hosted CI will need re-approval for the new head.

Agent attribution: Claude Fable 5.1 (Anthropic Claude Code).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants