Skip to content

fix(proxy): replay full resend after bridge owner conflict - #1557

Open
Komzpa wants to merge 3 commits into
mainfrom
fix/http-bridge-continuity-conflict-fresh-replay-20260731
Open

fix(proxy): replay full resend after bridge owner conflict#1557
Komzpa wants to merge 3 commits into
mainfrom
fix/http-bridge-continuity-conflict-fresh-replay-20260731

Conversation

@Komzpa

@Komzpa Komzpa commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

HTTP bridge full-resend recovery now treats continuity_owner_conflict the same way as an unavailable required owner when the existing account-neutral replay safety checks pass. This prevents stale Codex session/turn affinity from surfacing a one-turn 503 when the client has resent enough plaintext context to start a fresh bridge safely.

Type of change

  • fix: — bug fix (no behavior change beyond the bug)
  • feat: — new user-facing feature or capability
  • refactor: — internal refactor (no behavior change, no API change)
  • docs: — documentation only
  • chore: / ci: / build: — tooling, CI, packaging
  • test: — test-only change
  • Breaking change (also append ! after the type, e.g. feat!: or include BREAKING CHANGE: footer)

Linked issue: n/a

OpenSpec

  • This PR includes / updates an OpenSpec change
  • Not applicable — bug fix that matches the existing spec
  • Not applicable — docs / CI / chore only
  • This PR touches a codex-faithful path (image pipeline, request/response shape, SSE framing, OAuth flow) and preserves upstream-equivalent behavior

Change directory: n/a

Changes

  • Allow account-neutral full-resend replay after continuity_owner_conflict, while keeping the existing safety gates: no forwarded request, no input-file owner, matching stored context prefix fingerprint, retained prior output, and account-neutral replay payload.
  • Add an integration regression where a stale owner conflict is recovered by stripping stale Codex/session headers and replaying without previous_response_id.

Simplicity

  • New feature defaults to off or works with zero config
  • No new required setup step (or maintainer approval via simplicity-budget-approved label)
  • New setting(s) and why each can't be a default: n/a
  • README sections / .env.example / dashboard nav within budget (or simplicity-budget-approved label requested)

Test plan

uv run pytest tests/integration/test_http_responses_bridge.py -k "replays_full_resend_after_owner_conflict"
uv run pytest tests/integration/test_http_responses_bridge.py -k "reports_unavailable_required_owner_when_other_account_exists or replays_full_resend_once_then_stays_on_new_owner or replays_full_resend_after_owner_conflict"
uv run ruff check app/modules/proxy/_service/http_bridge/streaming.py tests/integration/test_http_responses_bridge.py
uv run ruff format --check app/modules/proxy/_service/http_bridge/streaming.py tests/integration/test_http_responses_bridge.py
git diff --check

Screenshots / output

Live symptom observed before the fix:

status=503 code="continuity_owner_conflict" message="Account-owned continuity sources conflict; retry the logical turn"

The regression proves this class now succeeds through an account-neutral full-resend replay instead of surfacing 503.

Checklist

  • Title is in Conventional Commits format (<type>(<scope>)?: <subject>).
  • Linked the related issue / discussion above.
  • Added or updated tests covering the change.
  • Ran uv run pre-commit run local-ci --hook-stage manual --all-files or the relevant make <target> subset locally.
  • If touching specs: openspec validate --specs passes and /opsx:verify is clean.
  • Simplicity gates reviewed: the five simplicity rules (PRINCIPLES.md P1-P5).
  • CHANGELOG is not edited by hand (release-please handles it).

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@Komzpa
Komzpa force-pushed the fix/http-bridge-continuity-conflict-fresh-replay-20260731 branch from 22c0e9d to 1f2dbfe Compare August 1, 2026 21:33
@Komzpa

Komzpa commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@Soju06

Soju06 commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Two issues before this can land, beyond the rebase (#1562 rewrote the reconnect paths in streaming.py; #1394 merged on top):

  1. Spec: openspec/specs/sticky-session-operations/spec.md ("Conflicting hard owners fail closed" at :130, plus :206/:298) requires continuity_owner_conflict to fail before upstream dispatch, and the active openspec/changes/classify-required-http-bridge-owner-unavailable spec says conflicting aliases MUST still fail with continuity_owner_conflict. This PR relaxes that, so "matches the existing spec" doesn't hold — it needs an OpenSpec delta amending those scenarios (e.g. "unless a verified account-neutral full resend permits fresh replay"). Conflict is also semantically different from owner-unavailable: both owners are alive, and fail-closed was deliberate to surface alias split-brain rather than paper over it. Worth an explicit maintainer call.

  2. switch_model_transition_to_account_neutral_fork is weaker-gated than every analogous recovery path:

    • No forwarded_request guard. owner_unavailable_allows_account_neutral_replay refuses forwarded requests; this fork can fire on an owner-forwarded creation failure and start a local neutral lane on the wrong instance.
    • No payload-neutrality check. switch_to_account_neutral_replay requires _http_bridge_payload_is_account_neutral_fresh_replay (streaming.py:240 on main) and the cap-spill path requires _request_allows_bare_session_cap_spillover (affinity.py:294); the fork checks only rewritten_file_account_id, which misses opaque upstream-registered input_file.file_ids with no live local pin (forwarded verbatim per responses-api-compat), encrypted/account-scoped input items, and conversation. Repro: model-transition request on a hard session key whose input carries an unpinned upstream file_id living on the pinned account; owner conflict -> fork excludes that account -> replay on another account -> deterministic upstream file-not-found instead of a retryable 503.
    • Scope: _http_bridge_owner_failure_allows_account_neutral_replay includes previous_response_owner_unavailable, so the fork also fires for model transitions that fail full-resend fingerprint verification — wider than the conflict bug this PR describes, with no prefix verification at all.

The conflict->verified-full-resend lane itself keeps all the existing gates and looks sound for the observed one-turn 503; with the spec delta and the fork gates tightened (or the fork split into its own PR), this is close.

@Komzpa Komzpa added the needs rebase Needs rebase or conflict repair against current main label Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs rebase Needs rebase or conflict repair against current main

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants