Skip to content

chore: sync current main into next before major development - #4126

Closed
jbeckwith-oai wants to merge 343 commits into
nextfrom
codex/python-next-sync
Closed

jbeckwith-oai wants to merge 343 commits into
nextfrom
codex/python-next-sync

Conversation

@jbeckwith-oai

Copy link
Copy Markdown
Contributor

Bring Python next up to current main before starting next-major changes. The final tree exactly matches main 0e5794dc48b8f8d51f6047f8a0b1814eb1e65850; this carries existing reviewed SDK fixes, generated updates, dependency locks, security protections and Castiron tooling onto the stale branch.

Resolved the temporary CI bridge against main's supported toolchain and removed scripts/ci-bootstrap and the obsolete Nox configuration. Main already retired the old Stainless codeflow metadata; it stays retired. The custom-code policy is unchanged after its separate approved bootstrap in #4123. No new breaking-change profile is activated by this sync.

Release creation remains main-only. Manual PyPI build/publish remain main-only, with protected release environments and publishing credentials unchanged. Next generation/protection setup and the Python compaction candidate follow separately.

Validation: exact tree identity with current main; reviewed merge resolutions and release guards; Python support-policy check passes. The identical main tree previously passed 95 focused Castiron tests (one skipped). Local trusted-main budget and isolation checks pass at 7,351/10,000 lines, verifying snapshot e23db48; the documented local Git I/O workaround changes only batch input transport. Fresh hosted CI and SDK-team review are required before merge. This is a baseline synchronization, so its large diff consists entirely of already-landed main changes.

openai-sdks Bot and others added 30 commits September 2, 2026 01:22
Automated Release PR
---


##
[3.7.0](v3.6.0...v3.7.0)
(2026-09-02)


### Features

* **api:** update usage APIs and documentation
([#3779](#3779))
([6f0da16](6f0da16))


### Bug Fixes

* avoid repeated numpy checks for embeddings
([#3757](#3757))
([b19c216](b19c216))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Summary
- add docs/architecture/security-model.md as the canonical Codex
Security threat model
- keep SECURITY.md focused on coordinated disclosure and point it to the
canonical model
- clarify repository-code authority while preserving runtime parser,
webhook, metadata, and CI/release boundaries

## Validation
- verified 98 source citations resolve to existing files and valid lines
- resolved SECURITY.md policy chain for
docs/architecture/security-model.md
- git diff --check
- ./scripts/lint (blocked before linting by the preexisting base-state
uv.lock needing update under --locked)
## Summary

Add GPT-6 Astra support, Responses WebSocket steering, safety alert
retrieval, safety webhooks, and expanded safety metadata. This changes
the public ResponsesClientEvent models from response-creation classes
into discriminated unions, requiring users who instantiate those classes
to use ResponseCreate instead.

## Changes

- Add `gpt-6-astra` to supported chat and Responses model literals.
- Add synchronous and asynchronous safety alert retrieval through
client.safety.alerts, including raw and streamed response access and the
SafetyAlert type.
- Add project and organization safety alert webhook event types and
include them in webhook unwrapping.
- Add response.steer WebSocket methods for stable and beta Responses
clients, with text, image, and file input support.
- Add steering client and server event types for accepted, pending, and
failed states, including pending reasons, required input, and error
codes.
- Change ResponsesClientEvent and BetaResponsesClientEvent from
response-creation model classes to discriminated unions covering
response creation and steering; expose the original creation payloads as
ResponseCreate and BetaResponseCreate while retaining aliases for
existing helper types.
- Extend response lifecycle, tool definition, and tool-call types with
steering-related metadata and optional asynchronous tool execution
support.
- Add optional misalignment details and continuation guidance to shared,
Responses WebSocket, and video error models.

Co-authored-by: apcha-oai <228803254+apcha-oai@users.noreply.github.com>
Automated Release PR
---


##
[3.8.0](v3.7.0...v3.8.0)
(2026-09-03)


### Features

* **api:** add gpt-6-astra and related features
([#3791](#3791))
([09f446f](09f446f))


### Documentation

* add canonical SDK security model
([#3778](#3778))
([2a097b9](2a097b9))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Summary

Web-search calls can represent the incomplete status in input and
response types, including strict response validation.

## Changes

- Accept incomplete in stable and beta web-search call status types.
- Allow strict response validation of web-search calls with this status.

Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com>
## Summary

Expose optional prompt cache comparison diagnostics across the stable
and beta Responses APIs. Clarify how Fast and Priority service tier
requests resolve for different models.

## Changes

- Add the optional `comparison_response_id` prompt cache option to
response creation parameters and client events.
- Add `prompt_cache_diagnostics` to response models with typed cache
hit, cache miss, comparison-not-found, and unavailable outcomes.
- Expose cache miss reasons, affected token estimates, and
reusable-prefix token counts in diagnostic results.
- Include the comparison response ID in returned prompt cache options
when supplied.
- Clarify that Fast or Priority requests resolve to `fast` for models
with a dedicated Fast tier and to `priority` for other models.

Co-authored-by: apcha-oai <228803254+apcha-oai@users.noreply.github.com>
Positive numeric Retry-After values that overflow a float previously
selected short fallback backoff. Treat them as excessive server delays
so synchronous and asynchronous requests return the original API error
without retrying early. Preserve the existing 120-second limit, header
precedence, and malformed/literal-infinity handling.

Validation: 376 client and X.509 hardening tests passed (2 existing
skips), including 24 public-entrypoint overflow/precedence cases; Ruff,
Mypy, and Pyright passed. The new module failed 10 cases before the fix.
Two independent adversarial review rounds are clean. Exact-commit
custom-code budget: 6,626 / 10,000 lines.
…-545) (#3801)

## Summary

Removes the name model field from response.function_call_arguments.done
to match the API response.

## Changes

- Remove the name model field from stable and beta Responses function
argument completion events.
- Update code that accesses the removed field to read name from the
function-call item matched by item_id.

Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com>
#3803)

## Summary

Document client throttling and model overload responses for moderation
and video requests.

## Changes

- Clarify the 429 slow_down and 503 server_is_overloaded response
contracts
- Document the optional minimum wait before retrying

Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com>
Automated Release PR
---


##
[3.9.0](v3.8.0...v3.9.0)
(2026-09-05)


### Features

* **api:** Add prompt cache diagnostics
([#3800](#3800))
([8326784](8326784))
* **api:** correct function argument completion event fields
(openapi-545)
([#3801](#3801))
([2a98f6a](2a98f6a))


### Bug Fixes

* **api:** accept incomplete web search call statuses
([#3786](#3786))
([3cc8d78](3cc8d78))
* refuse overflowing server retry delays
([#3799](#3799))
([88b4d43](88b4d43))


### Chores

* **api:** document throttling and model overload responses — SDK-235
([#3803](#3803))
([be92815](be92815))
* migrate to forked steady
([#3795](#3795))
([b24aeda](b24aeda))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Summary

Adds optional expiration fields for service-account API keys, clarifies
the Responses store option, and honors WebSocket retry limits across
repeated reconnects.

## Changes

- Allow service-account API key creation requests to specify
expires_in_seconds.
- Expose expires_at on service-account API key responses.
- Clarify the default and retention behavior of the Responses store
option.
- Honor the configured retry limit when WebSocket connections repeatedly
fail before receiving a non-error application event.

---------

Co-authored-by: jbeckwith-oai <269036200+jbeckwith-oai@users.noreply.github.com>
Co-authored-by: Marcus Wood <marcuswood@openai.com>
Adds GPT Image 2.5 Sunburst/Flare aliases and September 8 snapshots,
`xhigh`/`max` quality, and custom image dimensions.

- Exposes optional, nullable `quality` and `size` on Responses image
calls, including `quality: "auto"`.
- Clarifies Live and Realtime webhook call IDs.
- Preserves WebSocket reconnect retry accounting when raw events are
received.

Co-authored-by: marcuswood-oai <323319819+marcuswood-oai@users.noreply.github.com>
Automated Release PR
---


##
[3.10.0](v3.9.0...v3.10.0)
(2026-09-08)


### Features

* **api:** add GPT Image 2.5 models and image options
([#3824](#3824))
([5b39c45](5b39c45))
* **api:** add service-account API key expiration fields
([#3802](#3802))
([f1cd7f0](f1cd7f0))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Summary

Allow project service accounts to create initial API keys with a
configurable lifetime and expose their expiration timestamps. Clarify
related API behavior and refresh inline documentation links.

## Changes

- Add the optional `expires_in_seconds` parameter to synchronous and
asynchronous service account creation and its request type.
- Document that key lifetimes may be required or limited by policy and
cannot be set with `create_service_account_only`.
- Add `expires_at` expiration metadata to project API key and service
account creation response types.
- Clarify that transcription prompts are unsupported with
`gpt-4o-transcribe-diarize`.
- Clarify that incoming call webhook SIP headers exclude authorization
headers, preserve repetitions and ordering, and must be treated as
untrusted metadata.
- Point SDK resource and type documentation to the current API guides
and references.

Co-authored-by: apcha-oai <228803254+apcha-oai@users.noreply.github.com>
Automated Release PR
---


##
[3.11.0](v3.10.0...v3.11.0)
(2026-09-09)


### Features

* **api:** Add expiration controls for service account keys
([#3825](#3825))
([f348ec8](f348ec8))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Problem and root cause

Test jobs jumped on August 27 at #3641 (`f3f96317e`), which added the
dependency-security checker and its policy regression matrix. Comparing
adjacent main runs:

| Python 3.14 | Before #3641 | After #3641 | This PR |
| --- | ---: | ---: | ---: |
| Entire test job | 2m24s | 7m00s | **2m41s** |
| Pydantic v2 pytest | 60.48s | 192.88s | **62.75s** |
| Pydantic v1 pytest | 46.60s | 183.24s | **52.60s** |
| Passing tests per v2 run | 9,144 | 11,169 | 11,306 |

[Before
run](https://github.com/openai/openai-python/actions/runs/33028653786) ·
[After
run](https://github.com/openai/openai-python/actions/runs/33090881664) ·
[This
PR](https://github.com/openai/openai-python/actions/runs/34386187641)

The suites account for 269 of the 276 additional seconds. Large-payload
tests were already present while jobs remained around 2m10s; the Steady
migration happened afterward. Setup is not the primary cause.

The current security-floor matrix has 1,760 cases. Each previously
launched a Python checker and up to four Python Git stubs. This process
and compilation overhead repeats under both Pydantic versions in all
three test jobs. A representative local profile spent 85ms of 94ms in
subprocess calls, with little time in the policy algorithm. A
20-iteration harness comparison measured median 180ms per subprocess
case versus 0.9ms in-process.

## Change

Compile the same security checker once per pytest worker and execute
each policy case with fresh globals, its existing file fixtures, and the
same Git stub. Restore patched process state after each execution.
Preserve real subprocess execution for CLI parity cases and the existing
trusted-base, isolation, and workflow integration tests.

All existing policy cases, SDK coverage, Pydantic lanes, Python
versions, large-payload sizes, and production enforcement remain
unchanged. Add slow-test reporting to pytest configuration so future
regressions are visible.
## Summary

Fork PRs #3760 and #3345 have green Python CI but no required Castiron
budget statuses: both the workflow-run association and commit-to-PR
endpoint return no PRs. The trusted evaluator fails with `source run
must identify exactly one current PR targeting main`, and the publisher
returns without posting statuses.

Fall back to listing open PRs by the source run's fork owner and branch,
then retain the existing exact-head, target, freshness, and ambiguity
checks. Apply the fallback to report computation, budget evaluation, and
publication; update the reporter integrity digest.

## Validation

- Regression tests reproduce the evaluator failure and missing statuses
on unpatched main.
- Patched read-only lookup resolves the exact current heads of both
affected PRs.
- Castiron reporter/budget suite: 53 tests, OK (1 optional
compiler-contract test skipped), including the JavaScript publishers,
pagination, stale heads, wrong targets, and ambiguous matches.
- Ruff, Pyright, and mypy for `scripts/castiron`.

The trusted handler runs from main. After this fix merges, rerun the
Castiron custom-code workflows for #3760 and #3345 to publish their
required statuses.
…#3760)

Fixes #3338
Fixes #3341

## The bug

`transform()` and `construct_type()` both assume that any `dict` or
`list` annotation is parameterised, and index into `get_args()`
unconditionally. For a bare, unparameterised annotation `get_args()`
returns an empty tuple, so the index access raises instead of
transforming/constructing the value.

```py
from typing import TypedDict
from openai._utils._transform import transform
from openai._models import construct_type

class Params(TypedDict, total=False):
    metadata: dict  # bare dict — no type parameters

transform({"metadata": {"key": "value"}}, Params)
# IndexError: tuple index out of range          (_transform.py:183)

construct_type(value={"key": "value"}, type_=dict)
# ValueError: not enough values to unpack (expected 2, got 0)   (_models.py:660)
```

Two details that weren't in the linked issues:

- **Bare `list` is affected too.** `construct_type(value=[1, 2],
type_=list)` raises `IndexError` at `args[0]`, and `transform([1, 2],
list)` raises `RuntimeError: Expected type <class 'list'> to have a type
argument at index 0` via `extract_type_arg`. Same root cause, so it's
fixed here as well.
- **This reaches real response deserialization.** Any `BaseModel` with a
bare `dict`/`list` field crashes on construction, because
`Model.construct()` routes through the same `construct_type()` branch:

  ```py
  class M(BaseModel):
      metadata: dict

  M.construct(metadata={"a": 1})
  # ValueError: not enough values to unpack (expected 2, got 0)
  ```

The async transform path (`_async_transform_recursive`) has the same two
call sites and is fixed alongside the sync one.

## The fix

Bare containers are treated as if their contents were annotated with
`Any`, which is exactly the existing behaviour for `dict[str, Any]` /
`list[Any]` — values pass through unchanged, while nested `BaseModel`
values still get dumped for JSON-serializability. This keeps
parameterised and unparameterised annotations consistent rather than
special-casing bare ones into a "return unchanged" path.

- `_transform.py`: new `_extract_container_arg(typ, index)` helper that
falls back to `object` when the index is out of range, used by the
`dict` and `list`/`Iterable`/`Sequence` branches in both the sync and
async recursion.
- `_models.py`: `args` is already computed at the top of
`construct_type`, so the `dict` and `list` branches just guard the index
access.

## Verification

Added `test_bare_dict_annotation` / `test_bare_list_annotation` to
`tests/test_transform.py` (parametrised over sync and async) and
`tests/test_models.py`. All six new cases fail on `main` and pass with
this change.

`ruff check`, `ruff format --check`, `pyright`, and `mypy` are clean on
the four touched files. `tests/test_models.py`,
`tests/test_transform.py` and `tests/test_utils` pass, with no change to
the set of pre-existing failures.

---------

Co-authored-by: Marcus Wood <marcuswood@openai.com>
## Summary

Responses parsing raised `TypeError` when a response contained `output:
null`. Treat null output as empty for standalone parsing, and recover
finalized `response.output_item.done` items when a streaming completion
has null or missing output.

Recovery preserves item order, final statuses, annotations, refusals,
structured output, tool arguments, and completion metadata. Explicit
completion output, including `[]`, remains authoritative. This addresses
the review feedback about losing streamed output without adding per-item
finalization branches.

Fixes #3325.

## Validation

- Merged current `main` into the contributor branch.
- Responses suite: 48 passed with Pydantic v2 and 48 passed with
Pydantic v1 on Python 3.10.
- Public synchronous and asynchronous streaming coverage includes null,
missing, empty, and supplied completion output, with and without
streamed items.
- Ruff, Pyright (0 errors), Mypy (1,614 source files), and import check
passed.
- Full PR diff reviewed; no unrelated changes or security findings.

---------

Co-authored-by: Marcus Wood <marcuswood@openai.com>
## Summary

Add `AsyncStream.aclose()` as a thin async alias for the existing
`close()` method. This supports `contextlib.aclosing()` and adapters
that expect `aclose()` while preserving existing `close()` and async
context manager behavior, including subclass overrides of `close()`.

Fixes #2853.

The reported cleanup error occurs when an instrumentation wrapper
exposes an `AsyncStream` as its response and the higher-level chat
streaming helper calls `aclose()` on it. The alias makes that cleanup
path work without changing stream iteration or response handling.

## Tests

- Verify that `aclose()` closes an actual streaming HTTP response and
remains safe alongside repeated `close()` calls.
- Exercise `contextlib.aclosing()` through the public async client after
an early exit and an exception.
- Merge current main and adapt the original test to HTTPX2.

## Validation

- 23 streaming tests pass on Python 3.10 with both Pydantic v1 and v2.
- 16 additional local compatibility checks pass with both Pydantic
versions, covering existing cleanup methods, unread/partial/complete
streams, subclass overrides, and the reported instrumentation cleanup
path.
- Broad local run: 5,108 passed, 120 skipped; three environment-related
failures passed on rerun after installing local wheel metadata and using
CI-pinned uv 0.12.5 (5,111 passing tests total).
- Ruff, Pyright, Mypy, import checks, and changed-file formatting pass.
- Wheel and source distribution builds, Python metadata validation,
Bedrock wheel smoke checks, and isolated HTTPX2/legacy HTTPX/aiohttp
wheel checks pass.

Local limitation: the pinned Steady mock server could not download its
JSR dependencies in this environment. Forty fine-tuning tests failed
because the server was unavailable, and API-resource tests were not run
locally. CI still needs to validate the full mock-server suite and
supported Python matrix.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Marcus Wood <marcuswood@openai.com>
- Add Live API endpoints.
- Add synchronous and asynchronous WebSocket helpers for primary,
sideband, and fork connections.
- Add `TranscriptGrouper` and `AsyncTranscriptGrouper` helpers.

Co-authored-by: apcha-oai <228803254+apcha-oai@users.noreply.github.com>
Automated Release PR
---


##
[3.12.0](v3.11.0...v3.12.0)
(2026-09-10)


### Features

* **api:** Add Live API
([0e4bfef](0e4bfef))


### Bug Fixes

* add aclose() to AsyncStream for standard async cleanup
([#2854](#2854))
([802b334](802b334))
* handle bare `dict` and `list` annotations without type arguments
([#3760](#3760))
([c7e8c03](c7e8c03))
* preserve finalized output on null response completion
([#3345](#3345))
([adb212e](adb212e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
Add the `beta.agents` API.

- Manage agents, sessions, items, and turns; inspect subagents and their
history.
- Work with environments, templates, files, artifacts, vaults, and
credentials.
- Includes automatic pagination, streaming events, binary artifact
downloads, and the `OpenAI-Beta: agents=v1` header.
- `beta.agents.sessions.stream(...)`: Stream one turn on an idle
session; supports sync and async clients.
- Function-tool handlers: Parse arguments, invoke registered functions,
and submit tool results during the stream.
- `AgentSessionMessage.output_text`: Join a message’s output-text blocks
into one string.

Co-authored-by: apcha-oai <228803254+apcha-oai@users.noreply.github.com>
Automated Release PR
---


##
[3.13.0](v3.12.0...v3.13.0)
(2026-09-10)


### Features

* **api:** add Agents API
([1c4284a](1c4284a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
Fixes #3201.

## Summary

Streaming tool call deltas can include multiple entries with the same
logical `index` in the first chunk. The accumulator used to assign that
first list wholesale when the key was absent or `None`, so
duplicate-index entries bypassed the existing recursive merge path and
later argument fragments merged into the wrong physical list entry.

This changes the streaming delta accumulators to initialize indexed
lists through the existing merge loop instead of taking the first
indexed list as-is. It also applies the same initial-list normalization
to the chat completion snapshot path and the matching assistant
streaming accumulator, which shared the same early-return behavior.

## Root cause

`accumulate_delta()` already knew how to merge list entries by their
logical `index`, but only after an accumulator entry existed. When the
first streamed value for `tool_calls` contained two entries with `index:
0`, the fast path copied both entries directly into the snapshot. The
next chunk then merged into physical slot `0` while the earlier
arguments fragment stayed orphaned in physical slot `1`, producing
invalid final JSON.

## Validation

Reproduced on current `origin/main` with a minimal script: duplicate
`index: 0` entries remained as two physical list entries and the
assertion that they merge failed.

```text
env -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY -u http_proxy -u https_proxy -u all_proxy uv run --with pytest --with pytest-xdist --with pytest-asyncio --with respx --with inline-snapshot --with syrupy --with anyio --with pydantic --with httpx --with distro pytest tests/lib/test_streaming_deltas.py tests/lib/chat/test_completions_streaming.py::test_duplicate_tool_call_index_in_initial_chunk -q
# 3 passed

uv run --with ruff ruff check src/openai/lib/streaming/_deltas.py src/openai/lib/streaming/_assistants.py src/openai/lib/streaming/chat/_completions.py tests/lib/test_streaming_deltas.py tests/lib/chat/test_completions_streaming.py
# All checks passed!

uv run --with ruff ruff format --check src/openai/lib/streaming/_deltas.py src/openai/lib/streaming/_assistants.py src/openai/lib/streaming/chat/_completions.py tests/lib/test_streaming_deltas.py tests/lib/chat/test_completions_streaming.py
# 5 files already formatted

git diff --check origin/main..HEAD
# passed
```

---------

Co-authored-by: Marcus Wood <marcuswood@openai.com>
## Summary

The README vision example points to a Wikimedia thumbnail URL that can
fail during the API's image download. Replace it with the National
Gallery of Art image already used in the [OpenAI vision
guide](https://developers.openai.com/api/docs/guides/images-vision),
preserving the current Responses API example and model.

Fixes #2776.

## Image provenance

The image UUID `a2e6da57-3cd1-4235-b20e-95dcaefed6c8` is listed with
`openaccess=1` in the National Gallery's [official published-image
catalog](https://github.com/NationalGalleryOfArt/opendata/blob/main/data/published_images.csv).
The Gallery's [open-access
policy](https://www.nga.gov/terms-and-notices) releases these images
under CC0 for commercial and non-commercial use. The URL is hosted
directly by the Gallery and matches the official OpenAI docs example.

## Validation

- Ran the exact updated README URL example against the live Responses
API with SDK 3.13.0 and `gpt-5.5`: status `completed`, with a
description of the seated woman in the portrait.
- `git diff --check` passed.
- Reviewed the full diff: one image URL replacement in README.md.
Fixes #3125.

Skip null or missing `response.output_item.added` items and track valid
items by their original stream indexes. Later text and tool-call deltas
reach the correct item even when indexes have gaps. Content for an item
never received raises a clear `RuntimeError` instead of being silently
discarded.

Preserves the finalized-output recovery from #3345 and keeps generated
event types unchanged. Merged current main into the contributor branch
and resolved the test conflicts.

## Validation

- Responses suite: 95 passed with Pydantic v2 and 95 passed with v1 on
Python 3.10.
- Broader handwritten SDK and streaming suite: 2,125 passed, 83 skipped.
- Sync/async mock-stream coverage includes missing/null items, reused
and sparse indexes, text/tool deltas, empty/null/missing initial output,
and completion recovery. The original guard fails the new gap
regression.
- Ruff, Pyright (0 errors), Mypy (1,834 source files), compilation, and
import smoke checks passed.
- Forty fine-tuning tests require the local Steady server. Its
dependency download from JSR failed; a representative connection failure
also reproduces with main. These tests were excluded from the passing
broad run.

Reviewed the complete diff; no unrelated changes or security findings.

---------

Co-authored-by: nightcityblade <nightcityblade@gmail.com>
Co-authored-by: Marcus Wood <marcuswood@openai.com>
Fixes #3097

## Summary
- add an optional `max_wait_seconds` bound to
`vector_stores.files.poll()`
- thread the same bound through sync/async `create_and_poll()` and
`upload_and_poll()`
- raise `TimeoutError` instead of waiting forever when a vector store
file stays `in_progress`

## Why
`upload_and_poll()` currently waits until the vector store file reaches
a terminal state. If the backend leaves the vector store file in
`in_progress` indefinitely, the helper never returns and the caller has
no SDK-level escape hatch. The new argument keeps the default behavior
unchanged, while letting callers opt into a bounded wait.

## Validation
- `PYTHONPATH=src python -m pytest
tests/api_resources/vector_stores/test_files.py::TestFiles::test_poll_timeout
tests/api_resources/vector_stores/test_files.py::TestAsyncFiles::test_poll_timeout
-q`
- `PYTHONPATH=src python -m pytest
tests/api_resources/vector_stores/test_files.py::test_create_and_poll_method_in_sync
tests/api_resources/vector_stores/test_files.py::test_upload_and_poll_method_in_sync
-q`
- `PYTHONPATH=src python -m ruff check
src/openai/resources/vector_stores/files.py
tests/api_resources/vector_stores/test_files.py`
- `python -m compileall -q src/openai/resources/vector_stores/files.py
tests/api_resources/vector_stores/test_files.py`
- `git diff --check`

- [x] I understand that this repository is auto-generated and my pull
request may not be merged

Co-authored-by: Marcus Wood <marcuswood@openai.com>
## Summary

A timeout or broken connection after streaming starts currently escapes
as a raw HTTPX exception, bypassing `except openai.APIError`. Wrap
request failures at the event-read boundary, preserving the original
exception as `__cause__` and closing the response.

Keep parsing and callback errors unchanged. Preserve existing Assistants
event-handler and raw byte-stream behavior. Partially consumed streams
are not retried.

Fixes #3811. Supersedes the overlapping fixes in #3813, #3814, and
#3818.

## Release note

Release as a **minor version**. `Stream` and `AsyncStream` now raise
`openai.APITimeoutError` for read timeouts and
`openai.APIConnectionError` for other HTTPX request failures, including
decoding errors. Applications catching raw `httpx` or `httpx2`
exceptions during event streaming should catch these SDK exceptions
instead. The underlying exception remains available through `__cause__`.

## Validation

- Merged current main and resolved the test-import conflict.
- Six after-first-chunk regression cases fail on main and pass with this
change.
- 77 focused tests pass on each of Pydantic v1 and v2, including
sync/async HTTPX2 and legacy HTTPX, response cleanup, no retries, and
callback compatibility.
- Broad offline suite: 3,658 passed, 132 skipped; large-payload
contract: 1 passed, run sequentially.
- Ruff, Mypy, and focused Pyright pass.
- Custom-code budget passes: 6,827 / 10,000 lines.
- Full diff security review found no unrelated changes or dependency,
credential, or workflow modifications.

API/mock-server and network-dependent suites were excluded from the
broad local run. The separate optional legacy aiohttp adapter test could
not run because `httpx_aiohttp` is not installed.

---------

Co-authored-by: Marcus Wood <marcuswood@openai.com>
openai-sdks Bot and others added 25 commits October 17, 2026 00:23
Automated Release PR
---


##
[3.33.0](v3.32.0...v3.33.0)
(2026-10-16)


### Features

* **api:** add safety identifiers to image requests and responses
([#4093](#4093))
([c969e32](c969e32))
* **api:** share Decisions cache breakpoint parameter type
([#4092](#4092))
([f7cefda](f7cefda))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Why

Python callers need to send audio for Translation and receive its final
audio and transcript events before closing.

## High-level description

Add `client.realtime.translations.connect(model=...)` and sync/async
session helpers. Direct connections include the model on every
connection attempt and accept large audio events by default; caller-set
receive limits still apply.

The session helpers send the finish command once, reject later input,
keep trailing events visible, and close the connection on exit. They
never reconnect or replay commands. Existing API models and released
public signatures stay unchanged. The Live byte receiver also keeps its
existing contract on websockets 13.

## Validation

- The prior full local run passed 1,399 Translation, Realtime,
Responses, Live, redirect, and recovery tests.
- After the review fixes, all 41 Translation tests pass with current
dependencies and with Pydantic 1/websockets 13.1. They cover
direct/session 5 MiB events, explicit receive limits, and model
retention during reconnects.
- The rebuilt installed wheel completes four direct/session sync/async
connections with fresh credentials, request hooks, events, finish, and
cleanup.
- Repeat generation matches all 1,963 files. The custom-code budget
passes at 7,364/10,000 lines. Mypy, Pyright, and scoped Ruff checks
pass.
- [CI passes on the updated
commit](https://github.com/openai/openai-python/actions/runs/39015378913),
as do CodeQL and custom-code checks. Hosted service tests remain on
hold.

Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com>
## Summary

Recognize degraded as an external storage status.

## Changes

- Add degraded alongside pending, validated, and unhealthy while
retaining existing status values.
Automated Release PR
---


##
[3.34.0](v3.33.0...v3.34.0)
(2026-10-17)


### Features

* **api:** add degraded external storage status
([#4097](#4097))
([b216cb2](b216cb2))
* **api:** add Realtime Translation WebSocket sessions
([#4095](#4095))
([bfada50](bfada50))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Why
Synchronous Realtime reads pass a `decode` argument that websockets 13
does not support, despite that version being in the supported range.

## High-level description
Use the existing byte-receive compatibility helper. Add a real-socket
regression for Unicode text, binary frames, and the version-13 receive
signature. Public signatures, dependencies, and reconnect behavior stay
unchanged.

## Validation
29 focused Realtime contract/recovery tests pass with websockets 13.1
and with 15.0.1. Ruff and diff checks pass. Hosted tests remain on hold.

Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com>
## Summary

Add typed access to reflected input/output audio and Live transport
events.

## Changes

- Recognize reflected input/output audio, DTMF, ringing, answered, and
failed events on Live sideband connections.

## Why

Live sideband connections lacked typed access to reflected input/output
audio and transport events.

## High-level description

Add the seven existing sideband event variants while retaining existing
public event classes and unknown-event handling. Connection runtimes and
API helpers remain SDK-owned. Existing HTTP APIs, credential policy, and
recovery behavior stay unchanged.

## Validation

The new sync and async sideband tests pass from source and from an
installed wheel. They cover all seven added event variants, null and
omitted client event IDs, unknown events, and cleanup. Hosted-service
tests remain on hold. [Current
CI](https://github.com/openai/openai-python/pull/4099/checks).

Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com>
## Summary

Allow ultrafast service selection in Agents model settings.

## Changes

- Include ultrafast in typed service-tier options for agent creation,
updates, and session model settings.






Scope review: the transformed API changes only the ultrafast enum value
and its matching description from OpenAPI 8ba0678. Existing service-tier
values and public method types remain available.
Automated Release PR
---


##
[3.35.0](v3.34.0...v3.35.0)
(2026-10-17)


### Features

* **api:** add typed Live sideband events
([#4099](#4099))
([8d5cbf0](8d5cbf0))
* **api:** add ultrafast service tier for Agents
([#4101](#4101))
([100bf8f](100bf8f))


### Bug Fixes

* **realtime:** preserve byte receives with websockets 13
([#4098](#4098))
([309916e](309916e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Why
Synchronous beta Realtime calls `recv(decode=False)`, but the supported
websockets 13.x sync API has no `decode` argument. Receiving a message
therefore raises TypeError.

## High-level description
Use the existing SDK byte-receive helper, as the other synchronous APIs
already do. Extend the real-socket text/binary regression to beta
Realtime, including the legacy dependency signature. Add wire-level
tests across all eight connection entrypoints for sync/async redirects,
fresh credentials, explicit header precedence, events, and cleanup.
Preserve current redirect and connection behavior.

## Validation
All 191 tests in the two focused modules pass with both websockets 13.1
and 15.0.1. The unpatched published SDK 3.35.0 reproduces the beta
receive failure on 13.1 (two failing wire cases); with 15.0.1 it passes
all 64 new wire cases and 263 existing functional cases. Ruff checks
pass. All servers are local and credentials synthetic; no hosted tests.

## Release note
Fix synchronous beta Realtime message reception when using websockets
13.x. Public signatures and returned bytes remain unchanged.

A locally built wheel containing this fix also passes all 64 new
connection cases with websockets 13.1 when installed outside the source
tree. Focused Pyright checks pass.

[Current CI
checks](https://github.com/openai/openai-python/pull/4102/checks)
Automated Release PR
---


##
[3.35.1](v3.35.0...v3.35.1)
(2026-10-18)


### Bug Fixes

* preserve beta Realtime byte reads on websockets 13
([#4102](#4102))
([5766349](5766349))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
## Summary

Use a generic placeholder for text in moderation examples.

## Changes

- Replace the explicit text example with a neutral placeholder.
- Keep moderation parameters, response types, and behavior unchanged.





<!-- moderation-follow-up -->

The moderation request uses a neutral placeholder. Its obsolete response
example is removed because it described the previous input; response
examples are optional. API parameters, response types, and endpoint
behavior are unchanged.
## Summary

Accept valid vector-store file-batch responses when strict response
validation is enabled.

## Changes

- Preserve the returned object discriminator and validation of other
response fields.

Co-authored-by: jbeckwith-oai <269036200+jbeckwith-oai@users.noreply.github.com>
## Summary

Expose 30-minute cache-write token counts in completions and Decisions
usage results.

## Changes

- Add the optional input_cache_write_30m_tokens usage metric.
- Allow the metric to be null or absent in older responses.

## Validation

- 16 synchronous/asynchronous transport cases pass; custom-code budget
passes at 7,368 / 10,000 lines.
- Handwritten tests cover 73, zero, explicit null, and omission, and
preserve the existing cache-write counters. Isolated decoder mutations
fail on the expected value; the unchanged candidates pass again.

Co-authored-by: jbeckwith-oai <269036200+jbeckwith-oai@users.noreply.github.com>
Restore the two Castiron reporting files to the verified generated
snapshot (`12578924cd37047e1bff02ea0e6f90114b363d15`). This removes a
local variable rename and restores the generated reporter assertions,
including coverage that workflow/action ownership is visible when
explicitly requested. It eliminates 2 mixed files and 17 custom patch
lines without changing the budget, ownership rules, provenance, or SDK
API.

Validation:
- `python3 -m unittest discover -s scripts/castiron -p
'test_custom_code*.py'`: 95 tests run: 94 passed and one compiler-binary
contract test skipped because `CASTIRON_TEST_BIN` is unset.
- Both files match the verified generated snapshot byte for byte.
- The budget evaluator AST is identical after normalizing the local
variable name.
- A mutation that drops `include_workflows=True` fails the restored
ownership assertion.
- Local budget checker: budget and isolation pass, with 39 mixed files
and 7,351 custom patch lines against the verified snapshot (down from 41
files and 7,368 lines); the existing ceiling is 10,000.
The Python SDK has 41 generated-owned files carrying 7,368 custom patch
lines (6,081 added and 1,287 deleted) at the pinned audit revision. Add
a complete per-file inventory, current/generated physical line counts,
and a compatibility-preserving plan to eliminate those patches through
compiler facts and handwritten runtime boundaries.

The plan partitions all files into 17 tracks, records exact contracts
and test requirements, distinguishes moved signatures and overload churn
from runtime logic, and defines compiler-before-SDK dependencies. No
developer-facing breaking changes are permitted. Counting, budget,
generation provenance, CODEOWNERS, and immutable fixture policies stay
intact. Existing compiler audio/compatibility features are identified
for reuse; their presence in the verified snapshot means remaining
patches require exact compatibility analysis.

Independent execution is underway:
- #4113 restores two reporting files to verified generated output:
measured 41 → 39 mixed files and 7,368 → 7,351 patch lines. Local
offline suite: 94 passed, one compiler-binary test skipped; byte/AST
equivalence and budget/isolation checks pass.
- #4112 adds 16 synchronous/asynchronous public-entrypoint upload tests.
Tests, Ruff, targeted mypy and pinned Pyright pass after repairing the
initial CI typing findings. Reversed completion ordering caused the
intended failures.
- Separate upstream changes are submitted for Live queue generation, the
exact file-processing delegate, and two authored-schema wording fixes.
Compiler/runtime tests and raw parent-output comparisons pass. SDK
promotion waits for required compiler merges and verified regeneration;
projected reductions are not claimed as merged.

Validation: the existing reporter verified snapshot metadata, ancestry
and content hash and reproduced all 41-file counts. Every per-file
current/generated physical size, patch identity, JSON/Markdown total and
local link was checked; independent review confirmed the inventory and
resource contracts. Compiler validation details and local environment
limitations are recorded in the plan and upstream reviews. This PR
changes documentation only.
Add handwritten compatibility tests for `videos.poll()` and
`videos.create_and_poll()` before their custom generated-file
implementations move behind compiler-supported boundaries. The existing
generated suite covers individual endpoints and helper signature
synchronization; this suite exercises the public synchronous and
asynchronous clients with in-memory HTTP transports.

Cover terminal and future statuses, queued/in-progress polling,
default/server/explicit/zero intervals, helper headers, multipart
creation fields, per-call option scoping, error propagation, and
asynchronous cancellation. All payloads and uploads are synthetic.

Validation:
- 21 focused tests passed.
- Focused Ruff lint and formatting checks passed.
- Strict Pyright 1.1.413 reported no errors or warnings. The repository
pins 1.1.414, which was unavailable locally; the pinned check remains
for CI.
- Negative control: offsetting the explicit polling header by one in
both runtime methods caused six expected failures across synchronous and
asynchronous polling/creation cases. Restoring the exact runtime bytes
returned all 21 tests to green.

One existing coverage gap needs separate runtime work: the advertised
dictionary-shaped `ImageInputReferenceParam` currently fails file
extraction in `create()`. This suite uses the supported upload tuple and
adds no rejection contract for dictionaries.
Groups future transition work into coherent capability/resource
families, with focused tests, typing fixtures, API-reference changes and
ledger updates included. The guide is roughly 300–800 authored lines
when natural; larger exact generated diffs remain reviewable through
per-file counts and compatibility evidence. The next polling family
covers Files, Videos and vector-store files/batches; compatible upload,
export, WebSocket and parsing work follows the same policy. Existing
submitted work keeps its review progress. Compiler-before-SDK-promotion,
zero developer-facing breaking changes, security/CODEOWNER gates and
separate ratchet-only budget changes remain mandatory. Routine status
updates are batched with implementation.

Records the first merged reduction in the Python generated-code
transition: #4113 merged as `9d12b565554c08bcee6287c0d8f671b8c97ed911`,
and its post-merge push checks are green. Verified remaining
customization is 39 files / 7,351 patch lines, down from 41 / 7,368. The
original per-file audit stays frozen; the JSON inventory adds a separate
merged-progress record with current totals and restored paths.

Plan #4114 has also actually merged as
`6a52987f2da5c3bc9b700a7094c0cf14fe7e78dc`; Conductor separately
verified post-merge push CI, CodeQL and release checks successful on
that merge commit, including
https://github.com/openai/openai-python/actions/runs/39316813847 . This
branch is reconciled onto that main commit, and the complete PR diff
contains only the two documentation files.

The ledger records the two independent successors started automatically
after the confirmed merge: handwritten video polling compatibility tests
in #4115 and the now-submitted compiler generation of existing Beta
resource aliases (72 configuration and 680 renderer tests,
runtime/actual-SDK contracts and raw parent parity passed; all normal
publication hooks enabled). Its one-file/21-line reduction remains
projected until compiler merge and verified SDK generation. SDK
CODEOWNER/security approval, compiler-before-promotion, normal protected
merge gates and zero developer-facing breaking changes remain mandatory.
Review requests/updates use deduplicated root #sdk-reviews posts.

Validation: exact trusted-main reporter source verifies the same
snapshot ancestry/hash, two restored files and all 39 remaining
customizations unchanged. Local Git batch I/O needed a temporary-file
stdin adapter; the source, hash/counting logic and returned Git bytes
were unchanged, as documented. Frozen JSON identity,
totals/physical-size reconciliation, relative documentation links and
`git diff --check` pass. Independent review found no blockers. This
changes only two documentation files, with no runtime, API,
budget-policy, counting, provenance, dependency or fixture changes.

Ready for normal current-head CI and required reviews. No merge, queue
or post-merge success is inferred from earlier-head results.

Owning Codex conversation: 6ad66292-b06c-8191-b9f2-baafa5fb801d.
Conductor should route transition feedback and confirmed merge events to
this chat so the next eligible batch proceeds automatically.
When a caller closes a recovering WebSocket while the replacement
handshake is
still pending, the new connection can take over after close. Canceling
async
recovery can also leave the connection accepting commands into a queue
that
will never drain.

Use the existing sync close/publication lock for every manager and
retire the
queue as soon as close starts. Async recovery checks close before and
after
the handshake, closes an unwanted replacement even when its caller
cancels,
and clears the recovering flag on every exit. This preserves the
existing rule
against replaying a failed queue flush.

Validation: 30 targeted tests pass across Realtime, transcription,
sideband,
Responses and Live; the initial regression tests failed on the previous
source.
Existing WebSocket suites passed 1,108 tests with 2 live-test skips (one
new
test exceeded its original 2-second barrier under parallel load; it now
uses a
bounded 10-second barrier and passes).
Full Ruff, Mypy, Pyright, import, and the trusted custom-code budget
check pass.
The local `scripts/lint` wrapper could not resolve this environment's uv
registry lock. Its underlying checks passed in a frozen all-extras
environment;
Pyright used the repository's exact Node, pnpm and Pyright pins.
Chunked upload helpers currently live alongside generated resource code.
Add public-entrypoint compatibility tests before moving their
implementation behind compiler-generated delegates, preserving the
behavior callers already receive.

The tests cover synchronous and asynchronous clients with in-memory HTTP
transports: path and bytes inputs, empty payloads, inferred and explicit
metadata, ordered parts and completion IDs, MD5 forwarding and omission,
client default headers/query options, required metadata validation
before requests, and file handle cleanup after successful or failed part
uploads. All requests and payloads are synthetic. This change adds one
handwritten test file and makes no SDK, dependency, generated-file, or
budget changes.

Validation:

- `PYTHONPATH=src python -m pytest tests/lib/test_uploads.py -n 0`: 16
passed using the committed dependency lock on Python 3.10.
- Ruff check and format check: passed.
- Targeted mypy with `--follow-imports=silent`: passed.
- Targeted Pyright 1.1.414: 0 errors and 0 warnings. The follow-up
commit uses an explicit async-generator return annotation and a typed
async file recorder to satisfy strict CI type checking.
- Mutation check: reversing completion part IDs caused the six ordered
multipart cases to fail; the SDK source was restored afterward.

The explicit chunk-size cases cover multiple parts and a shorter final
part. The default 64 MiB boundary is outside this test slice. Request
SDK CODEOWNER review before merging.
The synchronous WebSocket client never supports `write_limit`; its
`max_queue` option requires websockets 14 or newer. The SDK currently
describes both sync and async connections with one options type.

Add `SyncWebSocketConnectionOptions` to the SDK-owned options module
with the five sync fields and the version note. Keep the existing
`WebSocketConnectionOptions` and legacy `WebsocketConnectionOptions`
alias fully compatible for async callers. This prepares the owned type
for a separate generated-code update: current generated sync method
annotations and the top-level export are unchanged in this PR.

Validation: the new type contract failed before the change and passes
afterward. Full Pyright, Mypy (2,036 files), Ruff and formatting passed.
After rebasing onto the latest recovery fix, 132 focused options,
recovery, Live and Translation checks pass; targeted Pyright remains
clean. The trusted budget check passes at the current PR head.
With Pydantic v1, a valid Responses function call containing both
`"async": true` and an extra `"async_": "future"` can replace the
validated boolean with that extra value. The same problem affects nested
validated SDK models with other aliased fields.

Preserve the declared wire field during Pydantic v1 validation and
discard only the colliding extra. Keep unrelated extra fields, input
dictionaries, and keys used as another declared wire alias intact.
Pydantic v2 and loose construction keep their existing behavior.

Tests cover public synchronous and asynchronous Responses parsing, valid
and future union variants, generic models, and overlapping declared
aliases. On Python 3.10, the focused model tests pass on the minimum
supported Pydantic 1.10.13 and on 1.10.26 (66 passed, 13 existing
v2-only skips); Pydantic 2.12.5 passes all 79. Broader model and
WebSocket suites pass with v1 (1,634 passed, 13 skipped) and v2 (1,647
passed). Ruff, Pyright, mypy, and the exact-commit custom-code budget
pass.

The shared model base is SDK-owned and absent from the current
generated-file manifest. This change does not require regeneration.
Legacy `client.beta.realtime.connect()` inherited a 1 MiB native receive
limit, so a larger event closed the connection with code 1009 unless
callers already supplied `max_size=None`. Its synchronous option type
also advertised `write_limit`, which only native async connections
support.

Default to no receive size limit when the beta connection opens, while
keeping every caller value, including finite limits and zero. Use the
existing synchronous options type for beta sync connections; the legacy
async type and its supported write limit stay available. This changes
only the SDK-owned beta path.

Before the change, both default-large cases failed. Local native tests
now pass on the minimum `websockets==13.0` (15/15) and
`websockets==15.0.1` (46/46 including Realtime recovery controls). Tests
compare the whole received payload, check code 1009 for caller limits,
and verify that the beta sync type rejects the async-only literal while
beta async still accepts it.
## Summary

Adds optional IDs to stable and beta compaction trigger items.

## Changes

- Accept omitted, null, or string compaction trigger IDs while retaining
existing construction APIs.
@jbeckwith-oai
jbeckwith-oai requested a review from a team as a code owner October 20, 2026 06:13
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 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-10-20T06:15:53.876156Z feeffa5 PR opened
🔒 Security Review ✅ Completed 2026-10-20T06:22:32.433541Z feeffa5 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.

@github-actions

Copy link
Copy Markdown
Contributor

Castiron custom code

Evaluated next: 594d122ca54c313726256feda422acda8e1943ad.

Trusted main policy: 0e5794dc48b8f8d51f6047f8a0b1814eb1e65850.

⚠️ Report unavailable for feeffa5535a4.

public snapshot lineage does not contain the base generation

Full report and patch

@jbeckwith-oai

Copy link
Copy Markdown
Contributor Author

Temporarily closing this sync while preserving its branch and commits. Validation caught two prerequisites: the existing next API differs from current main, and its legacy generation is absent from the main snapshot lineage. A normal Castiron preview also exposed formatter bootstrap choosing an incidental uv.lock instead of the explicitly Rye-managed project’s pinned formatter. I will address that narrow source issue first, then reconcile this transition through the supported generation/promotion workflow. No checks or metadata are being bypassed.

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.