Skip to content

fix(xai): seed Responses tool-result adjacency for interrupted Codex threads - #4871

Merged
lidge-jun merged 5 commits into
lidge-jun:devfrom
MerryEcho:fix/xai-responses-tool-result-adjacency
Sep 17, 2026
Merged

lidge-jun merged 5 commits into
lidge-jun:devfrom
MerryEcho:fix/xai-responses-tool-result-adjacency

Conversation

@MerryEcho

@MerryEcho MerryEcho commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #4870

Verification

Author's verification of the first commit (7026676):

  • bun test tests/providers/xai/xai-responses-adjacency.test.ts tests/providers/kimi-responses-adjacency.test.ts tests/responses/responses-forward-dangling-call.test.ts tests/responses/responses-stateless-dangling-call-repair.test.ts tests/test-layout.test.ts tests/test-layout-tooling.test.ts — 44 pass / 0 fail
  • bun test tests/providers/deepseek-inbound-wire.test.ts tests/ci-workflows/structure-ssot.test.ts tests/providers/provider-registry-parity.test.ts tests/server/server-combo-reasoning-replay-eligibility.test.ts — 134 pass / 0 fail
  • bun run typecheck — pass

Maintainer follow-up commit (d7e4efc), which separates pairing from adjacency, was verified by source reading and hosted CI on this head only. No local suite was run for it.

  • The capability is threaded exactly like requiresAdjacentResponsesToolResults: src/types/provider.ts, src/providers/registry/types.ts, both sites in src/providers/derive.ts, src/config/schema/leaf-validators.ts, and the stale-row backfill in src/router.ts. Neither flag is exposed through src/config/provider-validation.ts or the management provider routes, so nothing further is needed there.
  • Kimi's behavior is now identical to dev: it is not forward, not statelessResponses, and no longer requiresPairedResponsesToolResults, so repairOrphanedInputItems does not run for it at all. tests/providers/kimi-responses-adjacency.test.ts covers matched pairs only and is unaffected.
  • The forward path is unchanged in both commits: synthesizeMissingCallOutputs is !forward && ..., so a forward request still calls repairOrphanedInputItems(outBody, unexpandedMiss, false).
  • Added regressions pin the separation itself: adjacency alone never synthesizes an output, kimi and kimi-code carry adjacency without pairing, and a dangling custom_tool_call is paired before rewriteRoutedCustomToolsForUpstream lowers it.
  • structure/providers/chat-compat.md records both capabilities and why they do not collapse into one.
  • PROVIDER_CONFIG_FIELD_POLICY in src/server/auth-cors.ts is satisfies Record<keyof OcxProviderConfig, ProviderConfigFieldPolicy>, so the new capability needs a policy row or the whole typecheck fails from a file the change never touched. It is classified editor, matching its sibling wire capabilities (statelessResponses, requiresAdjacentResponsesToolResults, annotateEmptyToolOutputs) and matching what that policy means in the record's own comment: the field is user-authorable through the leaf validator schema and is seeded from the registry only when the user has not set it, it carries no credential, and it is not a runtime observation.

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.

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

  • Bug Fixes

    • Improved xAI Responses reliability after interrupted or replayed tool calls.
    • Restores missing tool results and keeps calls paired correctly during replay.
    • Preserves conversation state while repairing incomplete requests.
    • Handles developer messages between tool calls and results.
    • Maintains correct behavior for Kimi, without inventing missing tool results.
  • Documentation

    • Clarified Responses compatibility behavior and tool-result handling for xAI Grok subscription models.

…threads

Grok 4.6/4.5 OAuth Responses replays Codex tool history. After a mid-stream
502/reset the client can resend a function_call without its output, or with
hook-injected developer context between the pair. Google already synthesizes
a missing tool_result; xAI did not, so later turns in the same thread 400.

Reuse requiresAdjacentResponsesToolResults (Kimi lidge-jun#4726, DeepSeek lidge-jun#1292) and
run the existing orphan-call placeholder for non-forward adjacency providers.
Do not set statelessResponses: xAI stores responses for 30 days.

Closes lidge-jun#4870
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

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

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

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: afbe1830-99e7-4bc1-8786-0edde5a09a88

📥 Commits

Reviewing files that changed from the base of the PR and between 7026676 and 7c30bce.

📒 Files selected for processing (11)
  • src/adapters/openai-responses/passthrough.ts
  • src/config/schema/leaf-validators.ts
  • src/providers/derive.ts
  • src/providers/registry/entries-core.ts
  • src/providers/registry/types.ts
  • src/router.ts
  • src/server/auth-cors.ts
  • src/types/provider.ts
  • structure/providers/chat-compat.md
  • structure/providers/xai-grok.md
  • tests/providers/xai/xai-responses-adjacency.test.ts

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


📝 Walkthrough

Walkthrough

The xAI Responses configuration now supports separate adjacency and paired-result capabilities. Replayed stateful requests can synthesize missing tool outputs without removing store or previous_response_id. Forward-auth and adjacency-only behavior remain distinct.

Changes

xAI Responses paired tool-result repair

Layer / File(s) Summary
Capability contract and propagation
src/types/provider.ts, src/config/schema/leaf-validators.ts, src/providers/registry/types.ts, src/providers/registry/entries-core.ts, src/providers/derive.ts, src/router.ts, src/server/auth-cors.ts
The new requiresPairedResponsesToolResults capability is defined, validated, seeded for xAI, backfilled into stale configurations, routed, and exposed through provider configuration editing.
Replay repair behavior
src/adapters/openai-responses/passthrough.ts
Non-forward providers with paired-result support now receive orphan-call repair and synthesized function_call_output items. Adjacency-only providers still receive reordering without synthesized outputs.
Validation and documentation
tests/providers/xai/xai-responses-adjacency.test.ts, structure/providers/chat-compat.md, structure/providers/xai-grok.md, scripts/test-layout/layout.json, tests/fixtures/test-layout-expected.json
Tests cover xAI pairing, adjacency, state preservation, forward authentication, Kimi behavior, and custom tool lowering. Documentation and test-layout fixtures describe and register the capability.

Priority: ➖ Normal

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

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant ProviderRegistry
  participant enrichProviderFromRegistry
  participant buildRequest
  participant repairOrphanedInputItems
  participant xAIResponsesAPI
  ProviderRegistry->>enrichProviderFromRegistry: Seed paired and adjacent capabilities
  enrichProviderFromRegistry->>buildRequest: Provide resolved xAI configuration
  buildRequest->>repairOrphanedInputItems: Repair missing tool outputs
  repairOrphanedInputItems->>xAIResponsesAPI: Send repaired stateful Responses input
Loading

Merge Risk: ⚪ Minimal · up to 7c30b

The replay repair is covered across the configured xAI, Kimi, and forward-auth behaviors, with no concrete unresolved merge risk identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 9 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the xAI Responses replay fix for interrupted Codex threads. It highlights the primary adjacency-repair change and is concise, specific, and related to the changeset.
Linked Issues check ✅ Passed The PR meets the coding requirements in #4870. src/providers/registry/entries-core.ts seeds both requiresAdjacentResponsesToolResults and requiresPairedResponsesToolResults for xAI. It leaves `s…
Out of Scope Changes check ✅ Passed The changes remain within #4870. The shared adapter change implements the required Responses replay behavior. Registry, schema, type, derive, router, and field-policy changes provide the required capa…
Full details: Docstring Coverage

Explanation

Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 9 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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 17, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • hygiene: unsponsored_surface.

What to do

  • Fix unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/server/auth-cors.ts.
  • Tick all four boxes in the PR description once you're done (currently 0/4).

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.

0/4 boxes ticked.

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 marked this pull request as draft September 17, 2026 06:54
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 74 / 80

이 PR은 MerryEcho의 Draft 버그 수정이다. 제목대로 xAI Responses 쪽에서, Codex Desktop 스레드가 중간에 끊긴 뒤 도구 호출/결과가 짝이 안 맞거나 사이에 훅 developer 메시지가 끼면 나중 턴이 계속 400 나는 문제를 고친다. 닫으려는 이슈는 #4870이다. 현재 dev HEAD는 7868f5df5(tip #4867, web-search connect deadline을 가상 시계로 돌리는 테스트)이고 패키지는 2.58.0이다. 이 PR 베이스도 그 tip이다.

지금 dev에서 xAI 레지스트리(src/providers/registry/entries-core.tsid: "xai")에는 requiresAdjacentResponsesToolResults가 없다. 같은 플래그는 이미 Kimi(#4726)와 DeepSeek(#1292)에 심어져 있다. passthrough(src/adapters/openai-responses/passthrough.ts)는 그 플래그가 켜진 공급자에게만 normalizeResponsesToolResultAdjacency를 돌린다. 그런데 짝 없는 function_call에 가짜 출력을 넣는 repairOrphanedInputItems(..., synthesizeMissingCallOutputs)는 지금 forward || stateless일 때만 돌아간다. DeepSeek는 statelessResponses: true라서 둘 다 탄다. xAI는 공개 Responses가 대화를 최대 30일 저장하고 previous_response_id를 문서화하므로 statelessResponses를 켜면 store / previous_response_id를 벗겨 버려서 안 된다. 그래서 지금 xAI OAuth Responses 스레드는 인접 재정렬도, orphan placeholder도 둘 다 못 탄다.

증상은 #4870에 숫자로 적혀 있다. 첫 실패는 대개 업스트림 502/connection-reset(자주 ~15초)이다. 그 뒤 같은 스레드의 다음 요청 실패율이 약 20.6%로 치솟고, 한 번도 안 깨진 이웃 스레드는 깨끗하다. Google는 이미 빠진 tool_result를 합성한다(#2199). xAI Responses 파서는 그걸 안 해서, Codex가 function_call만 다시 보내거나 훅 developer 메시지를 짝 사이에 끼우면 이후 턴이 400으로 눈덩이처럼 커진다. 이 PR은 첫 15초 리셋을 고치지 않는다. 그건 업스트림 컷오프고, Cursor protobuf 어댑터도 범위 밖이다. 여기서 하는 일은 더러운 히스토리가 나중 턴을 전부 죽이지 않게 막는 것이다.

고치는 방법은 기존 능력을 재사용한다. (1) xAI 레지스트리에 requiresAdjacentResponsesToolResults: true를 심고 statelessResponses는 안 켠다. (2) passthrough에서 adjacentToolResultsrepairOrphanedInputItems도 돌리되, synthesizeMissingCallOutputs = !forward && (stateless || adjacentToolResults)로 둔다. forward-auth는 예전처럼 합성을 안 한다(fail-closed). (3) structure/providers/chat-compat.md에 xAI가 stateful이라 adjacency + orphan placeholder를 같이 쓰는 이유를 적는다. (4) 새 테스트 tests/providers/xai/xai-responses-adjacency.test.ts와 레이아웃 픽스처를 추가한다.

테스트 네 축이 핵심이다. 레지스트리 시드가 있고 statelessResponses는 undefined인지, 오래된 저장 행도 enrichProviderFromRegistry / routedProviderConfig로 백필되는지, 끊긴 function_call에 placeholder output이 붙으면서 previous_response_idstore: true는 남는지, 훅 developer 메시지는 짝 뒤로 밀리는지, 두 호출 중 하나만 결과가 있을 때 없는 쪽만 합성하는지, forward-auth는 합성을 안 하는지. 저자가 적은 로컬 검증(인접·dangling·레이아웃·레지스트리 패리티·typecheck)도 이 축과 맞다. CI는 지금 hygiene/label/enforce-target 정도만 통과했고 CodeRabbit과 본 테스트 스위트는 아직 진행 중이다. Draft 체크리스트 네 칸도 비어 있다.

types.ts/config.ts 대분할 캠페인으로 바로 무효화되는 PR은 아니다. 레지스트리 capability 한 줄과 passthrough 게이트 확장, 문서·테스트다. 다만 passthrough 게이트를 adjacentToolResults까지 넓히면 xAI뿐 아니라 레지스트리에 adjacency만 있고 stateless가 없는 Kimi / kimi-code가 Responses 와이어로 붙을 때도 orphan 합성이 새로 켜진다. DeepSeek는 원래 stateless라 이미 탔다. 의도된 일반화로 보이지만, Kimi 쪽 관측 400과 같은지 메인테이너가 한 번 확인하면 좋다.

passthrough.ts / synthesizeMissingCallOutputs 게이트 - forward||stateless만 돌리던 orphan 합성을 adjacency 공급자까지 넓힌다. xAI에는 필요하지만 Kimi/kimi-code(Responses로 붙을 때) 동작도 함께 바뀐다.
entries-core.ts xai requiresAdjacentResponsesToolResults - 플래그만 심고 statelessResponses는 안 켠 선택은 맞고, 공개 docs(store/previous_response_id)와도 맞다.
tests/.../xai-responses-adjacency.test.ts - function_call 경로만 본다. 이슈 본문의 custom_tool_call 언급은 테스트에 없다. repair 헬퍼는 둘 다 다루지만, Codex Desktop 재현이 custom_tool_call이면 한 케이스 더 있으면 더 단단하다.
PR Draft 체크리스트 - 네 칸 모두 비어 있다. CI 본검사·dev tip 재기반·Codex/CodeRabbit 소진 전에는 Ready로 올리면 안 된다.
첫 15s 업스트림 502/reset - 이 PR 범위 밖이라고 명시했고 맞다. 별 이슈로 남겨야 한다. 이 PR만으로는 실패율 전체 소멸을 기대하면 안 된다.

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

  • adjacency-only 공급자(Kimi/kimi-code)에 orphan 합성을 같이 켤지, xAI만 특수 케이스로 둘지. PR 설명은 전자(의도된 일반화)다.
  • Draft를 CI 그린 + 체크리스트 완료 후 바로 머지할지, 아니면 custom_tool_call dangling 테스트 한 줄을 더 받고 갈지.
  • #4870의 15초 connection-reset 클러스터를 후속 이슈로 새로 팔지, 기존 관련 이슈에 붙일지.

너의 추천
KEEP Draft. 방향은 Kimi/DeepSeek prior art와 같고, xAI에 stateless를 안 켠 것도 맞다. exact-head CI가 그린이 되고 Draft 체크리스트를 채운 뒤 머지하면 된다. 가능하면 custom_tool_call dangling 한 케이스와, Kimi adjacency-only에 합성이 켜지는 부작용이 의도인지 한 줄 확인을 받고 가도 좋다. types/config 분할로 close-don't-rebase 대상은 아니다. #4870은 머지 시 함께 닫힌다.

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

Gating the missing-output synthesis on requiresAdjacentResponsesToolResults
enrolled kimi and kimi-code in it too. Both carry that flag because their parser
rejects a hook-split pair, but the same report (lidge-jun#4726) shows a call left without
any result is accepted, so they would have started receiving placeholder tool
turns for a shape they never rejected.

Adjacency reorders items the upstream would accept in some order. Pairing
synthesizes an item the client never sent, which is a larger claim about what
happened in the conversation, so it gets its own capability:
requiresPairedResponsesToolResults, seeded on xai only. statelessResponses still
implies it, which is how DeepSeek already had the repair.

Stateful behavior is untouched: store and previous_response_id survive, and
forward auth still suppresses synthesis.
@lidge-jun

Copy link
Copy Markdown
Owner

Reviewed at 7026676 and pushed a follow-up commit (d7e4efc) to this branch rather than opening a competing PR, so the work and its credit stay here. Happy to revert it if you would rather make the change yourself.

The blocker, and what the follow-up does. Gating the missing-output synthesis on requiresAdjacentResponsesToolResults did not only affect xAI. kimi (src/providers/registry/entries-core.ts) and kimi-code (src/providers/registry/entries-extended.ts) carry that flag and are neither forward nor statelessResponses, so on dev repairOrphanedInputItems never runs for them at all. With !forward && (stateless || adjacentToolResults) it starts running with synthesis on, and a dangling Kimi call that used to pass through untouched acquires a placeholder tool turn. #4726 is explicit that Kimi returned HTTP 200 for call → developer message with no result, so that shape is not one Kimi rejects. DeepSeek was unaffected either way, since it already sets statelessResponses.

That matters beyond the registry bookkeeping. Adjacency reorders items the upstream would accept in some order, so it is safe to apply wherever the parser is strict about ordering. Synthesis inserts an item the client never sent, which is a claim about what happened in the conversation. Those deserve separate capabilities, and src/types/provider.ts documents the adjacency flag as the reordering one.

So d7e4efc adds requiresPairedResponsesToolResults, threaded exactly like its sibling (src/types/provider.ts, src/providers/registry/types.ts, both src/providers/derive.ts sites, src/config/schema/leaf-validators.ts, and the stale-row backfill in src/router.ts), seeded on xai only. statelessResponses still implies it, so DeepSeek keeps the repair it had. Kimi returns to exactly its dev behavior.

What I verified and agree with in your change.

  • The custom-tool path already works, and I added a regression for it. repairOrphanedInputItems indexes and synthesizes custom_tool_call_output (src/adapters/openai-responses/tool-output-recovery.ts), normalizeResponsesToolResultAdjacency pairs both types, and both run before rewriteRoutedCustomToolsForUpstream, so a dangling custom call is paired first and then lowered as a pair. That ordering is load-bearing and was previously unpinned.
  • The forward boundary is unchanged. synthesizeMissingCallOutputs is !forward && ... in both versions, so a forward request still gets repairOrphanedInputItems(outBody, unexpandedMiss, false). That is the right call: the backend holding the conversation can resolve the pair itself.
  • Statefulness is intact, which was the constraint I cared most about. stripStatefulResponsesParams is reachable only under if (stateless), xAI does not set it, and your test asserting store: true and previous_response_id survive is the assertion that keeps it that way. Repairing an interrupted history must not cost the thread its server-side state, and it does not.
  • The synthesized output is honest. It records that no result was captured and that execution status is unknown, rather than dressing an unexecuted call as success.

One thing still open for a maintainer. structure/manifest.json lists providers/xai-grok.md as an owner of src/providers/, and that page still describes the xAI surface as retaining its existing behavior. I updated structure/providers/chat-compat.md, which is where both capabilities are actually specified, and left xai-grok.md alone rather than duplicating the contract in two places. bun run structure:check does not fail on this, but it is worth a maintainer's call.

No local suite was run for the follow-up commit; it was verified by source reading and hosted CI on this head, per the constraints this review is operating under.

…actually takes

The previous case declared no custom tool, so collectRoutedCustomToolNames found
nothing and the lowering never ran; it proved only that the repair indexes
custom calls. xAI sets supportsResponsesCustomTools: false, so the production
shape is a declared custom tool that gets lowered, and that is what this now
asserts end to end.
… page

providers/xai-grok.md co-owns src/providers/ and says the surface retains its existing behavior, which stopped being true once a capability was seeded for xAI alone. Points at chat-compat.md rather than restating the contract in two places.
…d policy

PROVIDER_CONFIG_FIELD_POLICY is satisfies Record<keyof OcxProviderConfig, ...>, so adding a field to OcxProviderConfig without a policy row fails the whole typecheck from a different file. That is what broke gates and the production adapter contract test on Linux and Windows.

editor matches the sibling wire capabilities (statelessResponses, requiresAdjacentResponsesToolResults, annotateEmptyToolOutputs) and matches what the policy means: the field is user-authorable through the leaf validator schema and is seeded from the registry only when the user has not set it. It carries no credential and is not a runtime observation.
@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Sep 17, 2026
@lidge-jun

Copy link
Copy Markdown
Owner

Maintainer integration note (recorded per MAINTAINERS.md).

Repository CI evidence for this tree exists and was produced by a maintainer, not by the author. The exact tree at 7c30bce5266ba9cafc2b7c66fa4230af0427f228 was pushed to codex/ci-evidence-4871 merged with the current dev, and ci.yml was dispatched there with lane=all (run 35221386977). All nine Windows shards passed, alongside the Linux and macOS legs.

An earlier dispatch of this tree failed on gates, test 1/4 and one Windows shard with TS2741: Property 'requiresPairedResponsesToolResults' is missing in src/server/auth-cors.ts — a policy row that the new provider capability required in a file this change never touched. That was fixed at 7c30bce526 before the evidence above.

Two further dispatches of this tree failed on Windows for a reason that was not in this change: the evidence branch pre-dated #4876, and workflow_dispatch reads the workflow file from the dispatched ref, so those runs used a ci.yml without OCX_TEST_NO_QUEUE and reproduced the batch-serialization bug #4876 fixed. Merging current dev into the evidence branch removed that and the Windows legs passed.

Marking this ready for review on that basis. The readiness checklist's local-CI box is an author attestation that a fork contributor cannot satisfy against repository CI; the dispatch above is stronger evidence of the same property, and it is recorded here rather than asserted. Authorship and the Co-authored-by trailer are unchanged.

@lidge-jun
lidge-jun marked this pull request as ready for review September 17, 2026 13:02
@github-actions
github-actions Bot marked this pull request as draft September 17, 2026 13:03
@lidge-jun

Copy link
Copy Markdown
Owner

@MerryEcho — this is ready from our side and the remaining step is yours.

Repository CI has now run on this exact head (7c30bce526) and every substantive leg passed: gates, all four Linux test shards, both macOS shards, keyring and npm-global on all three platforms, storage policy, api usage, docker smoke. The nine Windows shards passed too, from a maintainer dispatch of this tree merged with current dev (see the note above). The only non-green entries are macos control, which the hosted macOS runners cancelled for capacity rather than failed, and the readiness gate itself.

That gate is what is holding the PR in draft. It needs the four boxes in the description ticked by you: local CI green, branch on the latest dev, Codex/CodeRabbit findings addressed, and the ready-for-review confirmation. We cannot tick the local-CI box for you — it is an author attestation, and asserting it on your behalf would make it meaningless. The evidence above is the maintainer-side equivalent and is recorded in this thread, so you can reference it.

Once the boxes are ticked the gate marks the PR ready and we will merge it. Thanks for the fix.

@lidge-jun

Copy link
Copy Markdown
Owner

Merging with maintainer admin rights. Three non-green entries at this head, and none of them is a defect in this change.

macos control was cancelled by hosted runner capacity, which is what makes the aggregate ci red.

windows 1/9 failed on a maintainer dispatch of this exact tree, and that failure is an artifact of how the evidence was produced rather than of this change. workflow_dispatch reads the workflow file from the dispatched ref; this head pre-dates #4876, so those runs used a ci.yml without OCX_TEST_NO_QUEUE and reproduced the batch-serialization bug #4876 had already fixed. The log shows the batch stalling on waiting for test run pid ... to release the user lock with zero test results for the following eight minutes. Re-running the same tree merged with current dev passed all nine Windows shards.

enforce-target and hygiene are the contributor readiness gate, whose local-CI box is an author attestation a fork contributor cannot satisfy against repository CI. The dispatch above is the maintainer-side equivalent and is recorded here.

Everything substantive passed: gates, all four Linux shards, both macOS shards, keyring and npm-global on all three platforms.

@lidge-jun
lidge-jun marked this pull request as ready for review September 17, 2026 13:25
@lidge-jun
lidge-jun merged commit 7c8e961 into lidge-jun:dev Sep 17, 2026
59 of 72 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working intake: hygiene-blocked Deterministic PR hygiene checks failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants