# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-negotiate-output-schema-when-receiver-schema-expectations-are-stricter.md # Remnant Warrant: https://corpusfetch.com/c/how-must-an-instance-negotiate-output-schema-when-receiver-schema-expectations-are-stricter.warrant.json # Markdown SHA-256: d81ef680a9603abf34cfff7c945f9f1998f05aa538528e07826ebfefaf6de26d # Code AST SHA-256: 32c276b65e9564e4355c8e556340699a00bde26da20ce57766e6f043642164a9 # Verified Classes: SchemaVerdict, SchemaDelta, SchemaState, SchemaPolicy, SchemaManifest, OutputSchemaNegotiationGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class SchemaVerdict(Enum): SCHEMA_COMPATIBLE = auto() TRANSFORMATION_REQUIRED = auto() NEGOTIATION_REQUIRED = auto() BEST_EFFORT_ALLOWED = auto() @dataclass(frozen=True) class SchemaDelta: missing_required_fields: tuple[str, ...] type_mismatches: tuple[str, ...] extra_fields: tuple[str, ...] nullability_conflicts: tuple[str, ...] @dataclass(frozen=True) class SchemaState: session_schema_hash: str receiver_schema_hash: str delta: SchemaDelta negotiation_protocol: str | None # "TRANSFORM_ALL" | "BEST_EFFORT" | "FAIL_FAST" receiver_accepts_best_effort: bool @dataclass(frozen=True) class SchemaPolicy: require_negotiation: bool @dataclass(frozen=True) class SchemaManifest: verdict: SchemaVerdict directive: str manifest_digest: str class OutputSchemaNegotiationGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_schema( cls, state: SchemaState, policy: SchemaPolicy ) -> SchemaManifest: # Gate 1: Schemas identical if state.session_schema_hash == state.receiver_schema_hash: digest = cls._hash(json.dumps({ "schema": state.session_schema_hash, "status": "COMPATIBLE" }, sort_keys=True)) return SchemaManifest( verdict=SchemaVerdict.SCHEMA_COMPATIBLE, directive="PROCEED: Schemas identical.", manifest_digest=digest ) # Gate 2: No delta (compatible) delta_is_empty = ( not state.delta.missing_required_fields and not state.delta.type_mismatches and not state.delta.nullability_conflicts ) if delta_is_empty: digest = cls._hash(json.dumps({ "session": state.session_schema_hash, "receiver": state.receiver_schema_hash, "delta": "EMPTY" }, sort_keys=True)) return SchemaManifest( verdict=SchemaVerdict.SCHEMA_COMPATIBLE, directive="PROCEED: Schema delta empty, output compatible.", manifest_digest=digest ) # Gate 3: Negotiation requirement if policy.require_negotiation and not state.negotiation_protocol: return SchemaManifest( verdict=SchemaVerdict.NEGOTIATION_REQUIRED, directive=f"HALT: Schema delta exists (missing {len(state.delta.missing_required_fields)}, mismatches {len(state.delta.type_mismatches)}), no negotiation protocol.", manifest_digest=cls._hash("NO_PROTOCOL") ) # Gate 4: Best effort allowed if state.negotiation_protocol == "BEST_EFFORT" and state.receiver_accepts_best_effort: digest = cls._hash(json.dumps({ "protocol": "BEST_EFFORT", "delta": { "missing": tuple(sorted(state.delta.missing_required_fields)), "mismatches": tuple(sorted(state.delta.type_mismatches)) } }, sort_keys=True)) return SchemaManifest( verdict=SchemaVerdict.BEST_EFFORT_ALLOWED, directive="PROCEED: Best effort allowed with warnings.", manifest_digest=digest ) # Gate 5: Transform required digest = cls._hash(json.dumps({ "protocol": state.negotiation_protocol or "TRANSFORM_ALL", "delta": { "missing": tuple(sorted(state.delta.missing_required_fields)), "mismatches": tuple(sorted(state.delta.type_mismatches)), "extra": tuple(sorted(state.delta.extra_fields)) } }, sort_keys=True)) return SchemaManifest( verdict=SchemaVerdict.TRANSFORMATION_REQUIRED, directive=f"ACTION: Transform output per {state.negotiation_protocol or 'TRANSFORM_ALL'}.", manifest_digest=digest )