Repository navigation
test(drift): accept OpenAI's three live K9 summary shapes on the provider side - #523
Merged
Merged
Conversation
…ider side Live o4-mini picks one of three reasoning-summary shapes at random for the K9 exhaustion request: the full summary (9 events), no summary (5 events), or a summary part that streams but never closes (7 events). Measured 2026-10-10 on the exact request: HTTP 22 runs gave 16/4/2, WS 10 runs gave 5/3/2. Every run ended response.incomplete/max_output_tokens with output_tokens 0 on o4-mini-2025-04-16. The HTTP and WS K9 live legs now accept exactly those named shapes on the provider/native side, and still require the incomplete terminal, zero output tokens and the requested model. Localhost grading is unchanged and must emit the full summary; the localhost-to-live comparison uses only the event order outside the summary run. Retained captures of each shape replay without a credential, with mutants for a reordered sequence, a wrong terminal status and nonzero output tokens.
commit: |
… unmatched shapes The HTTP output-token mutant rewrote every output_tokens field, including the zero-valued tool_usage on response.created, so it did not isolate the terminal usage check. It now changes only the terminal event. A new mutant on both surfaces gives only the terminal a different valid snapshot model, which only the created/in_progress consistency check rejects. A live K9 order that matches none of the three accepted summary shapes now fails with a message naming the accepted shapes instead of falling back to the full-summary label.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two live drift legs on main fail intermittently with
expected [ 'response.created', …(4) ] to deeply equal [ 'response.created', …(8) ]:openai-responses.drift.ts:K9:provider:exhaustion-contractws-responses.drift.ts:K9:native:exhaustion-contractThis is not drift in aimock. Live o4-mini picks one of three reasoning-summary shapes at random for the same K9 request (o4-mini, effort high, summary auto,
max_output_tokens: 32).Measurements (2026-10-10, exact K9 request, no changes between runs)
created, in_progress, output_item.added, output_item.done, incomplete. The reasoning item hassummary: [].reasoning_summary_text.doneandreasoning_summary_part.donenever arrive. The final item hassummary: [].response.incomplete/max_output_tokenswithoutput_tokens: 0ono4-mini-2025-04-16.Change
This follows the principle already applied to Gemini K5/K9: accept real upstream variants on the live/native side only.
OPENAI_K9_SUMMARY_SHAPESinhelpers.tsnames exactly the three observed shapes, with the measured frequencies in a comment. Any other summary run still fails. The check is not "any prefix".response.incompleteterminal with reasonmax_output_tokensoutput_tokens === 0created,in_progressand the terminal.src/__tests__/drift/fixtures/and replay without a credential. Mutants must fail:output_tokenscompareExhaustion/compareWSExhaustionso the replays use the same comparison path as the live tests, including the WS SDK/real/mock shape triangulation.No
src/changes, so there is no public API or type impact.Local red-green
RED: the replays run through the unfixed check (
env -u OPENAI_API_KEY npx vitest run --config vitest.config.drift.ts src/__tests__/drift/openai-responses.drift.ts src/__tests__/drift/ws-responses.drift.ts -t "variant replay"):GREEN: the same command after the fix:
Tests 18 passed | 23 skipped (41). All three shapes pass on both surfaces. Every mutant is rejected, and localhost still rejects the 5-event and 7-event shapes.Mutation check of the new assertions. Each mutant was applied and then reverted:
output_tokenscheck fails 6 testsLive GREEN: two consecutive runs of both full drift files with
OPENAI_API_KEY(npx vitest run --config vitest.config.drift.ts src/__tests__/drift/openai-responses.drift.ts src/__tests__/drift/ws-responses.drift.ts):Gates
pnpm typecheck,pnpm lint,pnpm format:check,pnpm build: all pass.pnpm test: 377 files, 14073 passed.Review round 1
Each finding was checked before any change. Every change has a mutation red-green.
OPENAI_RESPONSES_EXHAUSTION_CAPTURE_DIR. A grep of.github/returns nothing; the only references areopenai-responses.drift.ts:92/300-310/367. Thek9-20261008T170312Zcapture is not in the repo or in Actions artifacts, and PR feat: add deterministic model misbehavior faults #508 says no artifact host holds it. It can't be replayed, so CI never uses that path. No change.isOpenAIModelSnapshot): it already behaves correctly.o4-miniando4-mini-2025-04-16pass.o4-mini-high,o4-mini-foo,o4-mini-2025-04ando4-mini2025-04-16are all rejected. No change.output_tokensfield): the assertion readsterminal.response.usage.output_tokens, whereterminal = events.at(-1)narrowed toresponse.incomplete. However, the HTTP mutant'sreplaceAllalso rewrote the zero-valuedtool_usagefields in created and in_progress, so it didn't isolate the terminal. The mutant now sets only the terminal's usage to 5 and asserts that everything before the terminal is byte-identical. Removing the assertion fails 6 tests (HTTP and WS).o4-mini-2099-01-01, a valid snapshot form that differs from created/in_progress. Deleting the consistency loop fails 6 tests.toEqualwith "deeply equal", as the 8-event test showed. The fallback label is gone: an unmatched order now throwslive K9 event order matches none of the accepted summary shapes (full-summary, no-summary, unclosed-summary): …. Restoring the fallback fails the two 8-event tests.Live, after the review fixes: two consecutive runs of both full drift files:
Gates: typecheck, lint, format:check and build pass.
pnpm test: 377 files, 14073 passed.