Skip to content

fix(spec-drift): reconcile OpenAPI 3.25.0 nightly contract failures (#475)#476

Merged
TexasCoding merged 1 commit into
mainfrom
fix/spec-drift-475
Jul 17, 2026
Merged

fix(spec-drift): reconcile OpenAPI 3.25.0 nightly contract failures (#475)#476
TexasCoding merged 1 commit into
mainfrom
fix/spec-drift-475

Conversation

@TexasCoding

Copy link
Copy Markdown
Owner

Summary

Reconciles the SDK to upstream OpenAPI 3.25.0 so the nightly strict contract suite goes green again. Closes #475.

Two hard failures from the scheduled Spec Drift Detection run:

  1. MarginMarket.schedule (perps) — new required field referencing nested MarginMarketSchedule (is_open, next_close_ts, next_open_ts). The schedule object is null for 24/7 markets; when present the open/close timestamps are Unix epoch seconds and themselves nullable by phase.
  2. POST /portfolio/intra_exchange_instance_transfer (core) — newly listed on the core OpenAPI, marked currently not available. Already implemented on PerpsClient.transfers.transfer_instance (same path/schema). Recorded in _UNIMPLEMENTED_ENDPOINTS rather than dual-shipping a disabled core surface.

Changes

  • Vendored specs re-pinned: openapi.yaml 3.24.0 → 3.25.0, plus asyncapi / perps / perps_scm refreshes
  • New MarginMarketSchedule model; required schedule: MarginMarketSchedule | None on MarginMarket
  • Exported + registered in PERPS_CONTRACT_MAP
  • Core transfer path allowlisted in _UNIMPLEMENTED_ENDPOINTS with reason
  • Perps market fixtures/tests updated for the required schedule key

Non-goals

  • No core KalshiClient implementation of the intra-exchange transfer (endpoint disabled upstream; available on the perps client). Follow-up when Kalshi enables it.
  • Soft additive-optional warnings for SCM omitted_subtrader_count left as-is (non-blocking).

Test plan

…475)

Pin vendored specs to upstream 3.25.0 and absorb the two required-side
nightly failures: MarginMarket.schedule (plus nested MarginMarketSchedule)
and the core POST /portfolio/intra_exchange_instance_transfer endpoint map
entry (unimplemented — currently not available; live on PerpsClient).

Closes #475
@claude

claude Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review: fix(spec-drift) — reconcile OpenAPI 3.25.0 (#475)

Reviewed the diff (kalshi/_contract_map.py, kalshi/perps/__init__.py, kalshi/perps/models/__init__.py, kalshi/perps/models/markets.py, tests/perps/test_markets.py, tests/test_contracts.py, plus the four vendored spec files). Note: I wasn't able to execute uv run pytest/mypy/ruff in this review environment, so the below is a static read against the spec diffs and existing conventions — I did not independently re-verify the test-run numbers in the PR description.

Overview

Small, well-scoped drift fix with two independent changes:

  1. Adds MarginMarketSchedule and wires it as a required, nullable field on MarginMarket.
  2. Allowlists POST /portfolio/intra_exchange_instance_transfer in _UNIMPLEMENTED_ENDPOINTS on the core client, since it's already implemented (same path/schema) on PerpsClient.transfers.transfer_instance.

Correctness

  • MarginMarketSchedule modeling matches the spec exactly: is_open: bool (required, non-nullable), next_close_ts/next_open_ts: int | None (required key, nullable value). Leaving these fields without a = None default is the right call — it makes a missing key hard-fail validation rather than silently defaulting, which is what you want for a spec-required field and keeps future required-drift detectable. Good catch documenting why in the comment rather than just what.
  • schedule: MarginMarketSchedule | None on MarginMarket (no default) mirrors the same reasoning for the outer nullable-object case (24/7 markets → null).
  • Verified kalshi/perps/resources/transfers.py:transfer_instance (sync + async) already targets POST /portfolio/intra_exchange_instance_transfer — the exclusion reasoning in test_contracts.py checks out, and I confirmed there's no duplicate exclusion entry for that path elsewhere.
  • Confirmed IntraExchangeInstanceTransferRequest/Response schemas already existed in the core spec pre-diff (not newly added here), consistent with "same path/schema" framing.
  • Export lists (kalshi/perps/__init__.py, kalshi/perps/models/__init__.py) and the new _contract_map.py entry all look correctly placed/alphabetized.

Test coverage

  • tests/perps/test_markets.py covers both branches well: populated schedule on the happy path (asserts is_open, next_close_ts, next_open_ts roundtrip) and schedule: None for the 24/7 case.
  • Minor gap (not blocking): no test exercises the missing key case for schedule or the nested timestamp fields, i.e. nothing directly asserts that omitting a required key raises a validation error. If that's already covered generically by the contract-drift suite (TestRequestBodyDrift/required-field drift tests) rather than per-model, this is fine as-is — worth a one-line confirmation in the PR description if so, since the in-code comments call out "required-drift" as the explicit intent.

Style/conventions

  • Follows the project's DollarDecimal/nested-model conventions correctly; model_config = {"extra": "allow"} on the new model matches sibling models in the same file.
  • Docstring on MarginMarketSchedule clearly states the nullability contract (which field is null in which phase) — useful given the somewhat unusual "required key, nullable value" spec shape.

Risk / blast radius

  • Low risk: additive model change gated behind a required spec field (so any consumer already had to handle this data), plus a test-only allowlist entry for an endpoint the spec itself marks unavailable. No behavior change to request signing, retry logic, or existing public methods.
  • The large specs/openapi.yaml/specs/asyncapi.yaml diffs are mostly re-formatting from the vendored re-pin (multi-line YAML descriptions collapsed to single-line) rather than semantic changes — worth a quick sanity check that the re-pin script isn't introducing unrelated formatting churn on every drift PR, since it makes future diffs harder to review, but that's a process nit rather than a defect in this PR.

Nit

  • CHANGELOG.md wasn't touched — per CLAUDE.md that's "updated per release," so likely fine to defer to the actual version bump, just flagging in case this was meant to land with one.

Overall: solid, surgical fix that matches CLAUDE.md's spec-first conventions. No blocking issues found.

@TexasCoding
TexasCoding merged commit 643de7f into main Jul 17, 2026
7 checks passed
@TexasCoding
TexasCoding deleted the fix/spec-drift-475 branch July 17, 2026 10:34
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.

Nightly spec-drift: strict contract tests failing (since 2026-07-16)

1 participant