feat(core): enforce continuation provider compatibility at runtime#205
Merged
Conversation
Complete the public Continuation primitive (slice 5). The type, its version/provider-stamped to_jsonable/from_jsonable round-trip, and the api reference were already in place; the missing piece was the runtime half of the "Continuation compatibility is a Pollux contract" requirement. validate_interaction now rejects reusing a continuation produced by a different provider before dispatch. A live continuation records its producing provider, and its provider_state (response ids, provider-specific replay blocks such as Anthropic's signed thinking blocks) is not portable, so replaying it under another provider would corrupt the turn. Continuations without a provider marker (hand-built, or derived from plain history) are left alone. This mirrors the serialized-side check in Continuation.from_jsonable(expected_provider=...). Scope: provider-match is the load-bearing, clearly-correct compatibility check. A broader environment/tools/sources fingerprint is deliberately not built — reusing a continuation against a changed environment is not inherently broken.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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.
Summary
Complete the public
Continuationprimitive. The type, itsversion/provider-stamped
to_jsonable/from_jsonableround-trip, and the apireference were already in place. The missing piece was the runtime half of the
"Continuation compatibility is a Pollux contract" requirement: nothing stopped an
app from passing
Input(continuation=output.continuation)back under a differentprovider.
validate_interactionnow rejects, before dispatch, reusing a continuation whoseproducing provider differs from the active one. A live continuation records its
provider, and its
provider_state(response ids, provider-specific replay blockssuch as Anthropic's signed thinking blocks) is not portable, so replaying it under
another provider would corrupt the turn. This mirrors the serialized-side check in
Continuation.from_jsonable(expected_provider=...).Related issue
None
Test plan
just check→ 408 passed, 6 skipped (ruff format/lint, rumdl, mypy, pytest).uv run mkdocs build --strict→ clean.tests/interaction/test_continuation_compat.py(3): a cross-providercontinuation is rejected with an actionable error; a matching-provider
continuation runs; a continuation without a provider marker (hand-built or
history-derived) is left alone.
tests/interaction/test_continuation.py(serialization round-trip,version/provider rejection) still passes.
Notes
Continuations without a provider marker are deliberately not rejected - they arise
from plain
historyor hand construction and carry no provider-specific state.