Skip to content

[WRONG BRANCH] chore(release): promote the verified 2.55.0 product tree to main - #4619

Merged
lidge-jun merged 122 commits into
mainfrom
codex/260914-main-2550
Sep 14, 2026
Merged

[WRONG BRANCH] chore(release): promote the verified 2.55.0 product tree to main#4619
lidge-jun merged 122 commits into
mainfrom
codex/260914-main-2550

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Summary

Promotes the same product tree that shipped as 2.55.0-preview.20260914 (preview tip 7bdd1b29b5) to main as stable 2.55.0. Only package.json version differs from preview; the rest of the tree is byte-identical.

The 2.55.0 line carries the #4546 cost-guard work: one send budget per logical request with a shared final-recovery reserve, zero-is-zero refusals that return a typed local error rather than a synthetic 502, compact and the Kiro inner retries admitted against that budget, a finite send ceiling per root workflow with an interactive reserve a worker fan-out cannot take, and a healthy detour promoted on transient-hold expiry instead of released cold, with Retry-After honoured as a lower bound on the transient path.

What this release does NOT claim

#4546 is not fully resolved. Still open: the durable cross-restart reservation ledger, V2 child first placement, the minimum quota/cache domain contract, the transient half-open probe lease, combo hops on the shared budget, Cursor's inner retries, and sends-per-logical-request surfacing. The release notes must say so rather than announcing a complete fix.

Verification

