Skip to content

release: promote the verified 2.65.0 preview tree to preview - #5783

Merged
lidge-jun merged 49 commits into
previewfrom
codex/260925-release-preview-2.65.0
Sep 24, 2026
Merged

lidge-jun merged 49 commits into
previewfrom
codex/260925-release-preview-2.65.0

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

Promote the verified dev candidate 5cdd97ea17 to preview for 2.65.0-preview.20260925. The promotion commit has the candidate as its first parent and the previous preview tip as its second parent (-s ours), so the promoted tree is the verified candidate, apart from the four version sources set to 2.65.0-preview.20260925. This round lands #5749, #5751, #5753, #5752, #5744, #5712, #5765, #5769 and the dev repairs #5767, #5768, #5770 (revert of #5697) and #5772.

Verification

  • dev candidate 5cdd97ea17: full-platform lane=all Cross-platform CI succeeded with every requested job green, including all nine Windows shards (windows 3/9 passed on its one allowed rerun after a child-spawn stall).
  • bun scripts/release-version-sources.ts check 2.65.0-preview.20260925``: passed.
  • The release job requires successful push-event Cross-platform CI and Service lifecycle on the preview merge SHA; checked after merge.
  • Local full test suite: NOT RUN (hosted CI only, at the owner's direction).

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.

github-actions Bot and others added 30 commits September 23, 2026 18:30
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…EADME inventory counts (#5672)

* docs(devlog): triage the lane A tests-hygiene bundle

* fix(tests): capture the real resolver before mocking adapter-resolve

Carries #5482.

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>

* fix(tests): dispose test translator budgets in every file that creates them

Carries #5607.

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>

* fix(tests): restore the sandbox home after every test file

Carries #5570 (both PR commits, including the CodeRabbit ordering fix).

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>

* fix(tests): put the real modules back after the image tests mock them

Carries #5605. Folded review fix: each file restores only the module
snapshots it actually captured, so a beforeAll that failed partway
cannot install an empty module, and z-handler-activation restores its
overrides in a finally block so a failed directory removal cannot leave
them installed for later files in the process.

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>

* fix(desktop): never restart the real desktop app from the test runner

Carries #5630. restartCodexDesktopApp returns the skipped reason
test_environment when the test preload armed OCX_TEST_HOME_GUARD and no
execFile was injected, and the CLI reports that skip. Folded review fix:
structure/runtime.md documents the guarded outcome next to the CLI
restart scope it owns.

Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>

* docs(readme): derive the memory inventory counts instead of restating them

Carries #5340, rebuilt on dev after #5615 and #5638 so their README and
locale prose stays intact. Folded review fixes: dev now registers 14
retained stores, and native_control_replay is pinned (evictOldest
returns 0), so every page says 14 and names the one store the budget
never evicts; the guard's header drops the numbers that had gone stale;
readme/i18n-manifest.json carries the hash of the final README.md.

Co-authored-by: codingbo <9621077+codingbooo@users.noreply.github.com>

* docs(devlog): record the lane A delivery

---------

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>
Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>
Co-authored-by: codingbo <9621077+codingbooo@users.noreply.github.com>
…web_search, artifact connect deadline, Alibaba Responses pins, Windows kiro.exe (#5673)

* docs(devlog): plan bundle lane F1 (provider registry)

* fix(cursor): continue composer-2.5-fast tool turns as userMessageAction

composer-2.5-fast stayed on resumeAction after the 2026-08-20 capture because
it answered on that path then. A 2026-09-21 proxy log shows the fast build
completing a tool-result turn with no text and no tool call, the same empty
stop that moved composer-2.5 to the external continuation path. Route the fast
id through cursorNeedsExternalToolContinuation too.

Tests that pinned fast to resumeAction now use composer-1 as the native
counterexample, the live-transport screenshot case expects the Composer
continuation for both 2.5 builds, and the clipped-invocation restoration case
covers fast. cursor-blob.test.ts stays at its line cap.

Carries #5362.

Co-authored-by: Play <99410048+001005HS@users.noreply.github.com>

* fix(adapters): strip the refused web_search fields on direct Meta for every Muse id

Direct Meta Muse / Meta Model Responses refuses search_content_types and
indexed_web_access on a plain web_search tool as a gateway schema rule, before
inference, for every Muse model it serves. Dev only stripped them for the
Contributor ids, so the non-Contributor default muse-spark-1.3 (both direct-Meta
presets) still sent them and 400ed every Codex turn that attached web_search.

The direct Meta destination is now the whole predicate, including a missing
model id; the two OpenCode Zen destinations keep the Contributor-id gate because
they serve nothing else. Preview tools keep their accepted shape. The contract
moves to structure/transports/responses-wire-shapes.md, replacing the stale
"unrelated models" wording.

Carries #5314.

Co-authored-by: Ivan Fokeev <2017148+ifokeev@users.noreply.github.com>

* fix(images): add a connect deadline to provider artifact downloads

Provider-returned image and video URLs are downloaded through
connectPublicHttps and the pinned-IP transport. That path bounded the idle
phases and the first byte but did not arm a separate TCP/TLS connect
deadline, so a peer that never completed the handshake held the download for
the full first-byte window. connectPublicHttps now forwards a 10 s
DOWNLOAD_CONNECT_TIMEOUT_MS and pinnedHttpsGet accepts a per-call
connectTimeoutMs with the same default; a stalled connect fails with
connect_timeout. The idle timer and the 50 MiB cap are unchanged.

The production-path test lives in a new sibling file registered in both
layout manifests; the transport inventory records the deadline.

Carries #5349.

Co-authored-by: ahmedfrawelo <247386484+ahmedfrawelo@users.noreply.github.com>

* feat(registry): pin live-verified Alibaba Token Plan models to the Responses wire

Alibaba Token Plan (Beijing) documents a native Responses API on the same
compatible-mode base and an official Codex guide on wire_api = "responses"
(#5097). qwen3.8-flash, qwen3.7-plus and glm-5.3 were live-verified end to end
on that gateway, so the registry now defaults them to openai-responses for
Responses inbound only. Chat and Anthropic inbound keep the provider-wide Chat
wire and its measured prefix-cache behaviour, and modelAdapters still wins in
both directions.

The entry sets preserveResponsesReasoningContent beside the pins: the
Responses serializer reads that flag rather than the Chat-side
preserveReasoningContentModels list, and the gateway accepted replayed
plaintext reasoning content live. qwen3.7-plus sends its effort as a
reasoning.effort string on this wire instead of the Chat-side numeric
thinking_budget. The intl sibling stays unpinned.

Tests cover resolver defaults per inbound, the upstream URL through
handleResponses for all three pinned models (glm-5.3 now asserts the
Responses default, not only the Anthropic path), the qwen3.7-plus effort
payload, overrides, and the reasoning replay flag. The provider reference row
and structure/transports/responses-wire-shapes.md describe the pins.

Carries #5188. Closes #5097.

Co-authored-by: mdwsk88 <11055210+mdwsk88@users.noreply.github.com>

* fix(oauth): fall back to kiro.exe inside the dedicated Windows Kiro-Cli folders

Some Windows installs keep the CLI as kiro.exe in %LOCALAPPDATA%\Kiro-Cli or
Program Files\Kiro-Cli, so forced and add-account Kiro login could not find
it. After every canonical kiro-cli candidate misses, the resolver now accepts
kiro.exe inside those two folders only, which are already trusted for
kiro-cli.exe, and only when the base is a fully qualified drive path.

A short name is never resolved from PATH or from the shared POSIX bin
directories (~/.local/bin, /usr/local/bin, /opt/homebrew/bin): an unrelated
kiro there, such as the Kiro IDE launcher, must not receive credential-flow
arguments. Negative tests cover a short name on PATH, relative and
drive-relative bases, and the POSIX directories. The provider guide and
structure/providers/kiro.md state the order.

Partial carry of #5000: its Unix short-name fallback is left out.

Co-authored-by: 정우철 <86232509+oocheol@users.noreply.github.com>

* fix(bundle-f1): fold the adversarial review nits

- src/images/artifacts.ts: state the connect-deadline rationale correctly; a
  60 s first-byte timer already runs before the connection exists, and the new
  deadline bounds TCP/TLS setup on its own.
- fr, tr and zh-tw provider guides: add the Windows kiro.exe fallback and the
  never-a-short-name-from-PATH rule next to the existing Kiro-Cli paragraph.
- devlog lane plan: drop trailing blank lines and add the delivery doc.

---------

Co-authored-by: Play <99410048+001005HS@users.noreply.github.com>
Co-authored-by: Ivan Fokeev <2017148+ifokeev@users.noreply.github.com>
Co-authored-by: ahmedfrawelo <247386484+ahmedfrawelo@users.noreply.github.com>
Co-authored-by: mdwsk88 <11055210+mdwsk88@users.noreply.github.com>
Co-authored-by: 정우철 <86232509+oocheol@users.noreply.github.com>
…lls (lane F2) (#5674)

* fix(clients): tell Pi and omo to send system instead of developer (#5664)

Pi sends its system prompt as `developer` for reasoning models. The native
Chat Completions route forwards caller roles verbatim unless a destination
has recorded foldDeveloperRoleToSystem, so upstreams that reject the role
(DashScope compatible-mode answers "developer is not one of [...]") failed
every request. Users could not work around it: every export rewrites the
whole provider block and drops a hand-set compat key.

The Pi export now writes compat.supportsDeveloperRole: false next to the
session-affinity key, on both the export and the managed-contribution path.
omo keeps its byte-identical-to-Pi contract because senpi documents the same
key. Prime and Aside keep their compat-free block.

* fix(openai-chat): stop duplicated serialized tool calls reaching visible text (#5548)

Some Chat gateways send one model-produced call twice: as a bare
<tool_call><function=...>...</function></tool_call> block in content and as a
structured tool_calls entry, sometimes with the block body prefixed onto the
JSON arguments too. Codex then showed the raw call syntax as the answer and
could receive malformed arguments.

The adapter now holds a possible bare block (outside Markdown fences, quotes and
inline code) and removes it only when its function name and freeform body match
a structured call in the same response; the argument prefix is repaired only for
that exact duplicated shape. Mismatched markup stays byte-exact, held text is
drained on every terminal path, and the held bytes use the translator budget.

Carried from #5548 and rebuilt on dev's inline <think> splitter: reconciliation
sees only answer text; reasoning that arrives behind a held block is queued in
place (with a heartbeat) so order is kept and the duplicate is not exposed
early; buffered responses replay through the same buffer so both paths share
one rule set. The adapter glue lives in serialized-tool-call-content.ts to stay
under the file-size ratchet. #5548's unrelated codex/home.ts import-cycle,
WSL test, and service test edits are not carried.

Co-authored-by: Vadevious <56196048+Vadevious@users.noreply.github.com>

---------

Co-authored-by: Vadevious <56196048+Vadevious@users.noreply.github.com>
Record the verified preview and stable releases, the promoted candidate, exact CI run evidence, the dependency and routing fixes, and the remaining medium desktop dependency alerts.
…ement, goal helpers, Devin retry delays (#5675)

* docs(devlog): plan bundle lane E (responses and combo)

* fix(devin): accept generated approximate retry delays

Carries #5629. The shared retry-delay parser accepts the generated
"retry after ~180s" approximation marker after Retry-After, and the bounded
Devin replay re-evaluates the delay on every attempt within the existing
cumulative ceilings.

Folded review fixes: a repeated approximation marker ("~1 minute ~30
seconds") now rejects the hint instead of silently shortening it to the first
component, and the cloud-direct comment no longer claims the marker blocks
re-parsing.

Supersedes #5629.

Co-authored-by: Epinephrine <27862058+luvs01@users.noreply.github.com>

* fix(responses): restore code-mode goal helpers

Carries #5659. Routed create_goal, get_goal and update_goal calls (bare or
with a provider-invented default. prefix) are accepted as nested helpers of a
genuinely declared code-mode exec and compiled to the matching
tools.<helper>(...) call instead of falling through to exec_command. A
genuinely declared bare goal tool keeps its identity, and a catalog that
declares neither the tool nor exec still fails closed.

Folded review fixes: the guard is asserted on the original unrestored wire
name, an unlisted helper-like name is proven not admitted, bare-goal
precedence is covered through full restoration, the authorization comments in
src/types/tools.ts name the goal helpers, and the codex integration guide
describes the repair.

Closes #5495. Supersedes #5659.

Co-authored-by: ingwannu <186453546+Ingwannu@users.noreply.github.com>

* fix(responses): stop combo failover once a request has spent its ambiguous replacement

Carries #5646. Once a request has spent its retryOnReset replacement, the
first send may already have run the turn, so a replacement that answers 200
and then fails with zero output must not be sent again. RequestExecutionBudget
now reports ambiguousResendSpent from the one shared grant; combo failover
stops when it is spent and settles the answer with the shared
settleOperatorReplacement rule (a resendable status becomes the replay
refusal, anything else keeps its status with the non-replayable marker). On
the direct path the streamed opaque-blob rebuild is skipped once the grant is
spent. Carried before #5633 so its WebSocket replacement row is never exposed
to the third-send gap.

Supersedes #5646.

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>

* fix(responses): let retryOnReset replace a Codex WebSocket send that died unanswered

Carries #5633. A Codex WebSocket that opens and then closes or errors under
its create frame before any Responses event is the same unknown state as an
HTTP connection that resets before its head. For a provider that opted into
retryOnReset, the request-resend gate may now spend the request's single
replacement on it (one replacement per logical request, self-contained body
only). The exchange records the stage it reached; silence keeps its 504 and a
drop after a relayed event keeps its errored 200. Providers that have not
opted in are unchanged.

Carried after #5646, so the WebSocket replacement row inherits the spent-grant
stop. Folded review fixes: the duplicate settleOperatorReplacement import the
pair merge produced is removed, and responses-failover.md states the 2xx
replacement contract once as settled for all three replacement rows.

Supersedes #5633.

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>

* fix(combo): fail over undeclared zero-output tools

Carries #5489 (net diff; its upstream/dev merge commit is dropped). When a
runTurn adapter's first meaningful event in a combo attempt is a tool call the
current request did not declare, the existing fail-closed refusal is projected
as a pre-commit 502 so the combo can hop to the next target with the same tool
catalog. Chat Completions and Anthropic Messages inbound requests keep their
existing behaviour.

Folded review fix: the non-streaming path now applies the same boundary as the
streaming preflight. An undeclared tool call after a replay-unsafe heartbeat
(an adapter-side effect already ran) keeps the refusal on that child instead of
sending the turn to another target. New streaming and non-streaming cases prove
exactly one dispatch; the non-streaming one fails without the gate. The combos
guide gains the hop row in every locale and responses-failover.md records the
runTurn boundary.

Related to #5407 (covers its Responses path only; the reported Claude Code
Anthropic Messages path is unchanged). Supersedes #5489.

Co-authored-by: Yu Zhang <34849476+AaronZ345@users.noreply.github.com>

* fix(combo): keep failures after a replay-unsafe side effect on their child

Found by the lane's adversarial review of the carried #5646/#5489 changes.

- A runTurn adapter that emits a replay-unsafe heartbeat (it already ran a
  local side effect, as Cursor does) and then errors or ends empty before any
  output returned a plain 502, so a combo sent the turn to the next target and
  could repeat the side effect. Streaming and non-streaming paths now mark that
  502 non-replayable, and the combo stops on the child. This predates the
  carried commits; it sits on the same boundary structure/runtime.md states.
- A scope derived from a shape-compatible budget that implements
  claimAmbiguousResend but not ambiguousResendSpent reported "not spent" after
  it claimed the grant, which would let a combo hop on a zero-output 200 from
  the replacement (a third send). Grants claimed through the bridge are now
  latched per bridged parent and visible to every sibling scope.

Both are covered by new tests that fail without the fix.

* fix(responses): let a WebSocket replacement that resets use a second grant

Review finding on #5675. With retryOnReset.replacements set to 2, a dead
Codex WebSocket spends the first grant on its HTTP replacement; if that
replacement resets before its head, the WebSocket row settled it as the
replay refusal at once, so the configured second replacement was never
reachable. The reset is the pre-header row again, so the row now asks the
same gate (and the send budget) once more and resends only when a grant
remains; with the default of one it still settles as the refusal. The loop is
bounded by the request's finite allowance.

---------

Co-authored-by: Epinephrine <27862058+luvs01@users.noreply.github.com>
Co-authored-by: ingwannu <186453546+Ingwannu@users.noreply.github.com>
Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>
Co-authored-by: Yu Zhang <34849476+AaronZ345@users.noreply.github.com>
…403 as content_filter, tool-result echo filter (#5676)

* fix(xai): drop penalties for the reasoning models that reject them

xAI documents that presencePenalty and frequencyPenalty cannot be used with
reasoning models, and grok-4.7 answers 400 invalid-argument when either is
sent. noPenaltyModels already exists end to end; the xAI entry never seeded
it. Seed the documented reasoning ids so the openai-chat adapter and the Chat
passthrough omit both penalties; non-reasoning ids keep caller penalties.
Document the seed in structure/providers/xai-grok.md and the provider
configuration reference in every locale.

Carries #5668.

Co-authored-by: sh940701 <100397903+sh940701@users.noreply.github.com>

* fix(xai): drop stop for the reasoning models that reject it

xAI reasoning models reject stop with 400 invalid-argument ("Model grok-4.x
does not support parameter stop."). Claude Code auto-mode always sends
stop_sequences, and forwarding them as stop makes its safety classifier mark
Grok temporarily unavailable, so every Edit/Write/Bash is refused.

Add noStopModels next to noTemperatureModels/noTopPModels (provider config,
registry, derive fill, resolved-model policy, routedProviderConfig, OAuth
preset reconcile and login copy, and an editor row in
PROVIDER_CONFIG_FIELD_POLICY with the same shape as its siblings) and seed the
documented xAI reasoning ids. The openai-chat adapter and Chat passthrough omit
stop for them. The Responses passthrough drops stop and the penalties for
listed models as well (stripRejectedSamplingParams), because
grok-4.20-multi-agent-0309 has only the Responses wire and Claude inbound
translates stop_sequences into a Responses stop. Non-reasoning ids keep caller
stop and penalties.

Carries #5669 (which replaced #5280), plus the Responses-wire coverage and the
docs placement the review asked for.

Co-authored-by: sh940701 <100397903+sh940701@users.noreply.github.com>

* fix(xai): surface model policy 403 as a completed content_filter turn

xAI sometimes refuses a turn with HTTP 403 and "I can't help with that
request." Codex treats that as a transport failure, so the user message is
never recorded and retries loop, while a new thread on the same account works.

isUpstreamPolicyRefusal allowlists the exact normalized refusal sentences
after unwrapping JSON and "Provider error 403:" bodies. On a non-combo
Responses request, rewriteUpstreamPolicyRefusal returns an HTTP 200 Responses
incomplete/content_filter payload, JSON or SSE, on both the adapter path and
the native Responses passthrough; a streamed rewrite keeps the turn admission
lease until the body is read. Combo attempts keep the original 403 so failover
still works. Subscription, credit, entitlement and model-access 403s stay
errors; the xAI plan and credit cues guard only the refusal matcher, so the
global subscription classifier and status inference are unchanged.

Document the mapping in the proxy-formats and combos guides for every locale,
and the delivery and lease contract in structure/.

Carries #5667 (which replaced #5279). Refs #5277.

Co-authored-by: sh940701 <100397903+sh940701@users.noreply.github.com>

* fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking

grok-4.6 sometimes ends a turn by pasting a replayed [Tool Result] /
[tool_result] envelope after its prose. On Cursor the prefix sniffer never saw
a mid-turn paste, and Codex Desktop restoring the pre-remint conversation id
without a thread owner resumed the poisoned conversation. On xAI the Responses
SSE was relayed verbatim, so the paste was stored as assistant text.

One line-aware filter (src/lib/tool-envelope-echo-filter.ts) now runs on
Cursor text deltas and xAI Responses output_text deltas. It holds back only a
suffix that could still become a marker, so a marker split across deltas
cannot leak its prefix, releases prose as soon as it diverges, drops a
confirmed marker and its tail, and flushes harmless partial text at the end.
output_text.done, response.completed, JSON bodies and the xAI continuation
snapshot used for previous_response_id all carry the sanitized text.

Cursor remembers restored-id -> reminted-id rewrites in a map keyed by a
hashed credential scope, bounded to 2,048 entries with a one-hour expiry, so
an id can never be redirected across credentials. The echo-remint budget
follows the original conversation across remints, so a missing or changing
thread owner no longer bypasses or resets it.

Carries #5098, rebuilt on current dev with the split-marker, remint-scope,
credential-scope and snapshot defects from its review fixed. Refs #4874.

Co-authored-by: MerryEcho <126861868+MerryEcho@users.noreply.github.com>

---------

Co-authored-by: sh940701 <100397903+sh940701@users.noreply.github.com>
Co-authored-by: MerryEcho <126861868+MerryEcho@users.noreply.github.com>
…robe ceilings, hidden autostart, mise updates, Linux packaged E2E (#5682)

* fix(desktop): ad-hoc sign the bun sidecar on macOS after prepare

Bun's linker-signed standalone output is killed by macOS page validation
(CODESIGNING "Invalid Page"), so the bundled ocx sidecar never ran and the
desktop app stayed in "resolving". prepare-sidecar now reseals the copied
sidecar with an ad-hoc signature, but only when a macOS host prepares a
bun-darwin-* target, through the absolute /usr/bin/codesign; a failed or
unlaunchable codesign stops preparation. The decision and the spawn
boundary live in desktop/scripts/sidecar-signing.ts so they are tested
without running codesign.

Carries #5559.

Co-authored-by: agentHits <140916359+agentHits@users.noreply.github.com>

* fix(cli): warn about state loss before and after codex-restart

ocx system codex-restart fully quits and relaunches the Codex desktop app,
which can discard unsaved composer drafts, model-picker selections, and
pending approval prompts. The missing --yes error, the confirmed human
output, the capability metadata, the generated skill surface, and the
runtime structure doc now name that concrete loss. The restart request,
the --yes gate, and the JSON payload are unchanged.

Carries #5488. Refs #4761 (the warning slice only; restart scope is
unchanged).

Co-authored-by: Yu Zhang <34849476+AaronZ345@users.noreply.github.com>

* feat(server): OCX_PROBE_TIMEOUT_MS raises the liveness probe ceilings

On hosts where a content filter or EDR network extension adds a fixed cost
to every loopback connect, the shipped 750 ms probe expires before a
healthy proxy answers and every CLI liveness consumer reports it down.
OCX_PROBE_TIMEOUT_MS (whole milliseconds, 1 to 30000) raises the ceilings
on such hosts.

The override only raises: the 750 ms shared default and the 1500 ms
stop/start ownership budgets keep their floors, so a small value can never
shorten the budgets that prevent a duplicate proxy. Values above 30 s are
ignored so the single-shot stop deadline stays bounded (at most about 90 s).
The wiring tests read the constants in child processes, so no other test
file can observe an override. The CLI reference in all eight locales and
structure/ops/service-and-sidecars.md describe the setting.

Carries #5409 with the floor and ceiling fixed during the carry.

Co-authored-by: Kinso <5144108+kinsolee@users.noreply.github.com>

* perf(desktop): keep a hidden login launch on the startup surface

A login launch that starts hidden behind a usable tray no longer loads the
full dashboard after Ready. It keeps the small bundled startup page, and the
tray's Open Dashboard, a second ordinary launch, and the shell's open command
all go through startup::open_dashboard, which performs the run's single
navigation before showing the window. Manual launches and visible no-tray
launches keep eager navigation.

Two gaps in the original change are closed here. An open that arrives during
startup is recorded before progress is read, and finish reads it after
recording Ready, so whichever side runs second navigates. A WebView that
refuses the navigation script gives the one-shot claim back, so the next
open retries. Both reset with each run. Rust tests cover the first,
repeated, refused, and in-flight opens; the desktop guide in all eight
locales, structure/desktop-shell.md, and ADR-5494 describe the behavior.

Carries #5498. Refs #5493 (hidden-autostart deferral).

Co-authored-by: ingwannu <186453546+Ingwannu@users.noreply.github.com>

* fix(update): respect mise-owned installations

An opencodex package installed by mise was updated by npm self-update
inside mise's tree, behind mise's back. Install detection now recognises a
mise install from the adjacent .mise.backend.toml (tool alias plus the
canonical npm:@bitkyc08/opencodex backend) on both the lexical and the
resolved package path, reports installer "mise", and refuses mutation
with "mise upgrade <alias>" before any proxy stop, package write, or
worker creation: in the Node launcher, ocx update, the dashboard update
check and worker, and the sidebar badge. Unreadable or contradictory
metadata on either path fails closed without inventing a tool name. The
dashboard hides the command chip when there is no verified command, and
the lifecycle reference in all eight locales and all ten GUI catalogs
describe the behaviour.

Changes made while carrying it onto current dev:
- ported onto the update ownership transaction and the package-tree
  restart guard that landed after the PR's base;
- two verified owners whose tool roots differ only by a symlinked
  ancestor (macOS /var -> /private/var) are compared by canonical
  directory, so a real install behind a symlinked data directory is not
  reported as contradictory;
- the launcher refusal test now runs on Windows too (junction plus
  npm.cmd), proves the fake npm never runs, and covers contradictory
  metadata;
- the structure note moved to structure/ops/service-and-sidecars.md to
  keep structure/runtime.md within its line budget.

Carries #5316.

Co-authored-by: Gary Sassano <10464497+garysassano@users.noreply.github.com>

* test(desktop): add the Linux packaged-shell E2E driver

desktop/scripts/linux-packaged-e2e.ts boots the real AppImage and deb
payloads under a private Xvfb, Openbox and D-Bus session with fresh HOME,
XDG, CODEX_HOME and OPENCODEX_HOME roots and a reserved loopback port,
then requires a visible OpenCodex window, the bundled sidecar's matching
/healthz identity, port and version, and a clean drain after the only
window closes. Its report records readiness time and process-tree RSS as
evidence, not as budgets. Release asset collection accepts an explicit
isolated bundle root, and the AppImage patchelf wrapper follows the active
CARGO_TARGET_DIR so each Linux format can build in its own Cargo target.

Changes made while carrying it:
- the window is closed through the window manager (wmctrl -i -c, the
  EWMH close request a close button sends) instead of xdotool windowclose,
  which destroys the X window and can end the app without Tauri's
  close/drain path; the app must then exit on its own with code 0 and no
  signal, which is asserted and recorded in the report;
- verify-linux-sidecar.sh takes the staged AppImage directory as an
  optional argument, keeping the local default path;
- workflow wiring and the tests that read workflow files are in the
  following commit.

Carries #5502 (driver, scripts, docs). Refs #5493.

Co-authored-by: ingwannu <186453546+Ingwannu@users.noreply.github.com>

* ci(desktop): run the Linux packaged-shell E2E and isolate Linux release formats

CI: a new desktop scope (desktop/, gui/, src/, the standalone build
scripts, package.json, bun.lock and ci.yml itself) selects desktop-shell
alongside the native scope. When selected, the job builds the dashboard
and the bundled sidecar, builds the AppImage and the deb in separate Cargo
targets with updater artifacts disabled, stages them read-only, and runs
the packaged-shell E2E under dbus-run-session, xvfb-run and Openbox. The
report is uploaded with a SHA-pinned upload-artifact. The workflow keeps
contents: read, uses no secrets, and installs no package into the runner.
The aggregate gate derives the widened desktop-shell expectation the same
way the job does.

Release: on Linux, each format is built in its own CARGO_TARGET_DIR, staged
read-only, and collected from that staged root; the existing job-scoped
signing inputs are unchanged.

Changes made while carrying it:
- current dev's scope step no longer handles a privacy output; only the
  desktop output was added to it and to the aggregate;
- the Linux sidecar verifier moved after the isolated AppImage build and
  staging, and verifies the staged AppImage directory; before, it would
  have run before any Linux bundle existed in the default target;
- wmctrl is installed for the window-manager close request;
- the scope and aggregate tests that landed on dev after the PR's base
  now model the desktop output, and a new test file carries the CI wiring
  assertions.

Carries #5502 (workflow part). Refs #5493.

Co-authored-by: ingwannu <186453546+Ingwannu@users.noreply.github.com>

---------

Co-authored-by: agentHits <140916359+agentHits@users.noreply.github.com>
Co-authored-by: Yu Zhang <34849476+AaronZ345@users.noreply.github.com>
Co-authored-by: Kinso <5144108+kinsolee@users.noreply.github.com>
Co-authored-by: ingwannu <186453546+Ingwannu@users.noreply.github.com>
Co-authored-by: Gary Sassano <10464497+garysassano@users.noreply.github.com>
…riptions, launchd levers, passthrough tool ids (#5678)

* test(claude): cover bounded skill marker paths and document pass-through

Carries #5606. Adds the exact 4,096/4,097 UTF-16 code unit boundary cases for
POSIX and Windows skill directory markers and a long newline-free carrier, and
documents that a longer directory line is sent unchanged. The seven translated
Claude Code guides now state the same pass-through rule as the English guide.

Supersedes #5606.

Co-authored-by: Epinephrine <27862058+luvs01@users.noreply.github.com>

* fix(system-env): refresh and drop the launchd levers opencodex owns

Carries #5622. A lever opencodex already tracks as injected is refreshed instead
of skipped, a tracked lever the current config no longer produces is unset, and
PUT /api/claude-code reconciles on every model slot and lever field, not only
systemEnv and authMode. A launchd value the user set before injection is never
touched. The management API structure note records the PUT reconciliation.

Supersedes #5622.

Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>

* feat(claude): describe routed models instead of "From gateway"

Carries #5621. Readable Claude Code /v1/models rows carry a description naming
the native model or provider/model they route to, which Claude Code 2.1.257 and
later shows in the picker; the 1M copy keeps it and a Fast sibling appends
" · Fast". The gateway-model cache preserves string descriptions. The Claude
Desktop structure note records the picker description contract.

Supersedes #5621.

Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>

* fix(claude): keep routed model windows without disabling compact

Carries #5665. Claude Code aliases are minted as ocx-claude-/ocx-claude2- so the
picker keeps them while Claude Code applies CLAUDE_CODE_MAX_CONTEXT_TOKENS
without DISABLE_COMPACT; saved claude-ocx-/claude-ocx2- ids keep decoding.
maxContextTokens now injects only the window. The gateway cache mirrors the
picker's contains-claude rule and keeps #5621's descriptions.

Folded review fixes: native fallback recognizes the current prefixes; the
context-window map keeps registering the legacy spellings at the same window;
no compact lever is ever derived from maxContextTokens (pinned for values
outside the 100k-1M compact range); the tracked DISABLE_COMPACT from older
releases is removed by the system-env produced-key sweep instead of a one-off
cleanup; the Claude Desktop structure note records the alias and env contract.

Supersedes #5665.

Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>

* fix(claude): sanitize tool_use ids on native Anthropic passthrough

Carries #5628. The native passthrough bypasses the Anthropic adapter, so tool
call ids minted by routed models (Devin's Bash:0#<hex>) reached
api.anthropic.com verbatim and 400ed. The request-scoped allocator now rewrites
non-conforming and overlength ids, keeps call/result pairing, and leaves
conforming ids byte-identical.

Folded review fixes: an empty id fails locally with a 400 before the upstream
fetch instead of being forwarded; regressions cover the empty id, an overlength
id and a collision with an existing valid id; the Claude Desktop structure note
and the Claude Code guide in all eight languages describe the id rewrite.

Supersedes #5628.

Co-authored-by: wuwei <27188611+Haven2026@users.noreply.github.com>

* fix(claude): keep legacy slot selectors and hand-edited DISABLE_COMPACT safe on upgrade

Folds the bundle's adversarial review into the #5665 and #5622 carries.

A legacy claude-ocx-/claude-ocx2- selector configured in an OpenCodex model slot
is emitted in its current ocx-claude spelling on every env path. The route is
identical, and Claude Code then applies the configured window instead of
falling back to 200k accounting now that DISABLE_COMPACT is no longer paired
with maxContextTokens. A selection saved by Claude Code's own picker stays a
documented re-pick.

The system-env sweep removes a tracked DISABLE_COMPACT only while it still holds
the 1 older releases injected; a value the user changed by hand is released
from tracking without being deleted.

Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>

* fix(claude): keep legacy picker selectors on connected clients and Fable passthrough

Folds the Codex and CodeRabbit review of the bundle. A legacy
claude-ocx-native--claude-fable-* picker value compared only against the new
ocx-claude spelling and fell off the native Anthropic passthrough; both
spellings are accepted again, with the legacy value back in the endpoint test.
The connected-client context-window map registers the legacy route and native
spellings like the local map does, so a saved legacy selector keeps its [1m]
subagent marker on a connected hub.

Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>

---------

Co-authored-by: Epinephrine <27862058+luvs01@users.noreply.github.com>
Co-authored-by: terin <100397903+sh940701@users.noreply.github.com>
Co-authored-by: wuwei <27188611+Haven2026@users.noreply.github.com>
…egration status, quota locks, discovery snapshots (#5680)

* fix(codex): keep a fresh local Codex home before config.toml exists (#5441)

On WSL an unset CODEX_HOME switched to a discovered Windows Desktop home
whenever ~/.codex/config.toml was missing, even when the local ~/.codex
directory already existed on a fresh install. Keep the local home when it is
a directory; only an absent path or a non-directory lets discovery pick the
Windows home, and an unexpected stat failure keeps the local home rather than
switching. Structure and the Codex integration guide (all locales) now
describe directory presence instead of config.toml presence.

Carries #5441.

Co-authored-by: Lee Sang Gyu <217872453+lee3Q@users.noreply.github.com>

* fix(codex): treat an unchanged sync-cache as success (#5594)

ocx sync-cache exited 1 when models_cache.json was already current, because
an unchanged cache and a failed rewrite both surfaced as false. The cache
invalidation now reports written / unchanged / missing_catalog /
desired_disabled / failed; the CLI exits 0 for an unchanged cache, restarts
Codex only after a real write, and names the skip in --json.

On top of #5594: the human path no longer prints the integration-OFF
explanation before the real outcome (an explicit sync-cache refreshes
regardless of the toggle), the skip-count comment names all three benign
skips, and the composed acceptance test covers the human output and derives
the expected skip from whether an OFF sync left a catalog behind.

Carries #5594.

Co-authored-by: Gary Sassano <10464497+garysassano@users.noreply.github.com>

* fix(codex): refresh persisted integration intent in status (#5588)

GET /api/native-integrations derived the Codex switch from the server's
startup config snapshot, so a completed Codex toggle did not show until the
proxy restarted. The status read now takes per-client intent from persisted
configuration.

On top of #5588: the same fresh intent is used for the Grok and Claude
Desktop rows, whose toggles also persist independently (every other field
still comes from the snapshot); a Codex OFF toggle whose native restore did
not complete keeps the row unsafe on later reads instead of deriving absent
from intent; tests cover the stale-snapshot read, an off-then-on round trip,
and a failed restore followed by a status read.

Carries #5588.

Co-authored-by: Gary Sassano <10464497+garysassano@users.noreply.github.com>

* fix(codex): retire stale short-window main-account hard locks (#5620)

The main-account hard lock kept an old 5h reading forever once an account
moved to weekly or monthly windows: policy merging retained omitted blocking
short usage, and that stale tuple outranked a fresh weekly reading. A single
fresh WHAM response now replaces the short tuple when its primary window is
explicitly at least 24h and the secondary and tertiary windows are explicit
null or also long. The replacement proof is per observation and never
persisted; the current window still blocks at 99%.

On top of #5620: a non-null long auxiliary window only counts as proof when
it carries a valid used_percent, since unknown usage must never release a
block; regression covers a monthly primary with a long secondary or tertiary
window that omits used_percent.

The policy trusts one reported topology rather than repeated observations;
that trade-off is documented in structure/providers/openai-tiers.md.

Carries #5620.

Co-authored-by: 정우철 <86232509+oocheol@users.noreply.github.com>

* fix(catalog): bind model discovery's token and destination to one snapshot (#5647)

The provider connection probe resolved a token and then rebuilt its URL from
the live credential store, and a refreshing catalog gather captured its URL
before resolving a refreshed token. A Copilot account switch, or a refresh
that moves an account's API host, could therefore pair one account's bearer
with another account's origin. Discovery now rebuilds the send from the same
snapshot that supplied the token, keeps separate flights per stored origin,
probes Devin at the snapshot's tenant address, and a key row never borrows a
stored OAuth account's origin.

On top of #5647: negative tests pin that a snapshot without an API host falls
back only to static configuration validated against the vendor allowlist or
the vendor default, never to the live store (Copilot account switch during
refresh; Devin row with a non-allowlisted configured base), and
structure/catalog.md states that rule.

Carries #5647.

Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>

* fix(codex): discover the WSL Desktop runtime under CODEX_HOME/bin/wsl (#5635)

Windows Codex Desktop in WSL app-server mode ships its Linux Codex binary
under the effective Codex home as bin/wsl/<version-hash>/codex. An Ubuntu
service whose PATH has no codex resolved no runtime, so the v2 transition
failed with "Executable not found in $PATH".

On Linux, runtime discovery now enumerates the direct hash-directory
children of <effective CODEX_HOME>/bin/wsl newest first, after an explicit
runtime, PATH and the ordinary install locations, and probes them through the
existing isolated --version seam. The list is re-read on every resolve, so a
Desktop update that replaces the hash directory is rediscovered instead of
trusted from a remembered path, and CODEX_HOME joins the process memo key.

Regressions: absent PATH, replaced hash directory, newest hash first,
explicit pin wins, PATH wins, unreadable bin/wsl, and no enumeration on
macOS.

Closes #5635.

* fix(catalog): restore a native row's multi-agent pin after a forced mode (#5636)

Returning from forced v1 to default left newer native rows (gpt-6-astra,
gpt-6-luna) pinned to v1 when the pristine catalog backup predated them:
default mode preserves a live pin that the baseline does not mention, and
after a forced pass nothing distinguished the forced stamp from a genuine
pin.

A forced v1/v2 pass now records the row's pre-override value once, as
opencodex_multi_agent_version_origin (a string pin or null), and repeated
forced passes never replace it. Default mode consumes the record: pristine
baseline and native pins still win, routed-row normalization is unchanged,
and only a native row the baseline predates is restored from the record.
Rows written before the record existed keep the non-destructive read.

Closes #5636.

* fix(codex): bootstrap a missing config.toml in an existing Codex home (#5422)

A fresh Codex install can have its home directory but no config.toml yet:
Codex writes it lazily, and an authless Desktop user who never signs in to
OpenAI may never get one. Injection treated that as "Codex config not found
... Is Codex installed?" and blocked third-party provider onboarding.

When the resolved Codex home is a directory and config.toml is missing, an
applying injection now creates an empty config.toml exclusively (an existing
file is never overwritten) and continues; a validate-only preflight reasons
about that empty file and writes nothing. A missing home directory is still
refused, now with instructions to start Codex once or set CODEX_HOME, so a
wrong home stays distinguishable from an uninitialized one.

The client-connect preflight rollback scenario used a missing config.toml
as its fault; it now uses a deterministic injection refusal (ambiguous
managed sub-agent markers) instead.

Closes #5422.

* fix(clients): accept a relocated Aside root behind a symlinked ~/.aside (#5648)

A user who moved ~/.aside (for example to an external volume) and left a
symlink behind could not load Aside profiles: the reader refused the root
because the path itself was a link, although Aside follows it.

asideHomeDir now canonicalizes only that top-level alias, once, and only
onto a directory. Every boundary below the canonical root is unchanged: u/,
account directories and models.json still refuse links, and a ~/.aside link
to a regular file is still refused. Regressions cover the relocated root,
linked u/ and account directories and a linked catalog under it.

Closes #5648.

---------

Co-authored-by: Lee Sang Gyu <217872453+lee3Q@users.noreply.github.com>
Co-authored-by: Gary Sassano <10464497+garysassano@users.noreply.github.com>
Co-authored-by: 정우철 <86232509+oocheol@users.noreply.github.com>
Co-authored-by: Fred Amartey <43480311+FredAmartey@users.noreply.github.com>
…ports them (#5685)

On Windows two update-mise tests failed in a lane=all run (windows 7/9):
the detector reports installPath and toolRoot for a drive-letter or UNC
path with forward slashes, so the lexical and resolved candidates compare
in one spelling, while the fixture built its expectations with native
path.join (backslashes). Detection itself was correct: installer, tool,
backend and install boundary all matched, and the 8.3 RUNNER~1 prefix was
identical on both sides.

The fixture now spells its expected owner paths through reportedPath, and a
platform-independent test pins the reported spelling for backslash and
forward-slash Windows inputs, so a change to it fails on every OS instead
of only on the Windows shards.
* docs(devlog): plan first-party Claude Desktop Code tab model bindings

* feat(claude): first-party Desktop Code tab model bindings on the intercept ingress

* feat(gui): Code tab model bindings card for first-party Claude Desktop

* docs(claude): document first-party Code tab model bindings

* test(claude): stop the replay-scope adapter mock from recursing into itself

mock.module rewrites the live namespace, so the mock read its own resolveAdapter and froze any later test in the same process that dispatched a real adapter (the new intercept binding case). The binding case also uses a provider id no other suite shares.

* fix(gui): use the page model label for binding routes

* docs(devlog): record the live first-party binding proof

* test(gui): allowlist the picker-id placeholder as an identifier

* test(server): pin the intercept flag in the loopback policy source oracle
…ps (#5718)

The README led with three large download buttons and a long desktop section. npm install is the first command again; the desktop downloads are four npm-sized badges (macOS .dmg, Windows .msi, Linux .AppImage and .deb) in a collapsed block under it, and the Quick start desktop section is one short paragraph after the CLI install. The unused download SVGs are removed from assets and the npm files list. All seven locales are resynced.
…tion under the CLI install (#5719)

The four download chips under the npm command are no longer collapsed. The full Desktop app (beta) section (platform table, checksums, widget, local build) returns under Personal install (CLI) inside a collapsed block. All seven locales resynced.
* docs(devlog): plan the 260924 regression-risk fixes

* docs(devlog): note the wp1 re-walk

* fix(codex): keep a discovered Windows home when the local WSL ~/.codex holds no Codex state

#5441 made any local ~/.codex directory the Codex home on WSL, even when
config.toml is missing. A WSL user whose ~/.codex exists but holds no Codex
state, and who ran against the discovered Windows Codex home, was moved to
an empty local home on upgrade: auth and sessions disappeared and a sync
wrote a new local config.

The local home now wins only when Codex is already using it: config.toml,
auth.json, sessions or history.jsonl is present (an unexpected stat error
counts as present, so doubt never switches homes). #5441's fresh install
keeps its local home once Codex has logged in or run; a bare directory
falls back to Windows discovery as before #5441.

* fix(update): treat npm -g under a mise-managed Node as an npm install on Windows

On Windows, npm -g under a mise-managed Node installs OpenCodex directly
into <mise>/installs/node/<version>/node_modules. The mise ownership
walk then read Node's own .mise.backend.toml (short = "node", full =
"core:node") as contradictory OpenCodex metadata and refused ocx update
with metadata_inconsistent, although the install is plain npm.

That exact runtime record, with the package directly in the runtime's
global node_modules, now falls through to ordinary npm detection. Any
other backend or alias under a node tool root, a deeper nested layout,
unreadable metadata and every OpenCodex mismatch stay fail-closed. POSIX
is unaffected: its lib/node_modules layout never reaches the Node record.

* fix(xai,cursor): only a marker alone on its line is an echoed tool envelope

The shared tool-envelope echo filter from #5676 matched as soon as a line
started with a marker and dropped that line and everything after it. It
is armed on almost every agentic turn (input with tool calls or outputs,
or a previous_response_id continuation), so an answer line such as
"[Tool Result] shows the build passed." silently truncated the rest of
the reply on xAI and Cursor. The Cursor history stripper had been widened
to the same prefix rule and removed such prose from replayed history.

The envelope OpenCodex replays is a marker alone on its line. A result,
error or call marker now counts only when it is the whole line (trailing
whitespace and CR allowed), decided when the line completes; the end of
the stream follows the same rule, and a bare truncated marker still
counts. The "[Tool call:" line keeps its prefix rule because a call echo
wraps when its arguments do. The Cursor replay stripper uses the same
isWholeLineEchoMarker. Fenced markers, the xAI Responses JSON path and
the stored continuation snapshot follow from the shared filter.

* fix(openai-chat): bound the streaming hold of an unmatched serialized tool call

#5548 holds everything after a bare <tool_call><function=...> opening
until the stream ends, so a model that writes such a block and then keeps
answering without a structured call delivered the rest of its answer only
at the end of the turn, and could approach the translator budget.

Streaming content now goes through ingestStreaming. Once a closed block
is followed by more than 8 KiB of prose with no block open after it, or
held text plus queued events would pass 4 MiB (checked before the next
delta is retained), everything held is released in order with nothing
suppressed. A duplicated block is the tail of the content, so matching
blocks followed by their structured call are still removed; past a bound
the stream prefers delivery over suppression, the behaviour before
#5548. Buffered responses keep the unbounded ingest because their
structured calls are already known. openai-chat.ts keeps its line count.

* fix(openai-chat): close the streaming hold bound's single-delta and queued-event paths

A delta that opens a block and already passes 4 MiB is no longer retained, an oversized delta after an open block is delivered after the held text, and queued non-text events count toward the same bound. The fresh WSL home test now models a fresh install (auth.json present, config.toml absent) instead of a mock that reported every path present. Review decisions are recorded in the plan.

* test: place the whole-line echo test in the adapters domain its name seeds
#5721)

#5720 declared the Codex-state list as a module-level const below
defaultCodexHome. The storage workers reach defaultCodexHome during
module initialisation through an import cycle, and with a ~/.codex
directory present (every Windows CI runner, and most user machines) the
call read the const before it was initialised: ReferenceError in the
trash-restore and policy-run workers. The list is now local to the
function.

The CodeBuddy compiled-MCP test also removes its temp directory with the
shared retrying helper: Windows keeps the compiled ocx executable locked
briefly after the process exits, and a plain rmSync failed with EBUSY.
Cursor Connect rejects claude-opus-5-5-thinking-* with not_found
because the live GetUsableModels roster exposes flat effort-suffixed
ids (claude-opus-5-5-{low..max} and -fast) without a thinking infix.

Set defaultVariant to regular and update effort mapping to match the
live Cursor wire specification. Fixes #5722.
* fix(anthropic): degrade Opus 5.5 forced tool choice safely

* test(anthropic): preserve Opus 5.5 non-forced tool choices

* docs(anthropic): record Opus 5.5 disabled-thinking probe
* fix(usage): price Cursor Claude Fast variants

* test(usage): pin Cursor Fast provenance

* test(usage): reject unsupported Cursor Fast ladders
…op picker mode (#5728)

* docs(devlog): plan Claude Desktop gateway default, first-party risk warning and picker mode

* docs(devlog): close the picker-mode roadmap cycle

* docs(devlog): fold the wp2 audit into the gateway-default plan

* feat(claude-desktop): default Desktop to gateway and flag first-party account risk

Gateway (3P) is now the default Desktop mode. First-party stays available by explicit choice, and pre-field installs keep what they run: a selected owned gateway row or apply marker keeps gateway, owned first-party env keeps first-party. Foreign proxy env is never read as first-party.

Every first-party surface (CLI apply and help, POST /api/claude-desktop/apply, status, native toggle) carries one account-suspension risk notice from src/claude/desktop-risk.ts. The /api/sync writer and the roster auto-apply never write a gateway profile behind a first-party Desktop, rechecked after discovery.

* feat(gui): mark gateway as the Desktop default and show the first-party account risk

The mode picker badges gateway as default, falls back to gateway before /status answers, and shows the account-risk note whenever first-party is selected or its env is still applied. Copy is in all ten locales.

* docs(claude-desktop): document the gateway default and the first-party account risk

The Claude Code guide in all eight locales and the structure contracts now describe gateway as the default, first-party as an explicit opt-in with an account-risk caution, and the guards that keep sync and roster updates from overwriting a first-party Desktop.

* docs(devlog): fold the wp3 audit into the picker core plan

* docs(devlog): fold the wp3 round-2 audit

* feat(claude-intercept): add the name-constrained picker CA and keychain trust checks

The picker CA lives under <configDir>/claude-picker/ with a 0600 key and a critical nameConstraints extension that permits only claude.ai; a persisted CA without it is regenerated on reload. Trust is inspected, added and removed through an injectable macOS security runner: trusted needs the current CA's SHA-1 in the login keychain and a passing verify-cert for the claude.ai leaf. The intercept CA is unchanged.

* feat(claude-intercept): relay claude.ai and add opencodex routes to the Code picker bootstrap

A loopback node:https HTTP/1.1 terminator relays claude.ai with upstream certificate verification, raw headers, streamed bodies and WebSocket upgrades. Only the bootstrap response is rewritten: its code surface gains one cloned entry per route, under encoded and decoded caps, and any failure or overflow passes the original bytes through unchanged.

* feat(claude-intercept): picker model snapshot, per-connection tunnel choice and the picker preference

Picker entries mirror the gateway's rendered Desktop profile with opencodex aliases, served from a snapshot persisted to claude-picker/models.json. The CONNECT proxy takes an optional per-connection selectTunnel; async decisions hold the client until they settle and never dial for a client that left. claudeCode.intercept.picker is the new preference (absent = on).

* feat(claude-intercept): picker runtime on a dedicated Desktop egress proxy

The picker runtime caches when claude.ai may be terminated (macOS, first-party, Desktop intent, preference, no disarm latch, listener up, CA trusted) and serves it to a second CONNECT proxy on the intercept port + 1, used only as Desktop's egress proxy. The Claude Code proxy keeps its behaviour and never consults the picker. Start failures release every bound socket.

* docs(devlog): record the dedicated Desktop egress proxy amendment

* docs(structure): move the picker contract into the Claude Desktop doc

runtime.md sits at its 600-line budget; it now links to the picker section in clients/claude-desktop.md.

* docs(devlog): fold the wp4 pre-audit into the picker activation plan

* docs(devlog): fold the wp4 round-2 audit

* feat(claude-desktop): own a picker egress profile in Desktop's config library

The opencodex-picker row is an owned standard row whose profile holds only egressProxyUrl, pointed at the dedicated picker CONNECT proxy. The previous selection lives in claude-picker/profile-state.json, never in Desktop's _meta.json; removal reselects it (or an owned standard row), and gateway writes and cleanup leave the row alone.

* feat(claude-desktop): one picker controller serializes enable, disable and mode transitions

Enable rechecks the persisted first-party mode, Desktop intent, preference and bound picker proxy before and after the keychain step, applies the egress profile and rearms the runtime; any refusal after trust it (or a CLI caller) added removes that trust. Disable disarms first, then removes the profile and the trust. With no controller, transitions run with offline ops that only clean up leftover artifacts.

* feat(server): turn picker mode on with first-party and off with gateway

GET/PUT /api/claude-desktop/picker drive the controller; status reports firstParty.picker. First-party apply and the native enable run their switch under the picker lock in today's order and then enable the picker unless claudeCode.intercept.picker is false; gateway apply, native disable, /api/sync and the roster auto-apply run under the same lock, and the gateway paths disable the picker first. The runtime creates the controller next to the picker runtime.

* feat(cli): ocx claude desktop picker on|off|status|trust

The CLI drives picker mode through the running server; trust runs the macOS keychain step in the terminal and lets the server compensate a refused enable. First-party apply delegates to the server on the local hub path. Durable-OFF reconciliation is async and turns the picker off.

* feat(gui): picker mode card on the Claude Desktop page

In first-party mode the page shows a picker card with a toggle, the state and next step from the controller's reason, the model count and the offline note, in all ten locales.

* docs(claude-desktop): document picker mode

The Claude Code guide in eight locales and the structure contracts describe picker mode: on by default in first-party on macOS, the one-time keychain step for a CA limited to claude.ai, the offline dependency, the commands and the dashboard card.

* docs(devlog): point the wp5 egress check at the picker proxy port

* fix(claude-desktop): keep picker trust while its profile is selected, report refusals, lock profile writes

Security review follow-ups. Disabling picker mode removes the CA's trust only after Desktop no longer selects the picker profile, so a failed metadata write never leaves Desktop pinned to a proxy whose certificate it rejects; untrust is a no-op when the current CA is not in the login keychain. PUT /api/claude-desktop/picker answers refusals with 409 and incomplete cleanup with 500, and the CLI exits non-zero for them. Picker profile apply and removal run under the client lifecycle and config mutation locks, like the gateway writer.

* feat(claude-intercept): log the picker bootstrap rewrite outcome

The service log now records, per bootstrap, whether the Code picker surface was rewritten and how many entries were added, or which piece was missing (selector config, code surface with its surface ids, template, routes, cap or decode). Only metadata is logged, never values.

* fix(claude-intercept): add picker routes to the Desktop Code tab's ccd surface

The Desktop Code tab reads the ccd surface of the bootstrap's model_selector_config and falls back to code only when ccd has no catalog, so routes added to code alone never showed. Routes now go into ccd and code; the remote ccr surface stays untouched because a remote session never reaches this machine's proxy. Found in the live Desktop proof.

* fix(claude-intercept): route Desktop's spawned Claude Code through the intercept on the egress proxy

Desktop hands its pinned egress proxy to the Claude Code processes it spawns, so a Code-tab turn with an opencodex route reached Anthropic unintercepted and failed as an unknown model. The egress proxy now chooses per client from the CONNECT head: without a browser User-Agent (Claude Code, trusting only the intercept CA) api.anthropic.com gets the intercept and claude.ai stays blind; with Chromium's User-Agent (the app, trusting the login keychain) the picker decides as before. Found in the live Desktop proof.

* fix(claude-desktop): ask for a Desktop restart only after the picker profile changed

Desktop reads its egress profile only at launch, so picker status reports restart_required only until Desktop has fetched a bootstrap after this process changed the profile. A plain opencodex restart changes nothing Desktop reads and now reports active.

* fix(claude-intercept): cap single-read CONNECT heads and keep body values out of picker logs

Review follow-ups. A CONNECT head that arrives in one oversized read is refused like one spread across reads. The bootstrap outcome log names only known surface ids and counts the rest. The User-Agent tunnel choice is documented and tested as a routing hint: a faked or missing one reaches only what any local process already reaches and breaks only that client's TLS.

* test(claude-intercept): use a neutral marker for the surface-log test

* test(claude-desktop): expect the macOS-only reason in offline picker status off macOS
…#5727)

* feat(anthropic): keep Claude fast mode off until the provider opts in

Anthropic fast mode spends usage credits at 2x price. The anthropic and
anthropic-apikey registry entries now mark their Fast lane opt-in, and a new
providers.<name>.fastEnabled switch turns it on. While off, the models
publish no Fast toggle or --fast row and the proxy never sends speed.
The dashboard Models page gains an Off/On row on opt-in provider cards.
Cursor Fast and every other provider are unchanged.

* fix(providers): keep the Fast switch across a full provider save

The provider edit form never sends fastEnabled, so a POST overwrite dropped
an Anthropic Fast opt-in set from the Models page. Carry the live value when
the request omits it, like upstreamWebsocket.

* fix(gui): keep the Fast row on the confirmed value after a save

The row read its value only from the provider summary, so it showed the old
state until the catalog reload landed and a click on the stale option was
ignored. Hold the confirmed save until the summary moves. Also qualify the
structure note: the switch stops proxy-generated speed, while native
passthrough still forwards a caller's own speed.

* fix(gui): drop the Fast row override once the server confirms

Clear the saved value as soon as the provider summary moves off the value
the save started from, so a later change by another client is shown as-is.
Name the model-level Fast toggle in the structure note.
#5732)

The home-environment cases give every child a fresh fake HOME, and Bun keeps its
runtime transpiler cache under the HOME-derived cache directory, so each holder
re-transpiled the whole lock graph and the describe's warm-up paid for nothing.
On windows-latest those holders took 5-19 s against 1-4 s for the same child with
the ambient home, and "case 0" crossed INTERNAL_DEADLINE_MS twice in run
35953803435 after a new test file shifted it to the front of its batch.

Pin BUN_RUNTIME_TRANSPILER_CACHE_PATH to one per-process directory for the
warm-up and every child. The lock identity under test reads only HOME and
USERPROFILE, so no assertion changes.
The Desktop picker tests added in #5728 assert 0o600 on the profile, state and
model snapshot files. Windows reports 0o666 for any writable file, so
windows 3/9 and 4/9 failed on dev (ci.yml lane=all run 35957063545) with
"Expected: 384, Received: 438". Guard the three assertions the same way
claude-picker-ca.test.ts guards its key file.
…names excluded (#5731)

* fix(claude-intercept): trust the picker CA without a host policy string

Chromium skips keychain trust settings that carry a policy string, so the claude.ai-scoped trust left Claude Desktop rejecting the picker leaf while verify-cert reported it trusted. The CA's critical name constraints already limit it to claude.ai.

* fix(claude-intercept): exclude IP names from the picker CA and replace host-scoped trust

A DNS-only permitted subtree leaves the iPAddress form unconstrained, so a leaf
with an IP SAN signed by the picker CA would chain for any address. The picker
CA now also carries excludedSubtrees for every IPv4 and IPv6 address, and a
persisted CA without that exclusion is rotated on reload.

Trust added by the first build carried the claude.ai policy string, which
verify-cert honours and Chromium skips. inspectPickerTrust now reads the user
trust settings and reports such a CA as untrusted, so the trust step replaces
the setting instead of leaving Desktop on ERR_CERT_AUTHORITY_INVALID.

* fix(claude-intercept): report picker trust unknown when trust settings cannot be read

An unreadable trust-settings export could hide the host-scoped setting Chromium
skips, and arming on it cuts Desktop off from claude.ai. The inspection now
returns unknown, which never arms; the enable path re-adds trust and checks
again. Test fakes write an export with no picker entry.

* docs(devlog): show the IP exclusion in the picker CA name-constraints sketch
…ith a header newline (#5725)

* fix(openai-chat): read MiMo tool-call echoes without </function> or with a header newline

The Chat reconciler removed a duplicated <tool_call> block only in the
canonical <function=NAME>BODY</parameter></function> shape. MiMo also
echoes the block without </function>, and sometimes with a template
newline after the function header; both stayed on screen next to the
structured call that ran (#5724). The block pattern now accepts the
unclosed form after trying the closed one, and the body comparison
drops one leading newline, matching the Command Code reader's grammar.
Suppression still requires the name and body to agree with a structured
call, so mismatched markup stays visible.

* fix(openai-chat): scan serialized blocks linearly and record ADR-5724

Review follow-up. The closed/unclosed regex pair backtracked
quadratically on a long unterminated body and hid a closed body that
merely contained a literal <tool_call>. Blocks are now read by delimiter
scan: the first </tool_call> preceded by </function> closes the block,
and only when none appears before the next real block header does the
first </tool_call> close it. The decision moves to its own record,
ADR-5724; ADR-5548 is left as it was.

* fix(openai-chat): bound the block scan by line-start headers only

A body can carry a full literal header such as
text("<tool_call><function=exec>"). A separate bare block can only begin
at the start of a line, so the scan now stops only at a header there.

* fix(openai-chat): keep a closed block whose body has a line-start header

A line-start header only bounds an unclosed candidate. When no
</tool_call> appears before it, it is body text, and a closed
</function></tool_call> after it still ends the block.
…rm (#5737)

The desktop window never enabled page zoom. Tauri leaves zoom hotkeys off by
default, so WebView2 on Windows had its zoom control disabled and macOS/Linux
had no handler at all.

The main window now enables Tauri's zoom hotkeys. WebView2 zooms natively; on
macOS and Linux Tauri injects a keydown polyfill that calls set_webview_zoom.
The dashboard is served from the loopback proxy, a remote origin to Tauri, so a
new capability grants that one command to the main window for
http://127.0.0.1:* only. A test pins the capability's window, origin and
permission, and checks the pattern against the real dashboard URL.
…, #5714, #5704, #5707) (#5738)

* fix(claude): bound Responses user to 64 chars for long metadata.user_id

Claude Code sends metadata.user_id as a ~186-char JSON string. It was copied
verbatim into the Responses 'user' field, which Azure OpenAI and other
OpenAI-compatible backends cap at 64 chars, so every Claude Code request
routed to Azure failed with 400 "Invalid 'user': string too long".

Keep short ids as-is and send the SHA-256 hex digest (already computed for
prompt_cache_key) when the id exceeds 64 chars.

Fixes #5705

Co-authored-by: Giulio Leone <giulioleone097@gmail.com>

* Fix plaintext V2 SSE responses with missing content type

Co-authored-by: Jerry WANG <jerrywang@Jerrys-MacBook-Pro-2.local>

* fix(responses): exclude dropped chat reasoning from input admission

* test(admission): verify reasoning payload matches gate decisions

Co-authored-by: 정우철 <oocheol@naver.com>

* Allow HTTP upstream for canonical ChatGPT provider

An explicit upstreamWebsocket: false now routes streaming canonical ChatGPT turns over HTTP/SSE before sending. This gives operators a supported escape from intermittent post-send WebSocket closes without replaying ambiguous turns. The default remains WebSocket and native WS controls are unavailable when HTTP is selected.

Verified: focused Responses/provider suites, typecheck, structure check, privacy scan, docs build. Changed-area suite rerun pending.
Co-authored-by: kosta <kosta963@gmail.com>

* test(claude): pin exact user hash and the 64/65-char boundary

Refs #5705

Co-authored-by: Giulio Leone <giulioleone097@gmail.com>

* docs(architecture): attribute the admission fix to excluding unsent thinking

Split the preserved-reasoning statement from the refusal rationale in the English and Korean paragraphs, as review of #5714 asked.

Refs #5696

Co-authored-by: 정우철 <oocheol@naver.com>

* fix(anthropic): count ping events as upstream liveness

Anthropic streams may include any number of ping events. The adapter only turned SSE comments into heartbeats, so a long silent thinking phase that pinged was cut off at stallTimeoutSec with upstream_stall_timeout. Named and data-only ping records now yield the same heartbeat.

Refs #5707

* fix(management): report upstreamWebsocket as configured in GET /api/providers

The row coerced an unset value to false. After the canonical ChatGPT opt-out, unset means upstream WebSocket and false means HTTP/SSE, so a save built from the row could turn WebSocket off. The row now omits the key when it is unset.

Co-authored-by: kosta <kosta963@gmail.com>

* docs(providers): describe the canonical ChatGPT upstreamWebsocket opt-out

The reference row, its seven translations, and the provider type and schema comments still said the canonical ChatGPT transport ignores upstreamWebsocket. It now selects HTTP/SSE when set to false. The locale rows were also behind the English row on the first-party-only restriction; they are retranslated from it.

Co-authored-by: kosta <kosta963@gmail.com>

* fix(responses): bound the plaintext V2 SSE prefix probe by stallTimeoutSec

The carried probe read the first chunk of an unlabeled body with no deadline, before the passthrough stall guard is attached. An upstream that sent headers but no body held the request and its host lease until the client gave up, and a failed read escaped the classifier. Each probe read now races a per-read inactivity window and one total budget, both stallTimeoutSec, plus the client abort signal. Timeout, abort, and read errors cancel the reader and return the existing unsupported-content-type 502. Docs now scope the recovery to missing or unrecognized non-JSON content types.

Follow-up to #5683 review (maintainer, Codex, CodeRabbit).

Co-authored-by: Jerry WANG <jerrywang@Jerrys-MacBook-Pro-2.local>

---------

Co-authored-by: Giulio Leone <giulioleone097@gmail.com>
Co-authored-by: Jerry WANG <jerrywang@Jerrys-MacBook-Pro-2.local>
Co-authored-by: 정우철 <oocheol@naver.com>
Co-authored-by: kosta <kosta963@gmail.com>
* fix(bridge): fail closed when enforced tool catalog is absent

(cherry picked from commit 94c53f3)

* fix(bridge): retain unscoped null catalog compatibility

(cherry picked from commit 9e90829)

* test(bridge): assert nested tool refusal errors

(cherry picked from commit b06cc1f)
Co-authored-by: 정우철 <oocheol@naver.com>

* fix(combo): refuse first dispatch when send budget is exhausted

(cherry picked from commit 3f71a15)

* fix(combo): preserve classified 413 on denied later hop

(cherry picked from commit c50c42f)
Co-authored-by: 정우철 <oocheol@naver.com>

* fix(combo): cap explicit Retry-After cooldowns at one day

(cherry picked from commit c055671)

* docs(combo): align translated cooldown ceilings

(cherry picked from commit 11a8c4d)

* docs(combo): clarify cooldown contract and regression intent

(cherry picked from commit f70015c)
Co-authored-by: 정우철 <oocheol@naver.com>

* feat(combos): explicit last-resort cooldown policy for failover

A brief cooldown on a preferred target routes straight to whatever comes next
in the list — including a target the operator only ever wanted used in an
emergency. There is no way to say "this one is a last resort", so transient
cooldown state dispatches it.

`cooldownWaitPolicy: "before-last-resort"` plus `lastResort: true` on a target
makes selection try the normal targets first. If they are only cooling and the
earliest cooldown expires inside the combo's existing `waitForCooldownMs`
budget, the request waits for that instead of dispatching the last resort.

**The policy only ever defers, and that is the property the tests are built
around.** When no normal target can be reached — every one cooling past the
budget, already attempted, or ruled out by the caller — the last-resort target
is dispatched exactly as today. A policy that could withhold it would turn a
fallback into an outage, which is strictly worse than the premature routing it
prevents. Five tests cover that one way each: cooling past the budget,
excluded, ruled out by the caller's own predicate, a combo whose targets are
all last-resort, and a zero wait budget.

The deferral wait is scoped to normal targets. A short cooldown on the
last-resort target must not make the request sleep on behalf of the very target
the policy is avoiding — though the ordinary wait below the policy branch may
still wait for it, and should, once it is the only candidate left. The test
asserts which branch does the waiting rather than whether any wait happens.

Both fields are omitted by default and only the exact literal `before-last-resort`
opts in, matching the rule `reasoningEffortMode` already follows. A truthy
non-boolean `lastResort` normalizes to false, so a config that fails validation
cannot still change routing if it is loaded anyway. The normalizer's null is
dropped by `sparseComboConfig`, so stored combos do not gain a meaningless key.

Scoped to src/combos/resolve.ts, which #5716 does not touch — that PR changes
cooldown *duration* in failover.ts, this one changes *selection*. They merge in
either order.

Eight mutations, seven caught, including the safety one: withholding the last
resort when no normal target is reachable fails immediately. The survivor is an
equivalent mutant — the `targets.some(t => !t.lastResort)` guard is a
short-circuit that only avoids one wasted selection pass, since the fall-through
already handles an all-last-resort combo identically. Recorded rather than
papered over with a contrived assertion.

Closes #5691

(cherry picked from commit a1ab7f3)

* fix(combos): address review on the last-resort cooldown policy

Four findings from the review on #5736, all reproduced before changing anything.

**The deferral wait and the ordinary wait now share one budget.** The worst of the
four and a bug I introduced. `waitForCooldownMs` is documented as a cap per
*selection attempt*, but the fall-through kept the original clock and the full
budget, so a 3s deferral followed by a 9s ordinary wait spent 12s against a 10s
cap — close to double in the worst case. Both the remaining budget and the clock
now advance by whatever the deferral slept, and they are identical to the old
values when it did not, so the non-policy path is untouched.

The clock half needs its own test: sharing the budget alone still measures the
second wait from the original `now`, so a target whose cooldown lapses during the
deferral reads as cooling for longer than it is. Pinned by asserting the second
sleep is 500ms rather than 3,500ms.

**`lastResort: false` is no longer persisted.** The normalizer gives every target
an explicit `false`, and the management route wrote normalized targets straight
into stored config — so saving any combo added a noise key to every target,
including combos that never use the policy. Only the opt-in value is stored now,
matching how the combo-level policy is already handled by `sparseComboConfig`.

**An omitted policy no longer deletes the stored one.** The management route
preserves `cooldownMs`, `waitForCooldownMs` and `defaultEffortMode` when a request
omits them; `cooldownWaitPolicy` was missing from that list, so a GUI round-trip
would have dropped it. `lastResort` rides on each target and had the same problem,
so it is carried over per target, matched on provider and model.

**Docs.** The English config table gained rows for both keys, and the four
translated guides that carry that table (ja, ko, ru, zh-cn) gained the same two
rows. Those translations are mine and should be checked by a native speaker.

Two mutations added for the budget fix — not counting the deferral sleep, and not
advancing the clock — and both are caught. The re-anchored safety mutation still
fails immediately.

(cherry picked from commit a57f419)
Co-authored-by: Abhishek Sharma <abhicse24@gmail.com>

* test(layout): register combo-last-resort.test.ts

The carried #5736 test matched no layout seed, so tests/test-layout.test.ts
failed on it. Register it in codex-integration in both layout files.

Co-authored-by: Abhishek Sharma <abhicse24@gmail.com>

* fix(combos): keep omitted reasoningEffortMode and imageInput on PUT

A whole-combo PUT that omitted reasoningEffortMode or imageInput reset them
to strict/auto. `ocx combo set` has no flag for reasoningEffortMode, so every
CLI edit silently turned an adaptive combo back to strict. The route now
carries both from the stored combo when the body omits them, like it already
does for cooldownMs, waitForCooldownMs, defaultEffortMode and the last-resort
policy. Explicit values still replace them and invalid values are still
rejected.

The dashboard used omission to mean the default, so toPutBody now sends both
fields explicitly; otherwise switching back to auto or strict there would
never take effect. Storage stays sparse because the route strips defaults
before persisting.

Closes #5687

* docs(combos): state the 24h Retry-After cap and last-resort fields in the config reference

The configuration reference still said every combo cooldown is capped at
ten minutes and did not list lastResort or cooldownWaitPolicy. It now
states the 24-hour cap on explicit Retry-After delays, documents both new
fields, and the guide says the policy needs a nonzero waitForCooldownMs.

* test(combos): pin lastResort and cooldownWaitPolicy carry-over on PUT

A dashboard-shaped save re-sends targets without lastResort and omits the
combo policy. Pin that both survive it and a rename, that a swapped-in
target does not inherit the flag, and that explicit false/null clear them
without leaving keys in the stored config.

Co-authored-by: Abhishek Sharma <abhicse24@gmail.com>

* fix(combos): honor the last-resort policy on the post-failure hop

After an upstream failure, core-combo first takes a synchronous pick from
advanceComboAfterFailure, which ignored cooldownWaitPolicy. With normal A
and B, last-resort C and B cooling briefly, a failure on A dispatched C at
once and the policy never waited for B. Under the policy that pick now
skips last-resort targets; a null result falls through to
pickComboTargetWithWait, which waits for a normal target inside the budget
or dispatches the last resort. Also pin that a last-resort target stays
out of round-robin while a normal target is available.

Co-authored-by: Abhishek Sharma <abhicse24@gmail.com>

* fix(combos): validate targets before carrying lastResort over on PUT

The per-target lastResort carry-over read every target before validation,
so targets: [null] threw instead of returning the structured 400, and an
untrimmed re-sent target missed the stored (trimmed) one and lost its
flag. Skip non-record entries and match on trimmed provider and model.

Co-authored-by: Abhishek Sharma <abhicse24@gmail.com>

* docs(combos): describe last-resort targets as emergency-only under the policy

With cooldownWaitPolicy set, a lastResort target is skipped whenever any
normal target is available, for every strategy; waitForCooldownMs only
adds the wait for a cooling normal target. Replace the sentence that
said the policy needs a nonzero wait, and state the rule in the English
reference and in the translated table rows.

---------

Co-authored-by: 정우철 <oocheol@naver.com>
Co-authored-by: Abhishek Sharma <abhicse24@gmail.com>
… wait, one-process test leaks (#5740)

* ci: accept later PR timestamps for re-attestation

* ci: document delayed re-attestation events

* test(ci): cover re-attestation timestamp rejection

* test(server): wait for the sideband ceiling echo on events, not a 15s timer

The sideband ceiling case raced its 50MiB relay against an inner 15s setTimeout
and failed on an ordinary macOS shard at 15318ms (#4997). The transfer is what
the case asserts, so the wait now settles only on the echo, an early close, a
client error, or a failed assertion. onTestFinished owns teardown and reports
the stage and peer summary even when the harness budget ends the case.

Refs #4997

* test: stop hung or mocking test files leaking into later files in one process

Running tests/server, tests/images, or tests/lib in one Bun process (#5439)
failed for reasons outside the failing files:

- download-connect-deadline-default mocked node:dns/promises and
  src/lib/pinned-http and never put them back, so pinned-https-get,
  tests/lib/pinned-http, transport-null-body, and download-cap-default's own
  capture of the real modules all saw the stub. It now captures the real
  modules first and restores them in afterAll, as download-cap-default does.
- cancel-body-on-abort and server-key-failover-e2e stub globalThis.fetch and
  restored it only in the test's own finally, which a per-test timeout skips.
  Both now restore it from afterEach. The live-relay case also fails fast
  with the handler's status when handleLive settles without calling fetch,
  instead of waiting forever on the read it expected.
- server-key-failover-e2e stopped its proxies only in each test's finally,
  so one hung case kept the process-wide spend-ledger lease and every later
  file failed startServer with SPEND_LEDGER_OWNER_HOME_CONFLICT. Its servers
  are now tracked and stopped from afterEach, and request pacing is reset
  before and after each test.

Refs #5439

* test(server): put module mocks back after the files that install them

mock.module outlives the file that calls it, so five tests/server files left
stubs installed for every later file in a one-process run (#5439):
context-history (auth-context, routing, openai-sidecar, auth-cors, responses,
lifecycle), server-combo-failover-e2e (adapter-resolve, upstream-retry),
server-combo-zero-output-failover (adapter-resolve), companion-settings
(open-url) and startup-action-control-elevation (node:child_process). The
auth-cors stub alone makes later proxy tests answer 401 "test credential
missing". Each file now snapshots the real module before mocking it and
re-registers it in afterAll, the shape download-cap-default already uses.

Refs #5439

* test(server): release the native-main block the stop-hardening case leaves behind

"a rejected native-lifecycle release still drains the ACL flight" makes
releaseNativeMainStartupLifecycle throw, so the real release never ran for the
server it started. Under the spoofed win32 platform startServer takes a
process-wide "ownership-unknown" native-main block, which then stayed on for
the rest of the process: in a one-process tests/server run all 31 failing
reserve-ingress cases saw isNativeMainTrafficBlocked() true (#5439). The case
now runs the real release once the spy is restored and asserts the gate is
open again. Removing that release makes the new assertion fail.

Refs #5439

* test(server): start the replace-retry counter cases from zero

system-routes reset the process-wide Windows replace-retry counters after each
case but not before the first, so in a one-process tests/server run "a clean
replace records nothing" read two config:EPERM retries an earlier file had
recorded (#5439). Reset before each case as well.

Refs #5439

* test(server): start the logs display-metrics cases from an empty request log

management-api-logs-metrics cleared the process-wide request log after each
case but not before the first, so in a one-process tests/server run its first
case read a Kiro row an earlier file had logged and priced it (#5439). Clear
the log before each case as well.

Refs #5439

---------

Co-authored-by: Vadevious <Vadevious@users.noreply.github.com>
…xAI adapter fixes (#5739)

* fix(quota): label DeepSeek balance with the selected row's currency (#5692)

A CNY-billed account showed 'API balance ($76.88)'. The symbol now follows the balance_infos row that was picked: USD keeps $, CNY uses ¥, other codes prefix the amount, and a row without a currency keeps the legacy $.

* fix(registry): publish MiMo token-plan context, output and modality facts (#5695)

The mimo token-plan entry declared no model-level capacity, so V2.6 rows reached clients without a context window, output cap or input modalities. Xiaomi's model pages list 1M context and 128K output for all four roster ids, image input for V2.6 Pro/Flash and V2.5, and text only for V2.5 Pro. Video/audio have no catalog vocabulary and are not claimed; noVisionModels is unchanged.

* fix(google): give array tool parameters without items a string item schema (#5689)

A tool parameter declared as {type: array} with no items reached Gemini unchanged and could be rejected. The sanitizer now materializes items {type: string} for any array it emits without items (missing, tuple, or invalid source items). Valid item schemas are unchanged, the budget-exhausted path is untouched, and no loss category is recorded.

* fix(openai-chat): reconcile repeated MiMo tool-call echoes (carries #5693)

MiMo 2.6 Pro over OpenCode Go can echo two identical bare <tool_call>
blocks in assistant text beside one structured call whose input repeats
the body twice. The pair is now suppressed when exactly one structured
call agrees with its function and input, and a doubled input (direct or
newline joined, input as the only key) is reduced to one copy.
Ambiguous or mismatched markup stays visible.

Rebuilt on the blockAt/freeformBody reader from #5725, so the comparison
also holds for the canonical MiMo layout with a newline after the
function header.

Co-authored-by: Vadevious <Vadevious@users.noreply.github.com>

* fix(xai): give grok-4.7-build-fast grok-4.7's documented metadata (#5576)

The discovered grok-4.7-build-fast id fell back to a 128K window and a generic effort ladder. xAI documents Grok 4.7 Fast as the same model on faster infrastructure (Cursor and Grok Build only), so the id now carries grok-4.7's 500K window, low..xhigh ladder with a high default, image input, and the reasoning-model stop/penalty/reasoning-replay lists. The wire pin, service tier and lineup seed stay unclaimed until probed.

* fix(cli): resolve Codex catalog slugs in ocx effort model (#5096)

ocx effort model command-code/deepseek-deepseek-v4.1-flash, the slug the Codex catalog publishes, reported an empty ladder because the selector was split at the first slash and looked up literally. The model part now decodes through the router's known-id slug codec before the ladder, wire map and noReasoningModels lookups, so the slug and the exact id command-code/deepseek/deepseek-v4.1-flash report the same ladder. Output names the resolved id and adds requestedModel / 'Resolved from' when it differs. Unresolvable ids behave as before; no ladder rows change.

* fix(command-code): keep MiMo tool-call markup after prose off the text channel (#5698)

The Command Code tool-text filter only held a text block that opened with
<tool_call>. MiMo's gateway echo can arrive after ordinary prose in the
same delta, and interleaved reasoning interrupted held blocks, so the raw
envelope reached the client while the native call also ran.

- A delta is split at the marker: prose keeps its streamed or queued path
  and the markup starts a fresh probe block. Leading whitespace still uses
  the existing probe.
- Held blocks are no longer interrupted by interleaved events; the queued
  byte bound still flushes an envelope that never resolves.
- An envelope the strict parser rejects but that opens and closes around a
  declared function is dropped on the duplicate and clean-finish paths.
  Markup that parses but does not fit its schema is still released as text.

Reimplemented from the reporter's validated patch in the issue.

Co-authored-by: marciodps <95321123+marciodps@users.noreply.github.com>

* docs(command-code): describe the prose split, held envelopes and loose-envelope drop (#5698)

* test(layout): register L3 regression files; add the L3 lane plan

* fix(google): charge synthesized array items to the schema node budget (#5689)

Review follow-up: the materialized items schema was added after traversal without consuming a node, so many bare array leaves could exceed the 1,024-node bound. Synthesis now reserves one node and is skipped, with node-budget-widened reported, once the budget is spent.

* fix(openai-chat): reduce a doubled echo input only when one call qualifies

Review follow-up to the #5693 carry: the doubled-input repair ran per structured call, so two qualifying calls were both rewritten while the pair itself stayed visible as ambiguous. Both flush sites now reconcile a response's calls as one batch, and the reduction applies only when exactly one call qualifies.

* fix(command-code): drop a malformed echo only for its own native call; track only probing blocks

Review follow-ups to #5698: a malformed envelope was dropped when any native call exhausted its candidates, even one for another tool; it now needs a native call for the function it declares, otherwise it is released as text. Held blocks are no longer kept in activeProbes just to be skipped on every event.

* fix(openai-chat): count an already-agreeing call as a competing echo explanation

Review follow-up: with a doubled call A and a call B whose input already equals the repeated block, A was still reduced because only doubled shapes were counted. Both now count as explanations, and the reduction applies only when there is exactly one.

* fix(google): omit an array the node budget cannot complete instead of emitting it bare

Review follow-up to #5689: when the budget ran out at an array, the retained array could still be emitted without items, which Gemini rejects for the whole request. Every sanitizeSchema exit now completes an array's items or returns BUDGET_EXHAUSTED so the caller omits it, cascading to a parent that lost its own items. Non-array schemas keep the existing budget behaviour.

* test(openai-chat): pin fenced repeated echoes as visible and unrepaired

Review follow-up: a repeated pair inside a Markdown fence opened in an earlier chunk keeps its doubled input and stays visible, and a fenced echo does not repair the argument prefix beside it. The buffer never holds a complete block inside a fence, so the reducer and drain share the same starting context; these tests guard that.

---------

Co-authored-by: Vadevious <Vadevious@users.noreply.github.com>
Co-authored-by: marciodps <95321123+marciodps@users.noreply.github.com>
lidge-jun and others added 19 commits September 24, 2026 19:10
…rmes affinity, web-search Off, quota bar (#5742)

* fix(desktop): reopen the dashboard from the macOS app icon

(cherry picked from commit 920c052)

Co-authored-by: Jian Gong <fflake33@icloud.com>

* fix(desktop,gui): pause dashboard polling while the desktop window is hidden

WebView2 does not flip document.visibilityState when the Tauri window hides to the tray, so the dashboard kept polling. The shell now publishes window.__OPENCODEX_HOST_VISIBLE__ and an opencodex:host-visibility event for the main window on show, hide and every page load, and visibility-poll, client-resource and Combos read one deduped predicate from gui/src/host-visibility.ts. macOS WKWebView was measured to flip visibilityState already.

Refs #5493

* fix(hermes): generate and safely adopt dynamic session affinity

(cherry picked from commit fa097ba)

Closes #5710
Co-authored-by: Jian Gong <fflake33@icloud.com>

* feat(sidecar): make Off selectable in the web-search card and switch Codex's web_search off

The web-search sidecar could only be turned off by editing `config.json`. That
is not enough when an MCP search server should be the only search path: Codex
keeps declaring its native hosted `web_search` tool until its own root
`web_search` mode says otherwise, and the tool a client advertises is the tool
the model reaches for — so the model kept calling the native tool instead of the
MCP one.

Off is now the first row of the Dashboard's web-search model picker (i18n
`dash.webSearchOff`, all ten locales) and `ocx agent sidecar web --enabled off`
accepts the same switch. Both go through the existing
`PUT /api/sidecar-settings`, which persists `webSearchSidecar.enabled` and —
only when the switch actually MOVES — re-runs the Codex config injection, so the
sidecar state and Codex's client-side key follow each other immediately instead
of at the next `ocx sync`. The response carries the Codex-side write as
`codexWebSearch` (`applied`/`reason`/`retryable`), the same report the Desktop
switches use.

Ownership follows the routing keys: while the sidecar is off the injection owns
root `web_search` and writes `web_search = "disabled"` — the only mode that
removes the native tool. A user-owned root line is replaced in that state because
two root keys of the same name are invalid TOML; the journal snapshot returns it
on `ocx restore`. Switching the sidecar back on removes only the marker-owned
pair, so a re-enabled sidecar cannot be left with nothing to intercept.

(cherry picked from commit d2ec419)

* review: report the Codex-side write in the Dashboard and sharpen the docs

CodeRabbit review on #5709:

- The web-search card now warns when the switch was stored but Codex's own
  `web_search` key was not rewritten, and clears that warning once a sync applies
  the stored settings (`sidecarCodexWritePending`, i18n `dash.webSearchCodexSync` in all
  ten locales). Verified against a sandboxed Dashboard with the Codex write made
  to fail: the card showed the warning for both directions of the switch.
- `reference/cli/agents.md` and the sidecars guide no longer imply the CLI always
  prints the `Codex config:` line: only a save that moves the switch triggers a
  write, and the ordinary `not_requested` answer prints nothing extra.

(cherry picked from commit 07410d7)

* fix(codex): journal the web-search switch's ownership both ways

Review of the first pass found two ways the root `web_search` key could end up
in the state this feature exists to avoid.

Ownership by value (#1798 rule). A Codex app reserialize keeps values and drops
comments, so `web_search = "disabled"` could survive with no marker above it.
Switching the sidecar back on then left the line in place: the sidecar is on,
and the client still advertises no native tool for it to intercept. The journal
now records the value the injection wrote (`injectedRootWebSearch`) and the
strip consumes a marker-less line whose value matches it exactly, so a user's
own mode is still never mistaken for ours.

The operator's mode is no longer lost. Off has to remove a user-owned root line,
because two root keys of the same name are invalid TOML. The journal now carries
that exact line (`replacedRootWebSearch`) and the pass that switches the sidecar
back on puts it in our pair's place — including for a line the journal snapshot
predates, which `ocx restore` alone cannot cover. A second injection while the
switch is still off keeps the recorded line instead of clearing it.

`ensureRootWebSearchDisabled` reports what it did (the line it removed, the
value it wrote) rather than returning a bare string; the plan passes both to
`markJournalInjectedState`. The purge path in `remove.ts` is the enabled
direction of the same transform, so it drops our residue by value and returns
the operator's line as well.

Tests: the pure cases plus an end-to-end spawn test that runs off, simulates the
comment-dropping rewrite, and runs on again against the journal.

(cherry picked from commit 128d55b)

* fix(gui): keep an outstanding Codex-write warning across other saves

A save that did not move the web-search switch answers `not_requested` about a
Codex file it never touched. Saving anything else in the meantime (a Vision
setting, for instance) therefore replaced the stored report and cleared the
warning while the native tool was still being advertised. The report now
survives that answer and is settled only by a write that ran or by a successful
model sync.

(cherry picked from commit 26e315b)

* fix(codex,gui): read quoted web_search keys and keep a pending report on a failed save

Third review round on the web-search switch.

- `isRootWebSearchLine` accepts the quoted spellings TOML reads as the same key
  (`"web_search"` / `'web_search'`), which is what `tomlStringPattern` already
  matches for the value evidence. Without it a config written as
  `"web_search" = "live"` got a second root key from us, and two root keys of the
  same name stop Codex from loading the file at all — the outcome the ownership
  rule exists to prevent.
- `saveSidecar`'s catch no longer clears `sidecarCodexApply`. A request that
  failed before any answer arrived says nothing about the Codex file, so an
  outstanding report stays until a write that ran or a successful sync settles
  it; clearing it there was the same disappearing-warning bug through another
  path.
- The ownership test changes the operator's mode in place instead of appending a
  second root key, so the unchanged-content assertion exercises valid TOML.

(cherry picked from commit 86b525d)

Co-authored-by: Robin Bially <7304732+RobinBially@users.noreply.github.com>

* docs(sidecar): translate the web-search Off switch into the locale pages

The carried English docs for the web-search sidecar Off row, the --enabled off CLI flag and the enabled? config field now have matching text in fr, ja, ko, ru, tr, zh-cn and zh-tw.

* feat(gui): add header provider quota summary bar

(cherry picked from commit c17af7a)

* docs: describe dashboard quota summary bar

(cherry picked from commit ebda360)

Co-authored-by: Caesar7812 <279176182+Caesar7812@users.noreply.github.com>

* fix(gui): keep the quota summary bar off Startup and inside an error boundary

Review follow-ups for the carried header quota bar: hide it on the Startup page, wrap it in the page ErrorBoundary, use the shared z-index tokens, correct the provider-quotas ownership comments now that the bar keeps its own passive 60s read, align the Korean terms, and add the section to the fr, ja, ru, tr, zh-cn and zh-tw dashboard guides.

Co-authored-by: Caesar7812 <279176182+Caesar7812@users.noreply.github.com>

* perf(gui): look up quota headline windows by id instead of find() in a loop

React Doctor js-index-maps warning on the carried quota summary derivation.

* fix(gui,docs): address review on the quota summary bar

Let the bar's mobile Combos layout fill the remaining grid row instead of a second viewport, wrap long provider window labels in the popover, announce a failed or recovered read through a polite live region, and describe the headline as the preferred window (weekly first) shown on every page except Startup in all eight docs locales.

* fix(gui): keep quota chip percent on the same side of its color threshold, and let a second click close a pinned chip

---------

Co-authored-by: Jian Gong <fflake33@icloud.com>
Co-authored-by: Robin Bially <7304732+RobinBially@users.noreply.github.com>
Co-authored-by: Codex <codex@local>
Co-authored-by: Caesar7812 <279176182+Caesar7812@users.noreply.github.com>
…, sub-agent identity, agent-message recovery, 98% main lock (#5743)

* docs(devlog): plan lane L4 Codex integration, CLI and service bundle

* fix(service): preserve connected client key on uninstall (#5713)

ocx service uninstall unconditionally deleted service-api-token, which on a
remote-hub client is the per-client data-plane key issued by the hub (#5699).
Uninstall now deletes the token only under the client lifecycle and config
mutation locks, and only when persisted client state is disconnected and no
pending connect marker owns the current key's fingerprint. Connect publishes
that fingerprint marker before writing the key and clears it on commit or
rollback. Lock, state-read and unlink failures report cleanup as unverified.

On top of #5713: rollback checks the pending marker against its own
fingerprint, so a valid marker for a different key is left alone instead of
adding a spurious rollback failure.

Carries #5713.
Closes #5699.

Co-authored-by: 정우철 <oocheol@naver.com>

* fix(codex): bound aggregate rollout inspection during startup (#5703)

The native-residue classifier limited each referenced rollout to 64 MiB but
not the total, so the read-only startup preflight could parse gigabytes of
conversation history on every Codex launch (#5701). One observation now reads
at most 64 MiB of rollout content across the history database and backup
manifest together; a file that would exceed the remaining budget is reported
indeterminate before it is read, and classification stops at the first
indeterminate surface. Exhausting the budget never reports clean.

Carries #5703.
Closes #5701.

Co-authored-by: Konstantinos <37538071+konstantinosbotonakis@users.noreply.github.com>

* fix(codex-home): import path expansion without the config facade (#5548)

src/codex/home.ts imported expandUserPath from the ../config barrel, which
re-enters the config facade before the Codex home resolver has initialized.
On a fresh WSL process that import cycle could fail before the home was
resolved. The resolver now imports expandUserPath from src/config/paths.ts
directly, and a fresh-process regression test loads the resolver first with
a tilde CODEX_HOME.

Only the import fix, its structure note and the fresh-process test are
carried; the PR's cli-help, service and docker expectation edits target the
documented container-only failures and stay out.

Carries #5548 (partial).

Co-authored-by: Vadevious <Vadevious@users.noreply.github.com>

* docs(remote-hub): translate the service uninstall key-retention note

Adds the #5713 uninstall paragraph to the fr, ja, ru, tr, zh-cn and zh-tw remote hub guides so no locale describes the old unconditional token deletion.

Co-authored-by: 정우철 <oocheol@naver.com>

* fix(identity): name the worker's own model when a sub-agent is spawned (#5221)

Codex stores a session's instruction block once and replays it verbatim into
a sub-agent spawned on a different model, so a worker inherited the parent's
identity sentence and answered identity questions with the parent's model id
(#5217).

The catalog no longer bakes a model id into base_instructions; it writes the
model-neutral line. The destination is named at request time: the request
parser names the neutral line or a stale routed sentence in the top-level
instructions and developer items, adapters that call identifyRoutedModel still
settle on the wire model id, and the Responses passthrough renames on a routed
destination and drops the sentence on a native/forward one. Only sentences
this proxy generated are matched.

Rebuilt on current dev. On top of #5221: the parser also covers instructions,
so adapters that build their own system text (devin, ollama-native, cursor,
qoder, codebuddy, mimo-free) keep a named identity; a forward strip that
empties instructions or a developer item removes it instead of sending it
blank; catalog cases live in a sibling test file because codex-catalog.test.ts
is at its size cap; slug-codec and configured-native-models expectations
follow the neutral catalog.

Carries #5221.
Closes #5217.

Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com>

* fix(responses): recover FOLLOWUP_TASK and FINAL_ANSWER agent messages (#5009)

Opt-in encrypted agent-task recovery handled only NEW_TASK and MESSAGE, so an
unreadable FOLLOWUP_TASK or FINAL_ANSWER item either failed without recovery
or, for an unrecognised envelope shape, measured as readable and was
forwarded as raw ciphertext. Recovery and the unreadable-ciphertext guard now
recognise all four codex-rs agent-message types, including a FINAL_ANSWER
without a Task name line.

Sender and admission checks are unchanged: credential admission still runs
before any cache access, the structured author must equal the header sender,
and the recipient is cross-checked whenever the header names one. The cache
key is a JSON-encoded fixed-order tuple that binds the structured recipient,
and a recovered assignment that echoes the other routing family is rejected.
agentTaskRecovery stays default-off.

Carries #5009.

Co-authored-by: Zhaofeng Li <lzfxxx@gmail.com>

* docs(subagents): describe four-type agent-task recovery in every locale

The localized sub-agent guides still said agentTaskRecovery loses message-type follow-ups, which contradicts the #5009 recovery of FOLLOWUP_TASK and FINAL_ANSWER.

Co-authored-by: Zhaofeng Li <lzfxxx@gmail.com>

* feat(codex): lock the main account at 98% by default (#5694)

Codex Desktop disables its send button once the ChatGPT account window reads
0% remaining, even when the user routes every request to another provider.
The main-account hard lock already stops ocx from admitting new
identity-matched main-account requests at a usage threshold, but it was
opt-in at 99%.

The lock is now on by default at 98%: an absent or true
codexMainAccountHardLock enables it, and only an explicit false opts out.
Every gate reads one resolver (isMainAccountHardLockEnabled); the settings
route persists false and deletes the key for true, like fastRows; a
malformed hand edit falls back to the default; the blocked-request message
derives its percent from the constant.

Trade-offs: while blocked, the main account's Luna Reserve cannot activate;
switching the setting off lets the main account run to exhaustion. The old
switch deleted the key when turned off, so an earlier opt-out now reads as
on and has to be switched off once more.

GUI copy (all locales), the English and Korean accounts reference, and
structure/providers/openai-tiers.md describe the new default.

Refs #5694.

* docs(devlog): record L4 publish plan

* test(gui): expect the 98% hard-lock blocked label

The main-card blocked label follows the #5694 threshold change.

* fix(identity): drop the neutral catalog line on native destinations

After #5221 the catalog stores the model-neutral identity line, so a native worker spawned from a routed parent received "Do not claim to be GPT-5 or to be made by OpenAI", contradicting Codex's own model_switch identity. The forward strip now removes the neutral line as well as a routed sentence; an instructions value that becomes empty is still removed.

Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com>

* fix(gui): use the Turkish locative -de after %98

Ninety-eight ends in a front vowel, so the hard-lock title reads %98’de.

* fix(identity): name the final wire model and system-role items

Two review findings on the #5221 carry. The request parser names the
identity sentence from the client selector, which can be an alias, a
namespaced slug or a combo name, and adapters that never call
identifyRoutedModel (devin, ollama-native, cursor, qoder, codebuddy,
coding-agent) shipped that name. The final route normalization now renames
our sentence to route.modelId, where the dispatched id is known and every
dispatch path reads the context afterwards. The parser also names
system-role input items, not only developer items.

Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com>

---------

Co-authored-by: 정우철 <oocheol@naver.com>
Co-authored-by: Konstantinos <37538071+konstantinosbotonakis@users.noreply.github.com>
Co-authored-by: Vadevious <Vadevious@users.noreply.github.com>
Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com>
Co-authored-by: Zhaofeng Li <lzfxxx@gmail.com>
…s its home (#5747)

#5740 moved the sideband ceiling case's teardown to onTestFinished. Bun runs
the file's afterEach first, so afterEach removed .tmp-server-live-test while
the case's proxy still held files open inside it. POSIX allows that; Windows
answers EBUSY after the removal retries, the proxy is never stopped, and every
later case's beforeEach/afterEach fails on the same locked directory (windows
8/9 on dev 6c171aa, run 35992525426).

The case now hands its teardown to a slot the file's afterEach awaits before
anything else, which also runs when the harness budget ends the case. The
event-driven wait, every assertion, and the 20s budget are unchanged.

Refs #4997
…e and stop (#5748)

After #5694 made the main-account hard lock default-on, Windows full CI
returned 503 "native-main profile maintenance is active" for caller-owned
direct requests. Two defects in the startup gate caused this.

Admission: resolveCodexAuthContext refused a caller-owned request outright
while the owned startup's policy binding was pending. With the lock opt-in
that fence almost never ran; default-on it runs on every startup, and on
Windows convergence (recovery, stage sweep, policy binding under the
exclusive claim) lasts long enough that a request sent right after start
got the 503. The fence now waits, bounded at 15 s and abortable, for the
binding to settle and then lets the hard lock decide as usual; only a
binding still pending at the deadline is refused.

Release: the process-wide gate snapshot was set to recovery-pending when
convergence started and cleared only by that convergence while its entry
was registered. Stopping the last server mid-convergence deleted the entry,
so the gate stayed blocked for the rest of the process, and a later server
that does not sync Codex never re-armed it. Releasing the last reference now
resets a gate that belonged only to that entry, and convergence writes are
guarded by entry identity.
…nboarding (#5749)

* feat(desktop): spinner startup surface and first-launch GitHub star onboarding

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(gui): keep star prompt open on gh failure, hide when disabled, split styles

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: jun <bitkyc08@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
#5765)

Update availability is now signalled on every install type: the proxy refreshes the package update cache itself (async registry lookups, write-through, 40 h unknown), the desktop app publishes its signed updater state to the GUI it hosts, the desktop update button opens a bundled update page with a gated install path, and the macOS menu bar, Windows/Linux Tauri trays and the npm Windows PowerShell tray show a blue dot while an update is pending.

Merged by the maintainer before the Cross-platform CI run for b0e657d finished; PR hygiene, target, service lifecycle (Linux, macOS, Windows) and React Doctor passed at that head.
…s it (#5753)

* fix(responses): strip max_output_tokens only where the backend rejects it

stripUnsupportedForwardParams ran for every forward provider, outside the
isCanonicalOpenAiForwardProvider guard, dropping the caller's max_output_tokens
cost cap on self-hosted and third-party gateways that honour it — the turn then
generates far more than was authorised. Keep stripping metadata on every forward
route; strip max_output_tokens only on the canonical backend that rejects it.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* docs(reference): note which forward routes keep the caller's output cap

max_output_tokens now reaches every forward destination except the canonical
ChatGPT route that rejects it, so the reference had to say where a caller's
output cap survives and where it does not.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(responses): move the forward output-cap case to a sibling test and narrow the wording

Moves the non-canonical forward regression out of the capped passthrough test file into tests/responses/responses-forward-output-cap.test.ts (registered in both layout maps), fixes the passthrough comment to describe the two-field behavior, and narrows the metadata/cap wording in canonical-forward.ts and proxy-formats.md.

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: JUN <bitkyc08@gmail.com>
Co-authored-by: JUN <jun@lidgeai.com>
…#5752)

* fix(usage): split the attempt row on any account label, not only key labels

The split in `noteProviderAttemptSend` tested `KEY_ACCOUNT_LOG_LABEL_RE`
(`k` + 32 hex), which can never match a Codex pool (`p` + 6 hex) or generic
OAuth (`o` + 6 hex) label, so a rotation onto a second account folded that
account's sends and usage into the first account's row: per-account usage and
cost were reported against the wrong credential.

`isCodexUsageAccountLogLabel` (src/usage/log.ts:77) already tests the broad
`ACCOUNT_LOG_LABEL_RE` and the seal persists those labels onto the attempt, so
the row carried an `o`/`p` label the split then refused to act on. Read the same
pattern back at the split.

`sealRequestAttemptIdentity` separately re-stamped `attempt.provider` after the
send, laundering the account-qualified provider string that Anthropic pool turns
carry instead of a label. A sent row's account is settled; freeze it.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(usage): split the attempt row when the account-qualified provider changes

The label axis cannot see an Anthropic rotation. `stampOAuthAccountLabel`
(src/providers/label.ts:73) returns early for base `anthropic`, so those pool
turns carry no account label at all and keep their account inside the
account-qualified log provider string ("anthropic (pabc123)") instead. A
rotation therefore reported ONE attempt on the first account, carrying both
accounts' tokens.

Split on that string too. The comparison is only sound because a sent attempt's
provider is now frozen by `sealRequestAttemptIdentity`: after a send the two can
diverge only when the account moved underneath the row.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* test(usage): pin real Anthropic rotation shape and seal-before-send ordering

Uses formatAnthropicProviderForLog-shaped provider strings for the Anthropic rotation case, adds the seal-then-send ordering regression, and moves the ordered-attempts case into tests/usage/request-log-attempt-identity.test.ts for the file-size ratchet.

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: JUN <bitkyc08@gmail.com>
Co-authored-by: JUN <jun@lidgeai.com>
… mode (#5744)

* fix(chat-completions): avoid injecting native main credential in pool mode

When codexAccountMode is pool, /v1/chat/completions previously claimed
the native main profile and stamped Bearer ${token.accessToken} into the
forwarded request headers. This led /v1/responses to treat the request as
an explicit requestScopedMainCredential, bypassing the account pool, active
credential selection, and failover rotation.

Guard native main enrichment so that pool routes leave headers clean and let
auth-context resolve the designated pool account dynamically.

* fix(chat-completions): skip native-main enrichment only for explicit pool mode

Narrows the guard to codexAccountMode === "pool" so an omitted mode keeps its behavior, and makes the regression use a second pool account: the upstream request must carry that account's token and account id, never native-main-token-pool, without codexDesktopAuthless.

---------

Co-authored-by: JUN <bitkyc08@gmail.com>
Co-authored-by: JUN <jun@lidgeai.com>
…wire defaults (#5697)

* fix(providers): fallback to transport destination for registry model wire defaults

- Allow custom provider aliases (e.g. OG) to inherit registry modelWireDefaults, upstream streaming, and terminal repair policies when their endpoint matches a fixed-key registry destination (opencode-go)
- Capture destination fallback in router captureRouteStaticPolicy so staticPolicy.model.adapter respects transport defaults
- Retain name pinning for custom gateways with non-matching endpoints
- Add regression tests in opencode-go-luna-wire.test.ts

Agent-Generated-By: Codex

* fix(providers): fall back to the destination row after a named transport mismatch

A known registry id configured against another fixed destination now resolves that destination's wire policy; the router destination lookup only considers live-discovery rows so a shared Cline endpoint keeps liveModels. Adds OG alias route, adapter-resolve, and named-mismatch regressions; an alias at the exact canonical OpenCode Go endpoint takes that preset's policy, pinned in the route test.

---------

Co-authored-by: leon80900 <80900400+leon80900@users.noreply.github.com>
Co-authored-by: JUN <bitkyc08@gmail.com>
Co-authored-by: JUN <jun@lidgeai.com>
* feat(provider): add a Claude Code CLI subscription provider

`anthropic` reaches Claude by replaying Claude Code's HTTP identity (OAuth headers, a
hashed session id, beta flags) against the Messages API. That spends a subscription
outside Anthropic's own harness, and the account — not the proxy — carries the
consequence.

`claude-cli` makes the harness the transport instead: one headless `claude -p` turn per
request over the family's existing stream-json seam (`src/adapters/coding-agent/`). The
CLI's own sign-in is the only credential; OpenCodex stores none, reads none and injects
none, so this row needs no API key.

The profile is the family's first credentialless one: `tokenEnv` is optional, and the
shared turn skips the key preflight for such a profile while still redacting the generic
secret shapes. Arguments keep the family posture — `--tools ""`, `--strict-mcp-config`,
`--setting-sources ""`, `--no-session-persistence`, no permission bypass — and the scoped
child env inherits no `ANTHROPIC_*` value, so a `claude` already pointed at this proxy
cannot loop back into it. Telemetry, feedback and the auto-updater are off for the
spawned turn. `--system-prompt` replaces the Claude Code preset with the caller's system
and developer prompts instead of stacking a second instruction set in front of them.

v1 is text and reasoning only, exactly like `codebuddy` and `qoder`: with no tool channel
the client keeps approval, sandboxing and execution. The shared capture-only tool bridge
is the documented follow-up.

An unauthenticated CLI ends the turn on a normal `result` frame rather than a failure, so
the adapter rewrites that 401 into the action it implies (sign in with `claude`), instead
of leaving the operator to guess between key, row and account.

Verified against the installed CLI 2.1.270: the full argument set is accepted and a
stream-json turn reaches the account check, ending on the terminal `result` frame
"Not logged in · Please run /login".

* fix(provider): classify claude-cli as a keyless key row, not a local runtime

`local` is the Ollama / vLLM / LM Studio classification: the traffic never leaves the
machine, so there is no credential to classify. This row reaches api.anthropic.com, so the
marker misreported it wherever auth is classified — `classifyAccount` answered "local
provider ... has no credentials" for a provider whose whole point is a credential the
Claude Code CLI owns, and the dashboard filed the row as a local runtime.

`key` + `keyOptional` is what is true: the turn leaves this machine, and no API key is
required because the CLI signs in for itself. `deriveProviderPresets` already lists key
rows, so `dashboardPreset` is gone rather than duplicated, and `deriveKeyLoginMap` is
given the `dashboardUrl` every key row owes (the setup page, since a keyless row has no key
console).

A key configured on the row is still never handed to the harness; the new case pins that,
and the inherited HOME — one sign-in serves every request on this proxy — is now stated in
the registry note and the provider guide instead of only in the adapter comment.

* fix(provider): always replace the harness preset, and publish text-only models

Two review findings, both settled against the installed CLI 2.1.270 instead of the argument
list.

Omitting `--system-prompt` is not "no system prompt": it is Claude Code's own fourteen-block
preset, which describes a harness with tools this turn deliberately does not have. The
`prompt_snapshot` attachment the CLI writes into a session transcript makes the difference
visible — `--system-prompt "MARKER"` snapshots exactly that text, `--system-prompt ""`
snapshots the empty string, and omitting the flag snapshots the preset. The flag is now
always passed, with the empty string standing in for a caller that sends neither a system
nor a developer prompt, which is the same request the Messages API path forwards as no
system message at all.

The row published the Messages API image modality for all ten models while the adapter,
the guide and the note described v1 as text and reasoning only. Nothing verified that a
headless turn hands image bytes to the model, and an image the harness drops produces a
confident answer to the wrong question, so the models are published text-only
(`noVisionModels`) and the adapter refuses direct image input the way the Qoder presets
do. A vision sidecar on the request path still captions images into text.

The preset counts in the eight guides, eight quickstarts and the structure ops record move
from 97/80 to 98/81 with this row, which the derived-count gate asserts in every locale.

* fix(provider): sign the claude-cli child in, pin its roster, and stage the prompt file

Three defects the first signed-in run exposed, plus the argv hardening:

- `buildChildEnv` passes `USER` through. The CLI resolves its own keychain sign-in by
  account name, so a scoped environment without it answers "not logged in" on a machine
  that is signed in (`env -i` probe: `USER` alone -> `loggedIn: true`, `LOGNAME` alone or
  neither -> `false`). The value is a name, not a credential; no token is added.
- The row is `liveModels: false`, the same static-roster switch the CodeBuddy and
  Volcengine plan rows use. This route serves no model list, and a real start logged
  `Provider model discovery for "claude-cli" failed with HTTP 404` before falling back to
  the configured ids anyway.
- The folded system prompt moves off argv into a per-turn `0600` file passed as
  `--system-prompt-file`, removed in a `finally`: argv is world-readable through process
  listing. A caller that sends no system or developer prompt still gets a file, empty, so
  the harness preset stays out of the turn.

* docs(structure): name both control surfaces in the claude-cli registry note

---------

Co-authored-by: JUN <bitkyc08@gmail.com>
Move the account-rotation split out of request-log.ts for the 2,000-line limit, wire the claude-cli provider icon, and align the DeepSeek terminal-repair test with destination-based policy.
* Revert "fix(providers): fallback to transport destination for registry model wire defaults (#5697)"

This reverts commit 24b483b.

* test(providers): restore the DeepSeek alias terminal-repair expectation
… yet (#5769)

* fix(tray): let Windows tray probes run when CODEX_HOME does not exist yet

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(tray): only drop CODEX_HOME for a missing default home

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: jun <bitkyc08@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 24, 2026 18:19
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T18:20:45.742079Z 0b6907c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@lidge-jun
lidge-jun merged commit d4c26e2 into preview Sep 24, 2026
8 of 10 checks passed
@lidge-jun
lidge-jun deleted the codex/260925-release-preview-2.65.0 branch September 24, 2026 18:19
@coderabbitai

coderabbitai Bot commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 766 files, which is 466 over the limit of 300.

To get a review, reduce the PR to 300 files or fewer by splitting it into smaller PRs or changing its base branch.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: e129e132-72f1-497f-8e60-15c044490f34

📥 Commits

Reviewing files that changed from the base of the PR and between 836321b and 0b6907c.

⛔ Files ignored due to path filters (9)
  • assets/download-linux.svg is excluded by !**/*.svg
  • assets/download-macos.svg is excluded by !**/*.svg
  • assets/download-windows.svg is excluded by !**/*.svg
  • desktop/src-tauri/Cargo.lock is excluded by !**/*.lock
  • desktop/src-tauri/icons/tray/icon-update.png is excluded by !**/*.png
  • desktop/ui/logo.png is excluded by !**/*.png
  • src/tray/assets/opencodex-tray-offline-update.ico is excluded by !**/*.ico
  • src/tray/assets/opencodex-tray-online-update.ico is excluded by !**/*.ico
  • src/tray/assets/opencodex-tray-warning-update.ico is excluded by !**/*.ico
📒 Files selected for processing (766)
  • .github/scripts/pr-quality-state.test.cjs
  • .github/scripts/pr-readiness-reattest.cjs
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • README.md
  • app/Sources/NativeTray/Popover.swift
  • bin/ocx.mjs
  • desktop/package.json
  • desktop/scripts/appimage-patchelf.py
  • desktop/scripts/collect-release-assets.ts
  • desktop/scripts/generate-icons.ts
  • desktop/scripts/linux-packaged-e2e.ts
  • desktop/scripts/prepare-sidecar.ts
  • desktop/scripts/sidecar-signing.ts
  • desktop/scripts/verify-linux-sidecar.sh
  • desktop/src-tauri/Cargo.toml
  • desktop/src-tauri/capabilities/dashboard-zoom.json
  • desktop/src-tauri/src/lib.rs
  • desktop/src-tauri/src/native_tray.rs
  • desktop/src-tauri/src/popup.rs
  • desktop/src-tauri/src/proxy.rs
  • desktop/src-tauri/src/startup.rs
  • desktop/src-tauri/src/tray.rs
  • desktop/src-tauri/src/updater.rs
  • desktop/src-tauri/src/window.rs
  • desktop/src-tauri/tauri.conf.json
  • desktop/ui/index.html
  • desktop/ui/update.html
  • devlog/_fin/260923_release_2_64/000_plan.md
  • devlog/_fin/260923_release_2_64/010_wp2_prerelease_items.md
  • devlog/_fin/260923_release_2_64/011_wp2_privacy_gate_complement.md
  • devlog/_fin/260923_release_2_64/012_wp2_request_owned_main_cursor.md
  • devlog/_fin/260923_release_2_64/020_wp3_dev_candidate.md
  • devlog/_fin/260923_release_2_64/030_wp4_release.md
  • devlog/_fin/260923_release_2_64/050_done.md
  • devlog/_plan/260923_bundle_a_tests_hygiene/000_triage.md
  • devlog/_plan/260923_bundle_a_tests_hygiene/010_build.md
  • devlog/_plan/260923_bundle_a_tests_hygiene/020_delivery.md
  • devlog/_plan/260923_bundle_f1_provider_registry/000_overview.md
  • devlog/_plan/260923_bundle_f1_provider_registry/010_carry_plan.md
  • devlog/_plan/260923_bundle_f1_provider_registry/020_delivery.md
  • devlog/_plan/260923_bundle_lane_e/000_overview.md
  • devlog/_plan/260923_bundle_lane_e/010_decisions.md
  • devlog/_plan/260923_bundle_lane_e/020_carry.md
  • devlog/_plan/260923_bundle_lane_e/030_verify.md
  • devlog/_plan/260923_claude_desktop_first_party_models/000_plan.md
  • devlog/_plan/260923_claude_desktop_first_party_models/001_probe_evidence.md
  • devlog/_plan/260923_claude_desktop_first_party_models/010_roadmap.md
  • devlog/_plan/260923_claude_desktop_first_party_models/020_wp2_first_party_bindings.md
  • devlog/_plan/260923_claude_desktop_first_party_models/030_wp3_live_proof_and_pr.md
  • devlog/_plan/260924_anthropic_fast_opt_in/010_plan.md
  • devlog/_plan/260924_anthropic_forced_tool_choice/010_plan.md
  • devlog/_plan/260924_claude_desktop_picker_mode/000_plan.md
  • devlog/_plan/260924_claude_desktop_picker_mode/001_research.md
  • devlog/_plan/260924_claude_desktop_picker_mode/010_wp2_gateway_default_and_warning.md
  • devlog/_plan/260924_claude_desktop_picker_mode/020_wp3_picker_core.md
  • devlog/_plan/260924_claude_desktop_picker_mode/030_wp4_picker_activation.md
  • devlog/_plan/260924_claude_desktop_picker_mode/040_wp5_live_proof_pr_merge.md
  • devlog/_plan/260924_cursor_fast_pricing/000_plan.md
  • devlog/_plan/260924_cursor_fast_pricing/010_implementation.md
  • devlog/_plan/260924_cursor_fast_pricing/020_verification.md
  • devlog/_plan/260924_l3_provider_adapters/010_plan.md
  • devlog/_plan/260924_l4_codex_cli_service/000_roadmap.md
  • devlog/_plan/260924_l4_codex_cli_service/010_carry_ready_prs.md
  • devlog/_plan/260924_l4_codex_cli_service/020_subagent_identity_5221.md
  • devlog/_plan/260924_l4_codex_cli_service/030_agent_message_recovery_5009.md
  • devlog/_plan/260924_l4_codex_cli_service/040_main_hard_lock_default_5694.md
  • devlog/_plan/260924_l4_codex_cli_service/050_publish.md
  • devlog/_plan/260924_regression_risk_fixes/000_overview.md
  • devlog/_plan/260924_regression_risk_fixes/010_wsl_home.md
  • devlog/_plan/260924_regression_risk_fixes/020_windows_mise_node.md
  • devlog/_plan/260924_regression_risk_fixes/030_echo_filter.md
  • devlog/_plan/260924_regression_risk_fixes/040_tool_call_hold.md
  • devlog/_plan/260924_regression_risk_fixes/050_delivery.md
  • devlog/_plan/260924_update_indicator/000_plan.md
  • devlog/_plan/260924_update_indicator/001_sol_plan_draft.md
  • devlog/_plan/260924_update_indicator/002_architect_proposal.md
  • devlog/_plan/260924_update_indicator/010_phase1_package_cache.md
  • devlog/_plan/260924_update_indicator/020_phase2_desktop_state_icons.md
  • devlog/_plan/260924_update_indicator/030_phase3_desktop_update_page.md
  • devlog/_plan/260924_update_indicator/040_phase4_windows_npm_tray.md
  • devlog/_plan/260924_update_indicator/050_delivery.md
  • docs-site/src/content/docs/fr/getting-started/quickstart.md
  • docs-site/src/content/docs/fr/guides/claude-code.md
  • docs-site/src/content/docs/fr/guides/codex-integration.md
  • docs-site/src/content/docs/fr/guides/combos.md
  • docs-site/src/content/docs/fr/guides/desktop-app.md
  • docs-site/src/content/docs/fr/guides/integrations.md
  • docs-site/src/content/docs/fr/guides/macos-menu-bar.md
  • docs-site/src/content/docs/fr/guides/pi.md
  • docs-site/src/content/docs/fr/guides/providers.md
  • docs-site/src/content/docs/fr/guides/remote-hub.md
  • docs-site/src/content/docs/fr/guides/sidecars.md
  • docs-site/src/content/docs/fr/guides/subagent-v1-default.md
  • docs-site/src/content/docs/fr/guides/web-dashboard.md
  • docs-site/src/content/docs/fr/reference/cli.md
  • docs-site/src/content/docs/fr/reference/cli/agents.md
  • docs-site/src/content/docs/fr/reference/cli/lifecycle.md
  • docs-site/src/content/docs/fr/reference/configuration/providers.md
  • docs-site/src/content/docs/fr/reference/configuration/server.md
  • docs-site/src/content/docs/fr/reference/management-api.md
  • docs-site/src/content/docs/fr/reference/proxy-formats.md
  • docs-site/src/content/docs/getting-started/quickstart.md
  • docs-site/src/content/docs/guides/claude-code.md
  • docs-site/src/content/docs/guides/codex-integration.md
  • docs-site/src/content/docs/guides/combos.md
  • docs-site/src/content/docs/guides/desktop-app.md
  • docs-site/src/content/docs/guides/integrations.md
  • docs-site/src/content/docs/guides/macos-menu-bar.md
  • docs-site/src/content/docs/guides/pi.md
  • docs-site/src/content/docs/guides/providers.md
  • docs-site/src/content/docs/guides/remote-hub.md
  • docs-site/src/content/docs/guides/sidecars.md
  • docs-site/src/content/docs/guides/sub-agent-surface.md
  • docs-site/src/content/docs/guides/subagent-v1-default.md
  • docs-site/src/content/docs/guides/web-dashboard.md
  • docs-site/src/content/docs/ja/getting-started/quickstart.md
  • docs-site/src/content/docs/ja/guides/claude-code.md
  • docs-site/src/content/docs/ja/guides/codex-integration.md
  • docs-site/src/content/docs/ja/guides/combos.md
  • docs-site/src/content/docs/ja/guides/desktop-app.md
  • docs-site/src/content/docs/ja/guides/integrations.md
  • docs-site/src/content/docs/ja/guides/macos-menu-bar.md
  • docs-site/src/content/docs/ja/guides/pi.md
  • docs-site/src/content/docs/ja/guides/providers.md
  • docs-site/src/content/docs/ja/guides/remote-hub.md
  • docs-site/src/content/docs/ja/guides/sidecars.md
  • docs-site/src/content/docs/ja/guides/subagent-v1-default.md
  • docs-site/src/content/docs/ja/guides/web-dashboard.md
  • docs-site/src/content/docs/ja/reference/cli.md
  • docs-site/src/content/docs/ja/reference/cli/agents.md
  • docs-site/src/content/docs/ja/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ja/reference/configuration/server.md
  • docs-site/src/content/docs/ja/reference/management-api.md
  • docs-site/src/content/docs/ja/reference/proxy-formats.md
  • docs-site/src/content/docs/ko/getting-started/quickstart.md
  • docs-site/src/content/docs/ko/guides/claude-code.md
  • docs-site/src/content/docs/ko/guides/codex-integration.md
  • docs-site/src/content/docs/ko/guides/combos.md
  • docs-site/src/content/docs/ko/guides/desktop-app.md
  • docs-site/src/content/docs/ko/guides/integrations.md
  • docs-site/src/content/docs/ko/guides/macos-menu-bar.md
  • docs-site/src/content/docs/ko/guides/pi.md
  • docs-site/src/content/docs/ko/guides/providers.md
  • docs-site/src/content/docs/ko/guides/remote-hub.md
  • docs-site/src/content/docs/ko/guides/sidecars.md
  • docs-site/src/content/docs/ko/guides/subagent-v1-default.md
  • docs-site/src/content/docs/ko/guides/web-dashboard.md
  • docs-site/src/content/docs/ko/reference/architecture.md
  • docs-site/src/content/docs/ko/reference/cli.md
  • docs-site/src/content/docs/ko/reference/cli/agents.md
  • docs-site/src/content/docs/ko/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ko/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/server.md
  • docs-site/src/content/docs/ko/reference/management-api.md
  • docs-site/src/content/docs/ko/reference/proxy-formats.md
  • docs-site/src/content/docs/reference/adapters.md
  • docs-site/src/content/docs/reference/architecture.md
  • docs-site/src/content/docs/reference/cli.md
  • docs-site/src/content/docs/reference/cli/agents.md
  • docs-site/src/content/docs/reference/cli/lifecycle.md
  • docs-site/src/content/docs/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/reference/configuration/agents.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/routing.md
  • docs-site/src/content/docs/reference/configuration/server.md
  • docs-site/src/content/docs/reference/management-api.md
  • docs-site/src/content/docs/reference/proxy-formats.md
  • docs-site/src/content/docs/ru/getting-started/quickstart.md
  • docs-site/src/content/docs/ru/guides/claude-code.md
  • docs-site/src/content/docs/ru/guides/codex-integration.md
  • docs-site/src/content/docs/ru/guides/combos.md
  • docs-site/src/content/docs/ru/guides/desktop-app.md
  • docs-site/src/content/docs/ru/guides/integrations.md
  • docs-site/src/content/docs/ru/guides/macos-menu-bar.md
  • docs-site/src/content/docs/ru/guides/pi.md
  • docs-site/src/content/docs/ru/guides/providers.md
  • docs-site/src/content/docs/ru/guides/remote-hub.md
  • docs-site/src/content/docs/ru/guides/sidecars.md
  • docs-site/src/content/docs/ru/guides/subagent-v1-default.md
  • docs-site/src/content/docs/ru/guides/web-dashboard.md
  • docs-site/src/content/docs/ru/reference/cli.md
  • docs-site/src/content/docs/ru/reference/cli/agents.md
  • docs-site/src/content/docs/ru/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/server.md
  • docs-site/src/content/docs/ru/reference/management-api.md
  • docs-site/src/content/docs/ru/reference/proxy-formats.md
  • docs-site/src/content/docs/tr/getting-started/quickstart.md
  • docs-site/src/content/docs/tr/guides/claude-code.md
  • docs-site/src/content/docs/tr/guides/codex-integration.md
  • docs-site/src/content/docs/tr/guides/combos.md
  • docs-site/src/content/docs/tr/guides/desktop-app.md
  • docs-site/src/content/docs/tr/guides/integrations.md
  • docs-site/src/content/docs/tr/guides/macos-menu-bar.md
  • docs-site/src/content/docs/tr/guides/pi.md
  • docs-site/src/content/docs/tr/guides/providers.md
  • docs-site/src/content/docs/tr/guides/remote-hub.md
  • docs-site/src/content/docs/tr/guides/sidecars.md
  • docs-site/src/content/docs/tr/guides/subagent-v1-default.md
  • docs-site/src/content/docs/tr/guides/web-dashboard.md
  • docs-site/src/content/docs/tr/reference/cli.md
  • docs-site/src/content/docs/tr/reference/cli/agents.md
  • docs-site/src/content/docs/tr/reference/cli/lifecycle.md
  • docs-site/src/content/docs/tr/reference/configuration/providers.md
  • docs-site/src/content/docs/tr/reference/configuration/server.md
  • docs-site/src/content/docs/tr/reference/management-api.md
  • docs-site/src/content/docs/tr/reference/proxy-formats.md
  • docs-site/src/content/docs/zh-cn/getting-started/quickstart.md
  • docs-site/src/content/docs/zh-cn/guides/claude-code.md
  • docs-site/src/content/docs/zh-cn/guides/codex-integration.md
  • docs-site/src/content/docs/zh-cn/guides/combos.md
  • docs-site/src/content/docs/zh-cn/guides/desktop-app.md
  • docs-site/src/content/docs/zh-cn/guides/integrations.md
  • docs-site/src/content/docs/zh-cn/guides/macos-menu-bar.md
  • docs-site/src/content/docs/zh-cn/guides/pi.md
  • docs-site/src/content/docs/zh-cn/guides/providers.md
  • docs-site/src/content/docs/zh-cn/guides/remote-hub.md
  • docs-site/src/content/docs/zh-cn/guides/sidecars.md
  • docs-site/src/content/docs/zh-cn/guides/subagent-v1-default.md
  • docs-site/src/content/docs/zh-cn/guides/web-dashboard.md
  • docs-site/src/content/docs/zh-cn/reference/cli.md
  • docs-site/src/content/docs/zh-cn/reference/cli/agents.md
  • docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/server.md
  • docs-site/src/content/docs/zh-cn/reference/management-api.md
  • docs-site/src/content/docs/zh-cn/reference/proxy-formats.md
  • docs-site/src/content/docs/zh-tw/getting-started/quickstart.md
  • docs-site/src/content/docs/zh-tw/guides/claude-code.md
  • docs-site/src/content/docs/zh-tw/guides/codex-integration.md
  • docs-site/src/content/docs/zh-tw/guides/combos.md
  • docs-site/src/content/docs/zh-tw/guides/desktop-app.md
  • docs-site/src/content/docs/zh-tw/guides/integrations.md
  • docs-site/src/content/docs/zh-tw/guides/macos-menu-bar.md
  • docs-site/src/content/docs/zh-tw/guides/pi.md
  • docs-site/src/content/docs/zh-tw/guides/providers.md
  • docs-site/src/content/docs/zh-tw/guides/remote-hub.md
  • docs-site/src/content/docs/zh-tw/guides/sidecars.md
  • docs-site/src/content/docs/zh-tw/guides/subagent-v1-default.md
  • docs-site/src/content/docs/zh-tw/guides/web-dashboard.md
  • docs-site/src/content/docs/zh-tw/reference/cli.md
  • docs-site/src/content/docs/zh-tw/reference/cli/agents.md
  • docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md
  • docs-site/src/content/docs/zh-tw/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-tw/reference/configuration/server.md
  • docs-site/src/content/docs/zh-tw/reference/management-api.md
  • docs-site/src/content/docs/zh-tw/reference/proxy-formats.md
  • gui/src/App.tsx
  • gui/src/client-resource.ts
  • gui/src/combo-workspace-data.ts
  • gui/src/components/ClaudeDesktopPicker.tsx
  • gui/src/components/ClaudeFirstPartyBindings.tsx
  • gui/src/components/desktop-star-onboarding.tsx
  • gui/src/components/provider-workspace/ProviderWorkspaceShell.tsx
  • gui/src/components/quota-summary-bar/QuotaSummaryBar.tsx
  • gui/src/components/quota-summary-bar/quota-summary-bar.css
  • gui/src/components/sidebar-github-row.tsx
  • gui/src/host-visibility.ts
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/fr.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/tr.ts
  • gui/src/i18n/vi.ts
  • gui/src/i18n/zh-TW.ts
  • gui/src/i18n/zh.ts
  • gui/src/lib/desktop-shell.ts
  • gui/src/main.tsx
  • gui/src/models-groups.ts
  • gui/src/pages/ClaudeDesktop.tsx
  • gui/src/pages/Combos.tsx
  • gui/src/pages/Models.tsx
  • gui/src/pages/Providers.tsx
  • gui/src/pages/dashboard-dialogs.tsx
  • gui/src/pages/dashboard-overview-sections.tsx
  • gui/src/pages/dashboard-shared.ts
  • gui/src/pages/models-fast-row.tsx
  • gui/src/pages/use-dashboard-data.ts
  • gui/src/provider-icons.ts
  • gui/src/quota-summary.ts
  • gui/src/styles/claude-desktop-mode-picker.css
  • gui/src/styles/claude-desktop-picker.css
  • gui/src/styles/claude-first-party-bindings.css
  • gui/src/styles/star-onboarding.css
  • gui/src/visibility-poll.ts
  • gui/tests/claude-desktop-mode-picker.test.tsx
  • gui/tests/claude-desktop-picker.test.tsx
  • gui/tests/desktop-shell.test.ts
  • gui/tests/desktop-star-onboarding.test.tsx
  • gui/tests/fr-localization.test.ts
  • gui/tests/host-visibility.test.ts
  • gui/tests/locale-parity.test.ts
  • gui/tests/main-account-hard-lock-setting.test.tsx
  • gui/tests/quota-summary.test.ts
  • package.json
  • readme/README.fr.md
  • readme/README.ja.md
  • readme/README.ko.md
  • readme/README.ru.md
  • readme/README.tr.md
  • readme/README.zh-CN.md
  • readme/README.zh-TW.md
  • readme/i18n-manifest.json
  • scripts/generate-windows-tray-update-icons.ts
  • scripts/test-layout/layout.json
  • skills/ocx/references/01_management_surface.md
  • src/adapters/anthropic.ts
  • src/adapters/claude-cli/adapter.ts
  • src/adapters/claude-cli/profiles.ts
  • src/adapters/codebuddy/profiles.ts
  • src/adapters/coding-agent/profile.ts
  • src/adapters/coding-agent/turn.ts
  • src/adapters/command-code-tool-text.ts
  • src/adapters/cursor.ts
  • src/adapters/cursor/catalog.ts
  • src/adapters/cursor/discovery.ts
  • src/adapters/cursor/effort-map.ts
  • src/adapters/cursor/envelope-echo.ts
  • src/adapters/cursor/request-builder.ts
  • src/adapters/cursor/thread-continuity.ts
  • src/adapters/devin/cloud-direct/chat.ts
  • src/adapters/google-tool-schema.ts
  • src/adapters/identity.ts
  • src/adapters/openai-chat.ts
  • src/adapters/openai-chat/passthrough.ts
  • src/adapters/openai-chat/serialized-tool-call-content.ts
  • src/adapters/openai-responses/canonical-forward.ts
  • src/adapters/openai-responses/passthrough.ts
  • src/adapters/openai-responses/request-strips.ts
  • src/adapters/openai-responses/web-search.ts
  • src/adapters/qoder/profiles.ts
  • src/adapters/registry.ts
  • src/adapters/run-turn-queue.ts
  • src/bridge/response-json.ts
  • src/bridge/sse.ts
  • src/claude/alias.ts
  • src/claude/context-windows.ts
  • src/claude/desktop-3p-library.ts
  • src/claude/desktop-3p.ts
  • src/claude/desktop-first-party.ts
  • src/claude/desktop-picker-profile.ts
  • src/claude/desktop-picker.ts
  • src/claude/desktop-risk.ts
  • src/claude/gateway-cache.ts
  • src/claude/inbound.ts
  • src/claude/intercept/connect-proxy.ts
  • src/claude/intercept/local-ca.ts
  • src/claude/intercept/model-bindings.ts
  • src/claude/intercept/picker-bootstrap.ts
  • src/claude/intercept/picker-ca.ts
  • src/claude/intercept/picker-listener.ts
  • src/claude/intercept/picker-models.ts
  • src/claude/intercept/picker-runtime.ts
  • src/claude/intercept/picker-trust.ts
  • src/claude/intercept/runtime.ts
  • src/claude/model-info.ts
  • src/cli/agent.ts
  • src/cli/capabilities.ts
  • src/cli/claude-desktop.ts
  • src/cli/claude.ts
  • src/cli/codex-shim-autorestore.ts
  • src/cli/dispatch.ts
  • src/cli/effort.ts
  • src/cli/ensure-desired-integrations.ts
  • src/cli/ready.ts
  • src/cli/registry.ts
  • src/cli/restart-scope.ts
  • src/cli/runtime-api.ts
  • src/cli/system-command.ts
  • src/client/connect.ts
  • src/client/state.ts
  • src/clients/config-export.ts
  • src/codex/auth-context.ts
  • src/codex/catalog/derive-entry.ts
  • src/codex/catalog/gather-capture.ts
  • src/codex/catalog/metadata.ts
  • src/codex/catalog/parsing.ts
  • src/codex/catalog/provider-models.ts
  • src/codex/catalog/retained-sync.ts
  • src/codex/catalog/sync.ts
  • src/codex/desktop-app-restart.ts
  • src/codex/desktop-switches.ts
  • src/codex/home.ts
  • src/codex/inject.ts
  • src/codex/inject/config-toml.ts
  • src/codex/inject/plan.ts
  • src/codex/inject/remove.ts
  • src/codex/journal.ts
  • src/codex/main-account-hard-lock.ts
  • src/codex/main-account-policy-wait.ts
  • src/codex/native-profile-startup.ts
  • src/codex/native-residue.ts
  • src/codex/quota-types.ts
  • src/codex/quota.ts
  • src/codex/runtime.ts
  • src/combos/failover.ts
  • src/combos/resolve.ts
  • src/combos/types.ts
  • src/config/load-degrade.ts
  • src/config/schema/config-schema.ts
  • src/config/schema/leaf-validators.ts
  • src/config/subagent-models.ts
  • src/images/artifacts.ts
  • src/integrations/owned-refresh.ts
  • src/integrations/ownership-policy.ts
  • src/integrations/state.ts
  • src/integrations/writer.ts
  • src/lib/config-ownership.ts
  • src/lib/errors.ts
  • src/lib/package-tree-integrity.ts
  • src/lib/request-execution-budget.ts
  • src/lib/request-resend-gate.ts
  • src/lib/retry-delay.ts
  • src/lib/tool-envelope-echo-filter.ts
  • src/lib/upstream-retry.ts
  • src/oauth/index.ts
  • src/oauth/kiro-credentials.ts
  • src/oauth/login-cli.ts
  • src/providers/derive.ts
  • src/providers/fast-opt-in.ts
  • src/providers/model-rename-fields.ts
  • src/providers/provider-id-rewrite.ts
  • src/providers/quota/vendor-probes-key.ts
  • src/providers/registry/entries-core.ts
  • src/providers/registry/entries-extended.ts
  • src/providers/registry/model-ids.ts
  • src/providers/registry/types.ts
  • src/providers/resolved-model-policy.ts
  • src/providers/service-tier.ts
  • src/responses/code-mode-helper-compat.ts
  • src/responses/parser.ts
  • src/router.ts
  • src/server/auth-cors.ts
  • src/server/chat-completions.ts
  • src/server/claude-messages.ts
  • src/server/grok-upstream-envelope-echo.ts
  • src/server/index.ts
  • src/server/index/claude-intercept-lifecycle.ts
  • src/server/index/serve-options.ts
  • src/server/management-api.ts
  • src/server/management/agent-settings-routes.ts
  • src/server/management/claude-desktop-picker-routes.ts
  • src/server/management/combo-routes.ts
  • src/server/management/config-routes.ts
  • src/server/management/context.ts
  • src/server/management/native-integration-routes.ts
  • src/server/management/provider-routes.ts
  • src/server/management/route-registry.ts
  • src/server/management/routing-profile-routes.ts
  • src/server/management/sidebar-routes.ts
  • src/server/proxy-liveness.ts
  • src/server/request-log-account-rotation.ts
  • src/server/request-log.ts
  • src/server/responses/adapter-dispatch.ts
  • src/server/responses/agent-task-recovery.ts
  • src/server/responses/codex-ws-exchange.ts
  • src/server/responses/codex-ws-wire.ts
  • src/server/responses/core-combo.ts
  • src/server/responses/core-normalize.ts
  • src/server/responses/core-opaque-recovery.ts
  • src/server/responses/encrypted-payload.ts
  • src/server/responses/fetch-helpers.ts
  • src/server/responses/input-admission.ts
  • src/server/responses/native-response-control.ts
  • src/server/responses/passthrough-delivery.ts
  • src/server/responses/passthrough-dispatch.ts
  • src/server/responses/policy-fallback.ts
  • src/server/responses/policy-refusal.ts
  • src/server/responses/request-send-budget.ts
  • src/server/responses/run-turn-execution.ts
  • src/server/responses/ws-upstream.ts
  • src/server/system-env-shell.ts
  • src/server/system-env.ts
  • src/service/cli.ts
  • src/tray/windows-tray.ps1
  • src/tray/windows.ts
  • src/types.ts
  • src/types/config.ts
  • src/types/provider.ts
  • src/types/tools.ts
  • src/update/async-check.ts
  • src/update/badge.ts
  • src/update/check-types.ts
  • src/update/desktop-badge.ts
  • src/update/index.ts
  • src/update/install-detection.d.mts
  • src/update/install-detection.mjs
  • src/update/job.ts
  • src/update/notify.ts
  • src/update/pnpm-owner-worker.ts
  • src/update/refresh-scheduler.ts
  • src/usage/cost.ts
  • src/usage/expected-prices.ts
  • structure/adapters/registry.md
  • structure/catalog.md
  • structure/clients/claude-desktop.md
  • structure/clients/integrations.md
  • structure/codex-home.md
  • structure/companion.md
  • structure/config.md
  • structure/dashboard-and-usage.md
  • structure/decisions/ADR-5493-linux-packaged-shell-acceptance.md
  • structure/decisions/ADR-5494-lightweight-background-startup.md
  • structure/decisions/ADR-5548-serialized-tool-call-content.md
  • structure/decisions/ADR-5724-serialized-tool-call-content.md
  • structure/desktop-shell.md
  • structure/gui-and-management-api.md
  • structure/ops/docs-and-release.md
  • structure/ops/service-and-sidecars.md
  • structure/providers-and-adapters.md
  • structure/providers/chat-compat.md
  • structure/providers/cursor.md
  • structure/providers/google.md
  • structure/providers/kiro.md
  • structure/providers/openai-tiers.md
  • structure/providers/xai-grok.md
  • structure/runtime.md
  • structure/subagents.md
  • structure/transports/inventory.md
  • structure/transports/responses-failover.md
  • structure/transports/responses-wire-shapes.md
  • structure/transports/responses.md
  • structure/transports/streaming-health.md
  • tests/adapters/abort-race.test.ts
  • tests/adapters/adapter-registry-authority.test.ts
  • tests/adapters/adapter-tool-conformance.test.ts
  • tests/adapters/anthropic/anthropic-compatible-stream.test.ts
  • tests/adapters/anthropic/anthropic-fast-opt-in.test.ts
  • tests/adapters/anthropic/anthropic-fast-speed.test.ts
  • tests/adapters/anthropic/anthropic-parallel-tool-disable.test.ts
  • tests/adapters/google/google-tool-schema.test.ts
  • tests/adapters/identity-subagent.test.ts
  • tests/adapters/key-failover.test.ts
  • tests/adapters/openai/openai-chat-sanitization-review-regressions.test.ts
  • tests/adapters/openai/openai-chat-serialized-tool-call-content.test.ts
  • tests/adapters/openai/openai-chat-serialized-tool-call-hold-bound.test.ts
  • tests/adapters/openai/openai-chat-serialized-tool-call-think.test.ts
  • tests/adapters/run-turn-queue.test.ts
  • tests/adapters/tool-envelope-echo-whole-line.test.ts
  • tests/ci-workflows/build-desktop-icon-set.test.ts
  • tests/ci-workflows/ci-privacy-gate.test.ts
  • tests/ci-workflows/ci-scope-reduction.test.ts
  • tests/ci-workflows/docs-readme-memory-inventory.test.ts
  • tests/ci-workflows/linux-desktop-packaged-ci.test.ts
  • tests/ci-workflows/linux-desktop-packaged-e2e.test.ts
  • tests/ci-workflows/package-tree-integrity.test.ts
  • tests/ci-workflows/pr-readiness-reattest.test.ts
  • tests/ci-workflows/release-desktop-scripts.test.ts
  • tests/claude-integration/claude-agents-inject.test.ts
  • tests/claude-integration/claude-alias.test.ts
  • tests/claude-integration/claude-cli.test.ts
  • tests/claude-integration/claude-code-thought-signature-scope.test.ts
  • tests/claude-integration/claude-context-windows.test.ts
  • tests/claude-integration/claude-desktop-cli.test.ts
  • tests/claude-integration/claude-desktop-discovery.test.ts
  • tests/claude-integration/claude-desktop-first-party-guards.test.ts
  • tests/claude-integration/claude-desktop-first-party.test.ts
  • tests/claude-integration/claude-desktop-mode-explanation.test.ts
  • tests/claude-integration/claude-desktop-picker-profile.test.ts
  • tests/claude-integration/claude-desktop-picker-routes.test.ts
  • tests/claude-integration/claude-desktop-picker.test.ts
  • tests/claude-integration/claude-gateway-cache.test.ts
  • tests/claude-integration/claude-inbound.test.ts
  • tests/claude-integration/claude-intercept-model-bindings.test.ts
  • tests/claude-integration/claude-intercept-proxy.test.ts
  • tests/claude-integration/claude-management-api.test.ts
  • tests/claude-integration/claude-messages-endpoint.test.ts
  • tests/claude-integration/claude-model-info.test.ts
  • tests/claude-integration/claude-models-discovery.test.ts
  • tests/claude-integration/claude-native-passthrough.test.ts
  • tests/claude-integration/claude-picker-bootstrap.test.ts
  • tests/claude-integration/claude-picker-ca.test.ts
  • tests/claude-integration/claude-picker-listener.test.ts
  • tests/claude-integration/claude-picker-models.test.ts
  • tests/claude-integration/claude-picker-runtime.test.ts
  • tests/claude-integration/claude-picker-trust.test.ts
  • tests/cli/cli-capabilities.test.ts
  • tests/cli/cli-effort-slug.test.ts
  • tests/cli/cli-headless-parity.test.ts
  • tests/cli/cli-registry.test.ts
  • tests/cli/cli-update-badge.test.ts
  • tests/clients/aside-profile-paths.test.ts
  • tests/clients/client-connect.test.ts
  • tests/clients/desktop-app-restart-posix.test.ts
  • tests/clients/desktop-app-restart.test.ts
  • tests/clients/desktop-exit-ownership.test.ts
  • tests/clients/desktop-host-visibility.test.ts
  • tests/clients/desktop-runtime-identity.test.ts
  • tests/clients/desktop-startup-surface.test.ts
  • tests/clients/desktop-update-surface.test.ts
  • tests/clients/integrations-hermes-affinity.test.ts
  • tests/clients/omo-client.test.ts
  • tests/clients/prime-client.test.ts
  • tests/codex-integration/catalog-oauth-observation.test.ts
  • tests/codex-integration/catalog-vision-sidecar-modalities.test.ts
  • tests/codex-integration/codex-account-store-refresh-classification.test.ts
  • tests/codex-integration/codex-account-store.test.ts
  • tests/codex-integration/codex-app-server-processes.test.ts
  • tests/codex-integration/codex-catalog-identity-neutral.test.ts
  • tests/codex-integration/codex-catalog-sync-hardening.test.ts
  • tests/codex-integration/codex-catalog.test.ts
  • tests/codex-integration/codex-composed-acceptance.test.ts
  • tests/codex-integration/codex-entitlement-identity-read-fence.test.ts
  • tests/codex-integration/codex-gather-authority.test.ts
  • tests/codex-integration/codex-home-wsl-local-state.test.ts
  • tests/codex-integration/codex-home-wsl.test.ts
  • tests/codex-integration/codex-inject-missing-config.test.ts
  • tests/codex-integration/codex-models-cache-invalidate.test.ts
  • tests/codex-integration/codex-native-residue.test.ts
  • tests/codex-integration/codex-runtime-wsl-desktop.test.ts
  • tests/codex-integration/codex-transition-state-adoption.test.ts
  • tests/codex-integration/codex-web-search-switch.test.ts
  • tests/codex-integration/codex-write-lock.test.ts
  • tests/codex-integration/combo-last-resort.test.ts
  • tests/codex-integration/combos.test.ts
  • tests/codex-integration/configured-native-models.test.ts
  • tests/codex-integration/issue-914-transport-attribution.test.ts
  • tests/codex-integration/main-account-hard-lock-auth.test.ts
  • tests/codex-integration/main-account-hard-lock-default.test.ts
  • tests/codex-integration/main-account-hard-lock-policy.test.ts
  • tests/codex-integration/main-account-hard-lock-recovery.test.ts
  • tests/codex-integration/main-account-policy-binding-wait.test.ts
  • tests/codex-integration/main-quota-evidence-validation.test.ts
  • tests/codex-integration/main-quota-provenance.test.ts
  • tests/codex-integration/main-quota-window-observation.test.ts
  • tests/codex-integration/multi-agent-origin.test.ts
  • tests/codex-integration/native-codex-toggle.test.ts
  • tests/codex-integration/native-profile-startup-release.test.ts
  • tests/codex-integration/slug-codec.test.ts
  • tests/config/client-config-export-new-clients.test.ts
  • tests/config/client-config-export.test.ts
  • tests/config/settings-main-account-hard-lock.test.ts
  • tests/config/settings-stream-mode.test.ts
  • tests/fixtures/pnpm-owner-stall-worker.ts
  • tests/fixtures/test-layout-expected.json
  • tests/gui/combo-workspace-data.test.ts
  • tests/gui/dashboard-sidecar-codex-write.test.ts
  • tests/gui/gui-desktop-sidecar-signing.test.ts
  • tests/helpers/agent-task-recovery.ts
  • tests/helpers/main-account-policy-startup-child.ts
  • tests/helpers/responses-core-source.ts
  • tests/helpers/translator-budget.ts
  • tests/helpers/update-bun-ownership-child.ts
  • tests/helpers/windows-tray-probe-lifecycle-driver.ps1
  • tests/helpers/ws-upstream-fixtures.ts
  • tests/images/download-cap-default.test.ts
  • tests/images/download-connect-deadline-default.test.ts
  • tests/images/loop-reasoning-replay.test.ts
  • tests/images/loop.test.ts
  • tests/images/pinned-https-get.test.ts
  • tests/images/z-fulfill.test.ts
  • tests/images/z-handler-activation.test.ts
  • tests/lab/lab-automation-coderabbit-regressions.test.ts
  • tests/lab/lab-automation-final-coderabbit-regressions.test.ts
  • tests/lab/lab-automation-management-http.test.ts
  • tests/lab/lab-automation-review-regressions.test.ts
  • tests/lab/lab-automation.test.ts
  • tests/lab/lab-evidence-ledger.test.ts
  • tests/lab/lab-evidence-sanitization.test.ts
  • tests/lab/lab-fabric-task.test.ts
  • tests/lab/lab-live-probe.test.ts
  • tests/lab/lab-live-review-regressions.test.ts
  • tests/lab/lab-live-sandbox.test.ts
  • tests/lab/lab-post-merge-hardening.test.ts
  • tests/lab/lab-public-surfaces.test.ts
  • tests/lab/lab-read-surfaces.test.ts
  • tests/lib/ambiguous-resend-composition.test.ts
  • tests/preload.ts
  • tests/providers/alibaba-token-plan-responses-optin.test.ts
  • tests/providers/alibaba-token-plan-wire-defaults.test.ts
  • tests/providers/claude-cli-adapter.test.ts
  • tests/providers/codebuddy-mcp-server.test.ts
  • tests/providers/command-code-tool-text-prose-split.test.ts
  • tests/providers/cursor/cursor-blob.test.ts
  • tests/providers/cursor/cursor-catalog.test.ts
  • tests/providers/cursor/cursor-discovery.test.ts
  • tests/providers/cursor/cursor-envelope-echo-retry.test.ts
  • tests/providers/cursor/cursor-fast-listing.test.ts
  • tests/providers/cursor/cursor-live-transport.test.ts
  • tests/providers/cursor/cursor-tool-continuation.test.ts
  • tests/providers/cursor/cursor-tool-result-invocation.test.ts
  • tests/providers/deepseek-quota-currency.test.ts
  • tests/providers/devin-stated-reset-retry.test.ts
  • tests/providers/github-copilot/github-copilot-wire-defaults.test.ts
  • tests/providers/kiro/kiro-windows-cli-executable-path.test.ts
  • tests/providers/mimo-token-plan-capacity.test.ts
  • tests/providers/muse-spark-web-search-compat.test.ts
  • tests/providers/provider-connection-test.test.ts
  • tests/providers/provider-quota.test.ts
  • tests/providers/provider-registry-parity.test.ts
  • tests/providers/xai/grok-47-build-fast-metadata.test.ts
  • tests/providers/xai/grok-lifecycle.test.ts
  • tests/providers/xai/xai-no-stop.test.ts
  • tests/providers/xai/xai-transport.test.ts
  • tests/responses/chat-completions-pool-mode.test.ts
  • tests/responses/passthrough-grok-upstream-envelope-echo.test.ts
  • tests/responses/responses-anthropic-fast-downgrade.test.ts
  • tests/responses/responses-chat-tool-call-content.test.ts
  • tests/responses/responses-code-mode-goal-helpers.test.ts
  • tests/responses/responses-forward-output-cap.test.ts
  • tests/responses/responses-send-budget-counts.test.ts
  • tests/responses/responses-snapshot-repair-server.test.ts
  • tests/responses/responses-tool-conformance.test.ts
  • tests/responses/ws-ambiguous-resend.test.ts
  • tests/responses/ws-native-injection.test.ts
  • tests/responses/ws-upstream.test.ts
  • tests/routing/combo-management-api.test.ts
  • tests/routing/routing-policy-fallback.test.ts
  • tests/routing/routing-policy-surface-parity.test.ts
  • tests/routing/subagent-roster-migration.test.ts
  • tests/server/agent-task-recovery.test.ts
  • tests/server/cancel-body-on-abort.test.ts
  • tests/server/claude-intercept-integration.test.ts
  • tests/server/companion-settings.test.ts
  • tests/server/config.test.ts
  • tests/server/context-history.test.ts
  • tests/server/errors-adapter-failure.test.ts
  • tests/server/input-admission.test.ts
  • tests/server/loopback-listener-admission.test.ts
  • tests/server/management-api-logs-metrics.test.ts
  • tests/server/management-client-config-route.test.ts
  • tests/server/management-provider-pinsless-validation.test.ts
  • tests/server/management-provider-proto-override.test.ts
  • tests/server/management-provider-upstream-websocket.test.ts
  • tests/server/management-provider-validation.test.ts
  • tests/server/management-route-registry.test.ts
  • tests/server/plaintext-v2-agent-messages-server.test.ts
  • tests/server/probe-timeout-env.test.ts
  • tests/server/replay-refusal-parity.test.ts
  • tests/server/retry-after-429.test.ts
  • tests/server/retry-delay-hardening.test.ts
  • tests/server/server-agent-task-recovery-replay.test.ts
  • tests/server/server-combo-failover-e2e.test.ts
  • tests/server/server-combo-zero-output-failover.test.ts
  • tests/server/server-key-failover-e2e.test.ts
  • tests/server/server-live.test.ts
  • tests/server/server-stop-config-hardening.test.ts
  • tests/server/sidebar-routes.test.ts
  • tests/server/startup-action-control-elevation.test.ts
  • tests/server/system-env.test.ts
  • tests/server/system-routes.test.ts
  • tests/server/update-async-routes.test.ts
  • tests/server/v2-agent-message-failfast.test.ts
  • tests/service/process-state.test.ts
  • tests/service/service-secrets.test.ts
  • tests/service/service-wsl-home-ownership.test.ts
  • tests/update/update-badge.test.ts
  • tests/update/update-desktop-badge.test.ts
  • tests/update/update-job.test.ts
  • tests/update/update-mise-node-runtime.test.ts
  • tests/update/update-mise.test.ts
  • tests/update/update-notify.test.ts
  • tests/update/update-refresh.test.ts
  • tests/usage/key-attribution.test.ts
  • tests/usage/request-log-attempt-identity.test.ts
  • tests/usage/request-log.test.ts
  • tests/usage/usage-cost.test.ts
  • tests/usage/usage-cursor-fast-pricing.test.ts
  • tests/vision/sidecar-settings-web-search-off.test.ts
  • tests/windows/tray-proxy.test.ts
  • tests/windows/windows-tray.test.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants