Keep typed trace contracts source-faithful

General lesson: A typed trace contract should model producer-observed evidence, not every shape that permissive downstream adapters happen to accept. This applies when legacy compatibility, normalization aliases, and semantic enrichment coexist with raw event payloads. Its limit is an explicit producer-owned extension contract: documented extensions should be modelled or deliberately preserved rather than rejected.

Method: 1. Inventory canonical producer/test fixtures separately from adapter-only aliases and downstream semantic envelopes. 2. Use strict nested models for structural fields, while keeping open JSON only in fields that are intentionally dynamic (for example state snapshots and tool arguments/results). 3. Preserve observed role-discriminated turns and correlations without rewriting source values. 4. Enforce referential invariants only when an explicit completeness signal proves the relevant capture is complete; otherwise an orphan or missing link is evidence-quality uncertainty, not necessarily malformed input. 5. Bound validation errors and omit captured values so ingestion failures are safe to log.

Evidence/example (2026-09-11): In ender-inference COR-4187 / PR #198, repository discovery separated canonical universal_context fields in ender_inference/training_service/mvp_context.py and tests/test_training_mvp_context.py from adapter-only aliases in training normalization/evaluation adapters. Review removed invented speech fields, semantic mvp_evaluation_context data, adapter-only tool-result aliases, and unobserved completeness flags. The resulting source-only Pydantic package is in ender_inference/training_service/universal_context/models.py with focused evidence in tests/test_universal_context_models.py. This is a dated implementation example, not a claim about all future producer versions.