"""Contract tests for manifest-output.schema.json.""" from __future__ import annotations import jsonschema from src.runtime.core.config import create_schema_registry, load_schema from src.runtime.storage.file_store import create_manifest_dict def test_manifest_output_schema_completed_text_valid(): schema = load_schema("manifest-output.schema.json") registry = create_schema_registry() validator = jsonschema.Draft202012Validator(schema, registry=registry) valid_manifest = create_manifest_dict( fingerprint="a" * 64, source_url="https://example.com/article/1", selected_extractor="trafilatura", final_status="completed_text", generate_markdown=True, markdown_path="out/articles/" + "a" * 64 + ".md", markdown_hash="b" * 64, config_version="1.0.0", trace_id="trace_001", ecp_classification={ "category": "DIRECT_INHERENT", "confidence": 0.95, "rationale": "High direct entity relevance.", "evidences": ["Direct entity mentioned."], }, enrichment={ "sentiment": "positive", "tags": ["river plate", "futebol", "argentina"], }, provider_versions={ "hygiene": { "provider": "groq", "model": "llama-3.1-8b-instant", "role_config_version": "1.0.0", }, "enrichment": { "provider": "deepseek", "model": "deepseek-chat", "role_config_version": "1.0.0", }, }, model_versions={ "runtime_primary": { "provider": "groq", "model": "llama-3.1-8b-instant", "role_config_version": "1.0.0", }, "runtime_fallback": { "provider": "deepseek", "model": "deepseek-chat", "role_config_version": "1.0.0", }, }, prompt_versions={ "article_content_hygiene": {"version": "1.0.0", "hash": "c" * 64}, "article_sentiment_tags": {"version": "1.0.0", "hash": "d" * 64}, }, error_codes=[], ) errors = list(validator.iter_errors(valid_manifest)) assert len(errors) == 0, f"Schema errors: {[e.message for e in errors]}" def test_manifest_output_schema_rejected_ecp_valid(): schema = load_schema("manifest-output.schema.json") registry = create_schema_registry() validator = jsonschema.Draft202012Validator(schema, registry=registry) rejected_manifest = create_manifest_dict( fingerprint="a" * 64, source_url="https://example.com/article/2", selected_extractor="newspaper4k", final_status="rejected_ecp", generate_markdown=False, markdown_path=None, markdown_hash=None, config_version="1.0.0", trace_id="trace_002", ecp_classification={ "category": "TANGENTIAL", "confidence": 0.88, "rationale": "Only brief tangential reference.", "evidences": ["Brief reference."], }, enrichment=None, provider_versions={ "hygiene": { "provider": "groq", "model": "llama-3.1-8b-instant", "role_config_version": "1.0.0", }, "enrichment": None, }, model_versions={ "runtime_primary": { "provider": "groq", "model": "llama-3.1-8b-instant", "role_config_version": "1.0.0", }, "runtime_fallback": { "provider": "deepseek", "model": "deepseek-chat", "role_config_version": "1.0.0", }, }, prompt_versions={ "article_content_hygiene": {"version": "1.0.0", "hash": "c" * 64}, "article_sentiment_tags": {"version": "1.0.0", "hash": "d" * 64}, }, error_codes=["ECP_REJECTED"], ) errors = list(validator.iter_errors(rejected_manifest)) assert len(errors) == 0, f"Schema errors: {[e.message for e in errors]}"