Preview at the identical tree published successfully: run 34834502951, DRY_RUN: false, real npm publish --tag preview, post-publish registry smoke green, GitHub Release v2.55.0-preview.20260914 at 7bdd1b29b5. Preview push CI 34833399886 completed success with no failing jobs, and service lifecycle 34833399853 succeeded on the same SHA. dev has been pre-moved to 2.56.0 (#4618) so it outranks this release. Local suite NOT RUN by policy.

Checklist

  • Targets main as a release promotion
  • Version-only difference from the published preview tree
  • Local CI — NOT RUN by policy

Summary by CodeRabbit

  • New Features

    • Added configurable catalog auto-refresh and clearer refresh status reporting.
    • Added web-search fallback through configured sidecar providers when ChatGPT forwarding is unavailable.
    • Improved provider compatibility for structured output, images, audio, video, and tool results.
    • Added clearer routing and account-affinity explanations, including move reasons and cache-preserving behavior.
    • Added Windows Codex runtime discovery and routing-adoption status.
  • Bug Fixes

    • Improved retry budgeting, failover handling, search continuation, policy errors, and media validation.
    • Dashboard commands now use the management ingress address when enabled.
  • Documentation

    • Updated multilingual guides, configuration references, and operational documentation.
  • Chores

    • Version updated to 2.55.0.

lidge-jun and others added 30 commits August 25, 2026 19:10
merge dev into preview for the v2.33.0-preview.20260825 release (api-usage oracle fix)
[WRONG BRANCH] release: promote dev to preview for v2.34.0-preview.20260827
[WRONG BRANCH] promote dev onto preview for v2.35.0-preview
[WRONG BRANCH] release: v2.36.0-preview.20260829
`preview` carries its own release-bump commits (`release: v2.36.0-preview.20260829`), which
are not on `dev`, so the promotion cannot fast-forward: `package.json` is the only conflicting
path. Resolved to the version this train publishes, `2.36.0-preview.20260830`, which moves the
`preview` channel forward from the 20260829 tip.

Every other path takes `dev` (`bb6a6fbdf`) unchanged.
[WRONG BRANCH] promote dev onto preview for v2.36.0-preview.20260830
[WRONG BRANCH] promote dev onto preview for v2.38.0-preview.20260831
[WRONG BRANCH] promote dev onto preview for v2.39.0-preview.20260901
release: promote dev to preview for v2.40.0-preview.20260902
…rkflow call (#3262)

Both v2.40.0 release dispatches (33615174183 preview, 33615177849 main) died
at startup_failure: a workflow_call cannot grant its callee more than the
calling job holds, and dev-version-bump.yml's job declares contents+pull-
requests write. #3129 wired the call but never dispatched a release, so this
is its first live run. The caller job now declares exactly the callee's two
permissions; no other job in release.yml gains anything.

Co-authored-by: jun <jun@lidge.dev>
(cherry picked from commit 7ce0ba5)
release: carry the release.yml permissions fix onto preview for v2.40.0-preview.20260902
Brings the reviewed dev head (81a1fc1) onto preview. The only conflict is
package.json's version, resolved to the preview channel's next version rather
than to either side: preview carried 2.40.0-preview.20260902 and dev carries
2.41.0, and neither is what this publish is.

The 37-commit delta since v2.40.0 is reviewed per-commit in
devlog/_plan/260903_muse_release_train/011_review_ledger.md.
[WRONG BRANCH] release: v2.41.0-preview.20260903
[WRONG BRANCH] release: refresh preview onto the audit-clean dev head for v2.41.0-preview.20260903
v2.41.0 published from main while this promotion was in flight, so the preview
line has to move past it: a 2.41.0-preview version is now BEHIND a released
one, which tests/release-version-line.test.ts refuses and npm would refuse
after it.

dev moved to 2.42.0 in #3354, the automatic post-release bump. Preview follows
the same line at 2.42.0-preview.20260903, which is the conflict resolution
here: neither side's value, because neither is what this publish is.

Also brings the three CI timing-flake fixes from #3351, which is what preview
CI failed on twice at 491ffcf.

Preflight: 2.42.0-preview.20260903 unpublished on npm, no v2.42.0* tag, no
GitHub release, and it moves preview forward from 2.40.0-preview.20260902.
[WRONG BRANCH] release: v2.42.0-preview.20260903
…dges

[WRONG BRANCH] release: promote dev onto preview for the main-account badge fix
…view

preview had diverged from main: it carried 28 merge commits main did not have,
while main carried 23 preview did not, so preview could not fast-forward.
The divergence was history only - the sole CONTENT difference between the two
branches was the package.json version line.

This merge takes main (48f8186, the v2.42.0 release commit) into preview and
resolves the tree to main's content, so preview now matches the released tree
exactly apart from its own prerelease version line.

The version could not stay at 2.42.0-preview.20260903: v2.42.0 has published,
and compareReleaseTags ranks that prerelease BEHIND its own stable release
(-1), which is what tests/release-version-line.test.ts fails on. preview opens
the next prerelease line at 2.43.0-preview.20260904, matching dev's 2.43.0.
[WRONG BRANCH] chore(release): promote main v2.42.0 onto preview and open 2.43.0-preview
lidge-jun and others added 20 commits September 14, 2026 15:09
…d agree with preview (#4546) (#4589)

Follow-up to #4580, from review of the merged commit.

P1: preview and resolve disagreed on the FIRST detour. Preview refused to pick one because pickRoundRobinAccount commits and advances the ring, so it returned null and fell through to the ordinary binding while resolve served from a fresh alternate. Subagent fallback scores the previewed account to decide whether a model is reachable, so it could retire a model over usage the request would never touch. Preview now peeks the same candidate through peekAlternateCodexAccount, which delegates for every strategy except round-robin because that is the only branch with a side effect.

P1: when no detour existed the code fell through and deleted the binding. A provider-wide 503 soft-avoids every sibling, which is precisely when the candidate list is empty, so the hold did not cover the failure it was written for. Being unable to send is not the same as forgetting which account owns the conversation: the binding now survives and the bound account is returned, on both the ordinary and model-detour lanes.

reset-first could still move a bound thread onto an account with no usage reading, because hasCodexQuotaHeadroom answers true for unknown. The quota strategy excludes those through its strictly-cooler compare; reset ordering has no such compare and now says it explicitly.
* docs(devlog): record the round 2 outcome and close the delivery unit

Three wave-A lanes landed with one config-schema owner and no collisions. Unit totals: 22 pull requests closed, 13 issues closed, three issues deliberately left open with their landed scope recorded, three follow-ups filed.

* docs(devlog): move the round 2/3 delivery unit to _fin

Both rounds delivered and the closure sweep verified against live GitHub state: 22 pull requests terminal, 13 issues closed, three issues deliberately left open with their landed scope recorded.
… turn (#4595)

* docs(devlog): plan the regression audit and the 2.55.0 release

Names the six source files three separate merges each touched in the dev delta, states that the audit reads the merged state rather than any single diff, and records the one deliberate deviation from the release script preflight along with what covers each skipped check.

* fix(web-search): do not release a withheld client call under a failed turn

A mixed bridge leg whose upstream terminal was response.failed released its withheld client-executed tool call, because the mixed-tool termination change routed both failed and incomplete terminals through the same endWithoutSearch branch and that branch flushes held calls. The failure path ten lines above documents the opposite rule: releasing a tool call the client would start executing is exactly what must not happen under a turn that is already over.

The two terminals differ. An incomplete turn is one the client can still act on, so its held call goes back; a failed turn is over. The decision now carries whether held calls may be released, true only for incomplete, and the emit path drops them otherwise. The hosted cell still closes in both cases, which is what the reordering was for.

Found by a cross-merge regression audit of the dev delta before promotion. Records the audit findings for all five contended file groups alongside the fix.

* docs(devlog): correct the release plan version-line and CI-event facts

preview and main carry two different version lines over the same product tree, because release.yml requires package.json to equal the dispatched version and a preview dispatch must be a prerelease. Only the clean-tree guard and the npm channel-forward check are script-only. And only a push-event CI run on the release branch satisfies the publish gate; a green PR run at the same SHA is refused.

* docs(devlog): write the 2.55.0 release runbook

The exact ordered sequence with the gate gating each step, including the two version lines over one product tree, the push-event CI requirement, the Service lifecycle prerequisite, and the dev move that must precede the stable publish.
…4546) (#4592)

* feat(codex): record why a live binding was kept, moved, or released (#4546)

logCtx.affinity was typed and persisted but never assigned, and routing had no reason to report, so an account move was only visible by comparing account labels across log lines. resolveCodexAccountForThreadDetailed now returns the decision and its cause, the pool auth context carries it, and the usage entry persists both move and reason.

* fix(codex): hoist the affinity decision to the pool context scope

The declaration sat inside the selection block and the spread landed on the main-pool return, so the pool context never carried it and typecheck failed. Reading resolution.affinity through an in-check keeps the fixed-account branch of the union valid.

* fix(codex): report the affinity decision on every selection path

A first placement returned through the active-account retention path, which carried no decision, so the record was missing for exactly the case that establishes a binding. All selection returns now report, and the detailed-resolver assertions move to toMatchObject because the resolution carries a field they did not previously expect.

* fix(codex): carry a release reason from the outcome path to the next resolve

A 429 clears the pin inside recordCodexUpstreamOutcome, so the request that pays for the cold prefix arrived with nothing left to explain why. The reason is now held per thread, bounded, and consumed by that thread next resolve. Two routing cases compared whole resolutions to each other and now compare the account, because a first placement and a later reuse legitimately report different decisions.

* fix(test): compare the account, not the whole resolution, for model detour independence

* fix(test): compare the account for the second model detour lane too

* fix(test): tolerate the affinity decision in the 401 replay resolution check
…d-budget owner (#4602)

* docs(devlog): plan wp4 send budget at diff level

* docs(devlog): correct the wp4 send-budget plan from the audit round

Four claims were wrong: the #2981 helper is not the opt-in part and Codex passthrough gets a fresh allowance per leg; the same-request account resend is retryCodexPoolOnAlternateAccount, not applyFailureFailover; continuation repair is already covered on the policy path while empty-completion, rebuildAndRefetch, compact and generic OAuth hops are not; and Retry-After is already shortened by local caps, so treating it as a lower bound is a behavior change. A 3-send ceiling would also break the 3+1 recovery the plan measured.

* docs(devlog): locate the send-budget owner and why the passthrough escapes it

handleResponses already owns a request-scoped transient budget and documents itself as covering recovery refetches, but the Codex passthrough legs sit in an earlier scope and pass neither attempts nor onSendsConsumed, so each takes a fresh default of 3. That is the source of the measured 4/7/12, and hoisting the owner is the smallest first step.
…oss a no-account resolve (#4598) (#4604)

The release reason re-derived a subset of the selectable guards and fell through to a quota fallback, so paused, plan-excluded, cooled-down and quota-avoided releases named a cause routing never used. It now comes from the same predicates in the same order as isCodexAccountSelectable. Separately, a no-account return carried no payload and the pending reason was consumed before selection, so a release that failed to find a replacement was never recorded; the reason is now reported on that return, handed forward, and forgotten only once reported.
…rough (#4546) (#4605)

* fix(responses): share one transient send budget with the Codex passthrough (#4546)

The budget owner was declared below the passthrough branch, so it was in the temporal dead zone for those four sends and each took the helper fresh default of 3. Hoisting it above the branch and wiring the sends makes one logical request share one transient budget across its recovery legs. The cross-account alternate is untouched because it does not go through the helper, so the 3+1 recovery shape is preserved.

* test(responses): pin the shared transient budget across a sanitized rebuild

The repeated function-output decrypt case sent 6 times (3 on the first leg, a fresh 3 on the rebuild). With the budget shared it sends 4: the rebuild draws on what is left rather than a new allowance. That count is the regression for #4546.

* test(lib): pin the passthrough legs into the shared-budget source oracle

The oracle asserted exactly three legs report into the counter. The four Codex passthrough sends now do too, and the oracle names them plus the transientRetryPolicyFor gate that would silently restore a fresh allowance.
) (#4606)

* feat(logs): surface the account decision in the route explanation (#4546)

The affinity move and its reason were persisted but never exposed, so the record only existed for someone willing to parse usage.jsonl. The route-decision endpoint behind ocx logs explain now carries them, null for rows that have no account decision.

* fix(usage): persist the affinity record the writer was already setting

appendUsageEntry builds the persisted entry from an explicit whitelist, so affinity and affinityReason were dropped on write and #4592 never reached disk. Both are now normalized against known value sets, and a reason is kept only alongside a move.
…#4546) (#4608)

The budget was a counter local to one handleResponsesInner frame, and a combo parent runs a separate child turn per target, so a three-target fan-out took three fresh allowances. It is now a holder on HandleResponsesOptions, minted at genuine ingress and inherited by children through the options spread that already carries comboAttempt and translatorBudget.
…ero (#4546) (#4609)

* fix(responses): one send budget per logical request, and zero means zero (#4546)

Refs #4546. wp4 steps 2-4 of the cost-guard roadmap.

The amplification behind #4546 was never one missing limit. Every layer that can re-send
counted its own allowance, so a per-layer 3 composed into a per-request 12. #4605 and #4608
gave the transient layers one shared counter; this gives that counter a policy.

src/lib/request-execution-budget.ts carries the guarded text-Codex profile: four model sends
per logical request, a base allowance of three shared by the initial send and same-target
retries, and ONE final-recovery reserve that an account move and a validated rebuild share
rather than taking one each. The permit is consumed immediately before the physical send, not
reconciled after the helper returns, because a counter read afterwards cannot stop two legs
that both saw the same remainder.

Zero now means zero. The Math.max(1, ...) floors in remainingTransientSendBudget and in both
retry helpers funded one more send on every recovery leg, which is most of how a bounded
per-leg allowance became an unbounded per-request count. A refused send raises the typed
SendBudgetExhaustedError, which UpstreamRetryEvidenceError no longer wraps and which
transportFailureResponse maps to request_send_budget_exhausted instead of reporting a proxy
decision as a 502 upstream fault.

Where a reusable upstream answer already exists, the refusal happens before that body is
cancelled: the native OAuth 401 replay and the same-target 429 wait now check the remainder in
their own conditions, so an exhausted request returns the real 401 or 429 with its Retry-After
rather than a synthetic 502.

Two holes that survived #4608 are closed. The adapter initial send passed the raw policy on the
argument that nothing had been spent yet, which is false for a combo child: it inherited the
parent's holder and then took a fresh full allowance anyway. And the cross-account move was
bounded by nothing per request -- excludeAccountId excludes only the account that just failed,
and the recovery loop can return after the alternate fails too, so one request could walk the
pool an account at a time.

Deliberately out of scope, recorded rather than hidden: the same-account gated-model 400 ladder
keeps its own maxRetrySends bound; compact, Kiro, Cursor and the generic OAuth hops still hold
their own allowances.

* docs(devlog): record the wp4 slice A audit counterexamples (#4546)

* fix(responses): a consumed dispatch permit refuses the next send (#4546)

Refs #4546. The single-use contract was written but not enforced: every call site discarded the boolean, so a leg that reached its thunk twice -- an adapter that calls its executor again, or a retry shape that re-enters -- got the second send for free. The return now gates the send.
…end budget (#4546) (#4611)

* fix(responses): compact and the Kiro inner retries join the request send budget (#4546)

Refs #4546. PRD R04.

Compact held its own allowance. Its normal send took a fresh transient three, the stored-pool
401 replay added one, and the 429 alternate added another -- and the guard meant to make those
last two mutually exclusive keys on kind === 'pool', so a main-pool credential left it false and
really could reach five. The recursive handoff child then forwarded the options object without a
holder and minted its own, so one logical compact could reach ten. It now draws the shared
remainder for the ladder and spends base-then-reserve for each single send, and the handoff child
inherits the holder explicitly.

Kiro was the larger multiplier. It nests a three-round throttle loop over a three-attempt reset
ladder that can itself run twice per round, so one adapter entry could be eighteen upstream
requests, and the text-fallback rebuild constructed a fresh context that dropped whatever core
passed. AdapterFetchContext now carries an optional budget, every physical send inside the reset
ladder is admitted against it, and the fallback rebuild carries it forward. The field is optional
and unlimited when absent so an adapter unit test that calls the transport context-free keeps its
own retry shape.

Deliberately still out of scope: Cursor rides IncomingMeta rather than AdapterFetchContext, the
compact routed fallback mints a fresh budget, and the generic OAuth hops keep their own
per-request failover counters.

* style(responses): align the sendBudget field with its sibling context keys (#4546)
Refs #4546. PRD R05/wp5, first slice.

The per-request budget bounds how many times one request reaches upstream. It cannot bound a
fan-out: a worker that spawns seven hundred children, each sending exactly once, never violates a
per-request cap and still spends the account. That is the second half of the incident.

src/lib/workflow-budget.ts tracks the root workflow -- the user-visible task, identified by the
parent thread header -- and gives it a finite physical-send ceiling. Every send charged to the
request budget is charged to the root as well, including the cross-account move, and a root that
has spent its ceiling is refused before dispatch with workflow_budget_exhausted rather than a
synthetic upstream error.

An exhausted root is never evicted to make room. Dropping a live entry would hand the fan-out a
fresh allowance, which is precisely the laundering the ceiling exists to stop, so eviction skips
any root with work in flight.

The ledger is process-local and in-memory. It bounds a single proxy process honestly and says
nothing about a second process sharing the same account pool; that needs a shared durable store
and is declared out of scope rather than implied. The concurrency ceiling and the interactive
reserve are implemented in the module but not yet wired, because they need a release path tied to
the turn lease.
…4546) (#4613)

Refs #4546. Forward fix for the gates failure on 1abc5cc.

HandleResponsesOptions.sendBudget is typed as the narrow TransientSendBudget holder so a caller
that predates the execution budget can still pass one. AdapterFetchContext needs the full
contract, because an adapter that retries internally has to call reserveDispatch. Passing the
narrowed value straight through failed typecheck at all three fetchResponse literals. Narrow it
once next to the other budget helpers instead of asserting at each call site; an adapter that
receives undefined keeps its own retry shape, which is the documented optional behaviour.
…) (#4614)

Refs #4546. PRD R06/wp5, second slice, completing the module landed in #4612.

A fan-out shares the conversation it serves. Without a reserve, a worker burst takes every
concurrency slot under its own root and the interactive turn that started it waits behind its own
children. runAdmittedHttpTurn now admits each turn against the root workflow as well as the
process-wide turn gate: a request that names a parent thread distinct from its own is treated as
that fan-out and may not take the reserved slots, while a top-level request is the conversation
and may.

The refusal is a local queue-capacity answer, not a synthetic upstream error, and the lease is
released on both the normal and the throwing path so a failed turn cannot leak a slot.
…our Retry-After (#4546) (#4616)

* fix(codex): promote a healthy detour instead of releasing it, and honour Retry-After (#4546)

Refs #4546. PRD R07.

When a transient hold outlived its window, routing deleted the whole affinity entry -- including
the detour account that had actually been serving the thread -- and re-picked cold. The timer
expiring restores the right to re-decide; it is not itself a recovery, and treating it as one
threw away the single piece of evidence the request had. A still-healthy detour is now promoted
to the binding instead, with the move recorded as rebound/transient_hold_expired so the reason is
visible. A detour that has itself gone unhealthy still falls through to the cold path.

Retry-After is a lower bound on the transient path. The local maximum delay bounds our own
exponential backoff and has no business shortening a wait the provider stated: sending early is a
request we already know will be refused, which is the storm the header exists to prevent. It is
opt-in per caller so the change lands on the transient path first rather than silently lengthening
every adapter's backoff, and an honoured wait is ceilinged at one minute so an hour-long
Retry-After cannot park a request.

* docs(devlog): record the R07 detour-promotion outcome (#4546)
Promotes the dev product snapshot 62f0222 to the preview train.

The 2.55.0 line carries the #4546 cost-guard work: one send budget per logical request with a
shared final-recovery reserve, zero-is-zero refusals with a typed error rather than a synthetic
502, compact and the Kiro inner retries admitted against that budget, a finite send ceiling per
root workflow with an interactive reserve a fan-out cannot take, and a healthy detour promoted on
transient-hold expiry instead of released cold.

The previous preview tip 2.54.0-preview.20260914 is already tagged and published and is outranked
by v2.54.0, so it could not be re-released; this is a new candidate rather than a re-cut.
[WRONG BRANCH] chore(release): promote 2.55.0-preview.20260914 to preview
Same product tree as preview 7bdd1b2 / 2.55.0-preview.20260914, which published successfully with its registry smoke green. Only package.json version differs.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 14, 2026 10:48
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 14, 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-14T10:50:04.681454Z f978400 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 1cc89cf into main Sep 14, 2026
16 of 17 checks passed
@lidge-jun
lidge-jun deleted the codex/260914-main-2550 branch September 14, 2026 10:48
@github-actions github-actions Bot added the chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature). label Sep 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: f4f1793d-abcc-4fcd-9731-31f8c812e0aa

📥 Commits

Reviewing files that changed from the base of the PR and between 9f7397e and f978400.

⛔ Files ignored due to path filters (1)
  • src/generated/model-metadata.ts is excluded by !**/generated/**
📒 Files selected for processing (292)
  • devlog/_fin/260913_contributor_carry_train/000_plan.md
  • devlog/_fin/260913_contributor_carry_train/001_candidate_inventory.md
  • devlog/_fin/260913_contributor_carry_train/010_wave1.md
  • devlog/_fin/260913_contributor_carry_train/011_wave1_outcome.md
  • devlog/_fin/260913_contributor_carry_train/020_wave1_merge.md
  • devlog/_fin/260913_contributor_carry_train/030_wave2.md
  • devlog/_fin/260913_contributor_carry_train/040_wave2_merge_regression.md
  • devlog/_fin/260913_contributor_carry_train/050_disposition.md
  • devlog/_fin/260913_contributor_carry_train/060_outcome.md
  • devlog/_fin/260914_round23_delivery_roadmap/000_roadmap.md
  • devlog/_fin/260914_round23_delivery_roadmap/010_lane_assignments.md
  • devlog/_fin/260914_round23_delivery_roadmap/020_merge_and_closure_policy.md
  • devlog/_fin/260914_round23_delivery_roadmap/030_round1_dispatch.md
  • devlog/_fin/260914_round23_delivery_roadmap/040_round1_outcome.md
  • devlog/_fin/260914_round23_delivery_roadmap/050_round2_outcome.md
  • devlog/_fin/260914_triage_round_lanes/000_plan.md
  • devlog/_fin/260914_triage_round_lanes/010_wp2_round1.md
  • devlog/_fin/260914_triage_round_lanes/020_wp3_round2.md
  • devlog/_fin/260914_triage_round_lanes/030_wp4_closure.md
  • devlog/_fin/260914_triage_round_lanes/040_outcome.md
  • devlog/_plan/260914_carry_pr4528/000_plan.md
  • devlog/_plan/260914_carry_pr4528/010_phase1.md
  • devlog/_plan/260914_cost_guard_stabilization/000_unit.md
  • devlog/_plan/260914_cost_guard_stabilization/010_bound_binding_policy.md
  • devlog/_plan/260914_cost_guard_stabilization/020_backoff_preserves_binding.md
  • devlog/_plan/260914_cost_guard_stabilization/030_move_reason_evidence.md
  • devlog/_plan/260914_cost_guard_stabilization/040_send_budget.md
  • devlog/_plan/260914_cost_guard_stabilization/050_worker_isolation.md
  • devlog/_plan/260914_cost_guard_stabilization/060_quota_cache_domains.md
  • devlog/_plan/260914_cost_guard_stabilization/070_delivery.md
  • devlog/_plan/260914_cost_guard_stabilization/080_codex_cache_reinforcement.md
  • devlog/_plan/260914_l2_pool_routing_cache/000_unit.md
  • devlog/_plan/260914_l2_pool_routing_cache/010_cache_safe_rebind.md
  • devlog/_plan/260914_l2_pool_routing_cache/020_routing_adoption.md
  • devlog/_plan/260914_l2_pool_routing_cache/030_delivery.md
  • devlog/_plan/260914_l4_responses_media/010_roadmap.md
  • devlog/_plan/260914_l5_provider_account_edges/000_plan.md
  • devlog/_plan/260914_l5_provider_account_edges/010_wp1_account_lifecycle_edges.md
  • devlog/_plan/260914_l7_web_search_bridge/000_plan.md
  • devlog/_plan/260914_l7_web_search_bridge/010_mixed_tool_continuation.md
  • devlog/_plan/260914_l7_web_search_bridge/020_alpha_search_fallback.md
  • devlog/_plan/260914_provider_parity_stack/000_plan.md
  • devlog/_plan/260914_provider_parity_stack/001_audit_evidence.md
  • devlog/_plan/260914_provider_parity_stack/002_architect_dispositions.md
  • devlog/_plan/260914_provider_parity_stack/003_blocker_corrections.md
  • devlog/_plan/260914_provider_parity_stack/010_phase1_ingress_normalization.md
  • devlog/_plan/260914_provider_parity_stack/020_phase2_chat_responses_controls.md
  • devlog/_plan/260914_provider_parity_stack/030_phase3_provider_wire_contracts.md
  • devlog/_plan/260914_provider_parity_stack/040_phase4_modality_fidelity.md
  • devlog/_plan/260914_provider_parity_stack/050_residuals.md
  • devlog/_plan/260914_provider_parity_stack/060_direct_media_guard.md
  • devlog/_plan/260914_r2l8_catalog_autorefresh/010_roadmap.md
  • devlog/_plan/260914_r2l8_catalog_autorefresh/020_issue_3377_capability_audit.md
  • devlog/_plan/260914_regression_audit_and_release/000_audit_and_release_plan.md
  • devlog/_plan/260914_regression_audit_and_release/010_audit_findings.md
  • devlog/_plan/260914_regression_audit_and_release/020_release_runbook.md
  • docs-site/src/content/docs/fr/guides/combos.md
  • docs-site/src/content/docs/fr/guides/remote-hub.md
  • docs-site/src/content/docs/fr/guides/web-dashboard.md
  • docs-site/src/content/docs/fr/reference/cli/lifecycle.md
  • docs-site/src/content/docs/fr/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/fr/reference/configuration/providers.md
  • docs-site/src/content/docs/guides/combos.md
  • docs-site/src/content/docs/guides/pi.md
  • docs-site/src/content/docs/guides/remote-hub.md
  • docs-site/src/content/docs/guides/sidecars.md
  • docs-site/src/content/docs/guides/web-dashboard.md
  • docs-site/src/content/docs/ja/guides/combos.md
  • docs-site/src/content/docs/ja/guides/remote-hub.md
  • docs-site/src/content/docs/ja/guides/web-dashboard.md
  • docs-site/src/content/docs/ja/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ja/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/guides/combos.md
  • docs-site/src/content/docs/ko/guides/remote-hub.md
  • docs-site/src/content/docs/ko/guides/web-dashboard.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/reference/adapters.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/providers.md
  • docs-site/src/content/docs/ru/guides/combos.md
  • docs-site/src/content/docs/ru/guides/remote-hub.md
  • docs-site/src/content/docs/ru/guides/web-dashboard.md
  • docs-site/src/content/docs/ru/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ru/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/tr/guides/combos.md
  • docs-site/src/content/docs/tr/guides/remote-hub.md
  • docs-site/src/content/docs/tr/guides/web-dashboard.md
  • docs-site/src/content/docs/tr/reference/cli/lifecycle.md
  • docs-site/src/content/docs/tr/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/tr/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/guides/combos.md
  • docs-site/src/content/docs/zh-cn/guides/remote-hub.md
  • docs-site/src/content/docs/zh-cn/guides/web-dashboard.md
  • docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md
  • docs-site/src/content/docs/zh-cn/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-tw/guides/combos.md
  • docs-site/src/content/docs/zh-tw/guides/remote-hub.md
  • docs-site/src/content/docs/zh-tw/guides/web-dashboard.md
  • docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md
  • docs-site/src/content/docs/zh-tw/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/zh-tw/reference/configuration/providers.md
  • docs/superpowers/plans/2026-08-14-cl10-final-review-closure.md
  • 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/zh-TW.ts
  • gui/src/i18n/zh.ts
  • gui/tests/account-pool-strategy.test.tsx
  • gui/tests/codex-account-auto-switch.test.tsx
  • package.json
  • scripts/generate-model-metadata.ts
  • scripts/test-layout/layout.json
  • skills/ocx/SKILL.md
  • skills/ocx/references/03_recipes.md
  • skills/ocx/references/05_remote_hub.md
  • src/adapters/anthropic-image-codec.ts
  • src/adapters/anthropic-image-normalize.ts
  • src/adapters/anthropic.ts
  • src/adapters/base.ts
  • src/adapters/coding-agent/protocol.ts
  • src/adapters/cursor/cursor-errors.ts
  • src/adapters/cursor/live-transport.ts
  • src/adapters/cursor/native-exec-fs.ts
  • src/adapters/cursor/native-exec-network.ts
  • src/adapters/cursor/native-exec-shell.ts
  • src/adapters/cursor/native-exec.ts
  • src/adapters/cursor/policy-error.ts
  • src/adapters/cursor/protobuf-request.ts
  • src/adapters/devin/cloud-direct/catalog.ts
  • src/adapters/devin/live-models.ts
  • src/adapters/google-wire-compiler.ts
  • src/adapters/google.ts
  • src/adapters/input-media-guard.ts
  • src/adapters/kiro-events.ts
  • src/adapters/kiro-images.ts
  • src/adapters/kiro-retry.ts
  • src/adapters/kiro/adapter.ts
  • src/adapters/kiro/payload.ts
  • src/adapters/openai-chat.ts
  • src/adapters/openai-responses.ts
  • src/adapters/registry.ts
  • src/bridge.ts
  • src/chat/image-parts.ts
  • src/chat/inbound.ts
  • src/cli/connect.ts
  • src/cli/dispatch.ts
  • src/cli/index.ts
  • src/cli/runtime-api.ts
  • src/cli/status.ts
  • src/cli/system-restart-client.ts
  • src/clients/config-export.ts
  • src/codex/app-server-processes.ts
  • src/codex/auth-context.ts
  • src/codex/autostart-health.ts
  • src/codex/catalog-auto-refresh.ts
  • src/codex/catalog-refresh-status.ts
  • src/codex/catalog/provider-fetch.ts
  • src/codex/history-provider.ts
  • src/codex/model-entitlements.ts
  • src/codex/native-profile-processes.ts
  • src/codex/prompt-text-probe.ts
  • src/codex/routing-adoption.ts
  • src/codex/routing.ts
  • src/codex/runtime.ts
  • src/combos/failover.ts
  • src/config.ts
  • src/lib/request-execution-budget.ts
  • src/lib/upstream-retry.ts
  • src/lib/workflow-budget.ts
  • src/oauth/devin.ts
  • src/providers/quota.ts
  • src/providers/registry.ts
  • src/responses/input-media.ts
  • src/responses/parser-content.ts
  • src/responses/schema.ts
  • src/server/audio-live.ts
  • src/server/audio-transcriptions.ts
  • src/server/auth-cors.ts
  • src/server/background-lifecycle.ts
  • src/server/chat-completions.ts
  • src/server/chat-native.ts
  • src/server/index.ts
  • src/server/management/request-history-routes.ts
  • src/server/request-log.ts
  • src/server/responses/compact.ts
  • src/server/responses/core.ts
  • src/server/search.ts
  • src/types/config.ts
  • src/usage/log.ts
  • src/vision/eligibility.ts
  • src/vision/index.ts
  • src/vision/plan.ts
  • src/web-search/alpha-search.ts
  • src/web-search/index.ts
  • src/web-search/passthrough-bridge.ts
  • src/web-search/sidecar-providers.ts
  • structure/adapters/registry.md
  • structure/catalog.md
  • structure/clients/claude-desktop.md
  • structure/codex-home.md
  • structure/config.md
  • structure/data-planes/inbound-compat.md
  • structure/data-planes/search.md
  • structure/gui-and-management-api.md
  • structure/ops/docs-and-release.md
  • structure/ops/service-and-sidecars.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/transports/byte-accounting.md
  • structure/transports/inventory.md
  • structure/transports/responses.md
  • tests/adapters/adapter-input-media-guard.test.ts
  • tests/adapters/anthropic/anthropic-compatible-stream.test.ts
  • tests/adapters/anthropic/anthropic-error-stop-reason.test.ts
  • tests/adapters/anthropic/anthropic-image-normalize.test.ts
  • tests/adapters/anthropic/anthropic-parallel-tool-disable.test.ts
  • tests/adapters/anthropic/anthropic-reasoning.test.ts
  • tests/adapters/bridge.test.ts
  • tests/adapters/coding-agent-tool-result-images.test.ts
  • tests/adapters/google/google-structured-output.test.ts
  • tests/adapters/openai/openai-chat-native-policy.test.ts
  • tests/adapters/openai/openai-chat-video-part.test.ts
  • tests/cli/cli-connect-readiness.test.ts
  • tests/cli/cli-dispatch.test.ts
  • tests/cli/route-explainability.test.ts
  • tests/cli/system-restart-client.test.ts
  • tests/codex-integration/bearer-admission-routed-provider.test.ts
  • tests/codex-integration/catalog-auto-refresh-scheduler.test.ts
  • tests/codex-integration/catalog-seed-window-fill.test.ts
  • tests/codex-integration/codex-auth-context.test.ts
  • tests/codex-integration/codex-catalog-refresh-status.test.ts
  • tests/codex-integration/codex-history-provider.test.ts
  • tests/codex-integration/codex-model-entitlements.test.ts
  • tests/codex-integration/codex-pool-rotation.test.ts
  • tests/codex-integration/codex-prompt-text-probe.test.ts
  • tests/codex-integration/codex-routing.test.ts
  • tests/codex-integration/codex-runtime.test.ts
  • tests/codex-integration/codex-sync-api.test.ts
  • tests/config/config-catalog-auto-refresh.test.ts
  • tests/fixtures/test-layout-expected.json
  • tests/lab/lab-community-mutation-lock.test.ts
  • tests/lab/lab-public-surfaces.test.ts
  • tests/lib/transient-budget-scope-source.test.ts
  • tests/lib/upstream-retry.test.ts
  • tests/providers/cursor/cursor-live-transport.test.ts
  • tests/providers/cursor/cursor-native-exec-policy.test.ts
  • tests/providers/cursor/cursor-tool-result-invocation.test.ts
  • tests/providers/devin-adapter.test.ts
  • tests/providers/devin-live-models.test.ts
  • tests/providers/devin-login.test.ts
  • tests/providers/flash-route-image-modalities.test.ts
  • tests/providers/kiro/kiro-remote-image.test.ts
  • tests/providers/kiro/kiro-stream.test.ts
  • tests/providers/provider-account-quota.test.ts
  • tests/responses/chat-completions-endpoint.test.ts
  • tests/responses/chat-inbound-reasoning-none.test.ts
  • tests/responses/chat-inbound-reasoning-replay.test.ts
  • tests/responses/chat-media-translation.test.ts
  • tests/responses/chat-native-image-normalization.test.ts
  • tests/responses/chat-responses-control-integration.test.ts
  • tests/responses/chat-responses-control-scope.test.ts
  • tests/responses/parser-content-audio.test.ts
  • tests/responses/responses-compaction-routing.test.ts
  • tests/responses/responses-forward-prompt-envelope.test.ts
  • tests/responses/responses-opaque-blob-recovery.test.ts
  • tests/responses/responses-pool-401-refresh.test.ts
  • tests/routing/router-combo-failover-classification.test.ts
  • tests/server/audio-dictation.test.ts
  • tests/server/audio-transcriptions.test.ts
  • tests/server/server-combo-failover-e2e.test.ts
  • tests/server/server-search.test.ts
  • tests/service/autostart-health.test.ts
  • tests/vision/vision-cache.test.ts
  • tests/vision/vision-eligibility.test.ts
  • tests/vision/vision-routed.test.ts
  • tests/vision/vision-sidecar-e2e.test.ts
  • tests/web-search/web-search-passthrough-bridge.test.ts

📝 Walkthrough

Walkthrough

This PR bundles cost-guard account-affinity routing (src/codex/routing.ts), request send-budget infrastructure (src/lib/request-execution-budget.ts, upstream-retry.ts, workflow-budget.ts), catalog auto-refresh scheduling, Codex runtime resolution improvements, provider parity fixes (vision, media, Anthropic, Google, Cursor, Devin, web-search bridge), combo failover classification, and a bridge string-accumulation refactor, plus extensive locale docs and delivery-process devlogs.

Changes

Cost-Guard Routing and Send-Budget Infrastructure

Layer / File(s) Summary
Account affinity and move-reason logging
src/codex/routing.ts, src/codex/auth-context.ts, src/server/request-log.ts, src/usage/log.ts, src/server/management/request-history-routes.ts, tests/codex-integration/codex-routing.test.ts, tests/codex-integration/codex-pool-rotation.test.ts, tests/codex-integration/codex-auth-context.test.ts, tests/cli/route-explainability.test.ts, tests/responses/responses-pool-401-refresh.test.ts
pool.cacheAffinity now defaults to true. A transient-failure streak detours a bound thread to another account without releasing the binding, and holds expire after CODEX_TRANSIENT_AFFINITY_HOLD_MS (10 min). Every resolution now reports a CodexAffinityDecision (move+reason), persisted to usage logs and surfaced in the route-decision API.
Request send-budget and workflow admission
src/lib/request-execution-budget.ts, src/lib/upstream-retry.ts, src/lib/workflow-budget.ts, src/server/responses/core.ts, src/server/responses/compact.ts, src/server/index.ts, tests/lib/*.test.ts, tests/responses/responses-opaque-blob-recovery.test.ts, tests/responses/responses-forward-prompt-envelope.test.ts
A shared per-logical-request send budget (base 3, +1 final-recovery reserve, 1 cross-account) is created at ingress and inherited by retries, account failover, combo children, and opaque-blob recovery. Exhaustion now returns 429 request_send_budget_exhausted instead of a synthetic 502. Retry-After can act as a lower bound. Root-workflow fan-out is admitted via admitWorkflowTurn.
Catalog auto-refresh, config schema, and entitlement budgets
src/codex/catalog-auto-refresh.ts, src/codex/catalog-refresh-status.ts, src/config.ts, src/types/config.ts, src/server/background-lifecycle.ts, src/codex/model-entitlements.ts, src/codex/catalog/provider-fetch.ts, tests/codex-integration/catalog-*.test.ts, tests/config/config-catalog-auto-refresh.test.ts
A new opt-in catalogAutoRefresh scheduler periodically re-converges the model catalog. model-entitlements.ts bounds per-account caller-selected version misses. provider-fetch.ts seeds registry context-window/max-output-token defaults into unconfigured providers.
Codex runtime resolution and CLI readiness
src/codex/runtime.ts, src/codex/prompt-text-probe.ts, src/codex/native-profile-processes.ts, src/codex/app-server-processes.ts, src/codex/routing-adoption.ts, src/codex/autostart-health.ts, src/codex/history-provider.ts, src/cli/*.ts, tests/codex-integration/codex-runtime.test.ts, tests/cli/cli-connect-readiness.test.ts
runtime.ts adds Windows/Unix installed-Codex discovery and a pinned-vs-discovered origin so unpinned selections yield to newer installs. routing-adoption.ts distinguishes clients that started before vs. after route injection. Terminal output is now escaped via terminalSafeText/terminalSafeError.

Provider Parity, Media, Web-Search, and Adapter Fixes

Layer / File(s) Summary
Vision capability and chat media normalization
src/vision/*.ts, src/chat/image-parts.ts, src/chat/inbound.ts, src/server/chat-completions.ts, src/server/chat-native.ts, src/adapters/anthropic*.ts, src/adapters/google*.ts, src/adapters/openai-chat.ts, src/adapters/openai-responses.ts, src/adapters/input-media-guard.ts, src/adapters/registry.ts, src/adapters/coding-agent/protocol.ts, src/adapters/kiro*.ts, src/responses/parser-content.ts, src/responses/schema.ts, src/responses/input-media.ts, matching test files
Vision admission is now capability-driven instead of noVisionModels-only. Chat image parts are normalized before routing. Anthropic maps refusal/content_filter to non-retryable incomplete events and encodes parallelToolCalls:false. Google forwards structured output. Untranslatable audio/file inputs are rejected explicitly instead of silently dropped.
Web-search bridge sidecar fallback
src/web-search/*.ts, src/server/search.ts, tests/web-search/*.test.ts, tests/server/server-search.test.ts
/v1/alpha/search now falls back to a configured webSearchSidecar backend when no ChatGPT forward provider exists. Mixed web_search + client-tool legs now run the search proxy-side and release the held client call instead of failing closed.
Cursor adapter policy hints and replay budget
src/adapters/cursor/*.ts, tests/providers/cursor/*.test.ts
Denied native exec now redirects to the actual catalog tool names, Cursor's Fable policy gate is decoded and explained, and a second pass refunds spare envelope bytes to restore clipped tool-result invocation arguments.
Devin OAuth alias resolution and Antigravity quota
src/oauth/devin.ts, src/providers/quota.ts, src/adapters/devin/*.ts, src/providers/registry.ts, tests/providers/devin-*.test.ts
resolveDevinApiServer now checks the literal credential slot before falling back to alias slots. Devin catalog rows carry a supportsImages tri-state. Antigravity quota probing preserves the more specific network-policy diagnosis.
Combo failover classification and bridge refactor
src/combos/failover.ts, src/bridge.ts, matching tests
Structured 400 rejections of user/reasoning-effort/image-input parameters now hop without cooldown. bridge.ts replaces paired text/byte counters with a StringChunks accumulator (no wire-format change).
Server outcome-recording fixes
src/server/audio-live.ts, src/server/audio-transcriptions.ts, src/server/auth-cors.ts, tests/lab/*.test.ts
Live/transcription relay outcomes now record the real upstream status instead of a fabricated 502.

Documentation and Delivery Records

Layer / File(s) Summary
Delivery devlogs
devlog/_fin/*, devlog/_plan/*
New planning and outcome records for contributor-carry, round-23 delivery, triage rounds, cost-guard stabilization, and provider-parity-stack units.
Docs-site locale updates, GUI i18n, structure docs, and skills
docs-site/**, gui/src/i18n/*.ts, structure/**, skills/ocx/**
Multi-locale docs and GUI strings updated for cache-affinity defaults and combo-hop behavior; structure/ SSOT docs synced; hub-invite skill docs updated for secret-handoff safety.
Misc support
package.json, scripts/*, tests/fixtures/test-layout-expected.json
Version bump to 2.55.0, generated-metadata capability-only bundle list, and test-layout fixture updates.

Estimated code review effort: 5 (Critical) | ~240 minutes

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/260914-main-2550

Warning

Tools execution failed with the following error:

Failed to run tools: 14 UNAVAILABLE: Connection dropped


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

❤️ Share

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

@github-actions github-actions Bot changed the title chore(release): promote the verified 2.55.0 product tree to main [WRONG BRANCH] chore(release): promote the verified 2.55.0 product tree to main Sep 14, 2026
@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

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

What to do

  • Retarget this PR to dev — all contributions go to dev.
  • Add a screenshot of the UI change to the PR description.

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

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 76 / 80

설명

이 PR은 이미 퍼블리시된 미리보기 태그 v2.55.0-preview.20260914 (트리 tip 7bdd1b29b5) 와 같은 제품 트리를 main 으로 올려 정식 2.55.0 을 찍는 릴리즈 승격 PR입니다. 미리보기와 다른 점은 package.json 의 version 한 줄뿐이고, GitHub compare 상으로도 미리보기 태그 대비 파일 차이는 package.json 뿐입니다. 리뷰를 쓰는 시점에는 이미 lidge-jun이 병합했고, main tip은 merge commit 1cc89cf88 이며 package.json2.55.0 입니다.

지금 로컬 dev HEAD는 626b0f932 (#4618) 이고, package.json 은 이미 2.56.0 입니다. origin/main..origin/dev 차이는 그 버전 오픈 커밋 하나뿐입니다. 즉 이 승격이 끝난 뒤 dev 는 다음 열차(2.56) 슬롯만 열어 둔 상태이고, 2.55.0 제품 코드 자체는 maindev 가 같은 줄기에 있습니다. 그래서 이 PR을 dev 기능 PR처럼 라인 단위로 재검토할 대상은 아니고, “미리보기에서 검증된 트리를 정식 채널에 올리는 순서·증거·남은 약속”을 확인하는 릴리즈 리뷰입니다.

본문이 말하는 2.55.0 라인의 핵심은 #4546 cost-guard 묶음입니다. 논리 요청당 하나의 send budget과 shared final-recovery reserve, 예산 0이면 typed local error(SendBudgetExhaustedError)로 거절, compact·Kiro 내부 재시도를 그 예산에 포함, 루트 워크플로당 유한 send ceiling과 worker fan-out이 빼앗지 못하는 interactive reserve, transient hold 만료 시 healthy detour promote, Retry-After 를 하한으로 존중하는 경로가 그 줄기입니다. 이 코드들은 이미 dev#4605~#4616 등으로 들어온 뒤 미리보기로 나갔고, 이번 PR은 그 트리를 main 에 올리는 일만 합니다.

검증 쪽은 본문 기준으로 미리보기 퍼블리시 run 34834502951(DRY_RUN: false, 실제 npm publish --tag preview), 레지스트리 스모크, GitHub Release v2.55.0-preview.20260914 @ 7bdd1b29b5, preview push CI 34833399886 성공, service lifecycle 34833399853 성공입니다. 로컬 스위트는 정책상 NOT RUN입니다. 릴리즈 트레인 관점에서 미리보기 실퍼블리시 증거가 있으면 정식 승격의 최소 조건은 대체로 충족됩니다.

다만 품질 게이트가 이 PR을 일반 기여 PR처럼 취급했습니다. enforce-targetwrong base (main); missing UI screenshot 으로 실패했고, 봇이 제목에 [WRONG BRANCH] 접두를 붙인 채 게이트 댓글로 “dev 로 리타겟하라 / UI 스크린샷을 넣어라”고 적었습니다. 릴리즈 승격 PR은 main 이 올바른 베이스입니다. 병합은 이미 끝났지만, 기록상 게이트 오탐이 남았고 브랜치 이름 codex/260914-main-2550 도 2.55.0을 2550으로 줄인 표기라 나중에 로그를 볼 때 헷갈릴 수 있습니다.

본문이 스스로 밝히는 한계도 중요합니다. #4546 은 아직 닫히지 않았고, durable cross-restart reservation ledger, V2 child first placement, minimum quota/cache domain contract, half-open probe lease, combo hops on shared budget, Cursor inner retries, sends-per-logical-request 표면화 등이 남아 있습니다. 정식 2.55.0 릴리즈 노트/설명에 “cost-guard 일부 착지, 완결 아님”을 분명히 써야 사용자·기여자에게 과대 약속이 되지 않습니다.

경로/심볼 - 문제

경로 package.json - 미리보기 2.55.0-preview.20260914 → 정식 2.55.0 한 줄 차이. 트리 동일성 주장은 compare와 맞음. 지금 main2.55.0 이라 승격 자체는 완료된 상태로 보임.

경로 codex/260914-main-2550 (브랜치명) - 버전 표기가 2550이라 2.55.0과 숫자가 어긋남. 기능 버그는 아니지만 태그·런북·감사 추적 때 혼동 여지.

경로 enforce-target / 게이트 댓글 - main 타깃 릴리즈 승격을 “wrong base”로 판정하고 UI 스크린샷을 요구함. 이 PR 유형에 대한 예외(release promote → main)가 게이트에 없거나 인식되지 않은 오탐. 제목의 [WRONG BRANCH] 접두는 그 결과물.

이슈 #4546 / 릴리즈 노트 범위 - 코드는 cost-guard 중간 착지를 실어 나르지만 에픽은 OPEN. 노트에 “완결”처럼 쓰면 안 되고, 본문 What this release does NOT claim 목록을 그대로 노출해야 함.

CI 로컬 스위트 NOT RUN - 정책상 허용이지만, 정식 채널 승격이므로 미리보기 실퍼블리시·lifecycle 성공 증거를 릴리즈 기록에 링크해 두는 편이 안전함 (본문에 이미 run id가 있음).

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

  • 이미 병합된 뒤에도 제목의 [WRONG BRANCH] 접두와 게이트 DRAFT 댓글을 정리(수정/닫힘 표시)할지, 다음 릴리즈부터 게이트에 main-promote 예외를 넣을지.
  • GitHub Release v2.55.0 / npm latest 퍼블리시가 미리보기와 같은 트리로 이어졌는지(이 댓글 시점의 확인 범위 밖이면 런북 다음 칸).
  • [Bug]: Account pool routing destroys prompt cache and triggers 10x-50x token burn death-spiral above 80% usage threshold #4546 잔여(half-open probe lease 등)를 2.56 dev 열차의 명시 목표로 올릴지, 릴리즈 노트에만 residual로 남길지.
  • 브랜치 네이밍 규칙(…-2550 vs …-255)을 다음 promote부터 맞출지.

너의 추천

병합은 이미 끝났으니 추가 코드 수정은 필요 없습니다. 바로 이어서 (1) v2.55.0 GitHub Release·npm latest가 미리보기와 동일 트리인지 런북대로 확인하고, (2) 릴리즈 노트에 #4546 미완 목록을 그대로 적은 뒤, (3) 게이트의 main-promote 오탐은 별도 이슈/패치로 빼 두세요. dev 는 이미 #4618로 2.56.0이 열려 있으니 다음 작업은 residual cost-guard와 열린 기여자 PR 정리입니다.

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

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

Labels

chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants