@@ -63,6 +63,68 @@ def test_provider_separate_verifier_publishes_bound_input_artifact(
6363 assert text .index ('"/app/input.json"' ) < text .index ('"/app/submission.json"' )
6464
6565
66+ def test_provider_feasibility_task_descriptions_are_provider_specific () -> None :
67+ """Provider-feasibility task descriptions must identify their own provider.
68+
69+ A copy/paste from cddlib left five tasks advertising a cddlib H/V
70+ polyhedra contract they do not exercise. Each task's ``description`` and
71+ ``keywords`` must reference its own ``required_provider`` so catalog
72+ consumers can distinguish the tasks without reading their implementation.
73+ """
74+
75+ import re
76+ import tomllib
77+
78+ def _normalize_tokens (text : str ) -> set [str ]:
79+ return set (re .findall (r"[a-z0-9]+" , text .lower ().replace ("-" , " " )))
80+
81+ for task_name in PROVIDER_TASKS :
82+ task = DATASETS / "provider-feasibility-v1" / task_name
83+ cfg = tomllib .loads ((task / "task.toml" ).read_text (encoding = "utf-8" ))
84+ provider = cfg ["metadata" ]["required_provider" ]
85+ description = cfg ["task" ]["description" ]
86+ keywords = cfg ["task" ]["keywords" ]
87+ description_tokens = _normalize_tokens (description )
88+ keyword_tokens = set ().union (* (_normalize_tokens (k ) for k in keywords ))
89+ provider_tokens = _normalize_tokens (provider )
90+ # Every provider's description must mention every token of its own
91+ # provider name (e.g. "lean" and "repl" for "lean-repl").
92+ missing_in_description = provider_tokens - description_tokens
93+ assert not missing_in_description , (
94+ f"{ task_name } : description does not mention required_provider "
95+ f"{ provider !r} tokens { sorted (missing_in_description )} : "
96+ f"{ description !r} "
97+ )
98+ missing_in_keywords = provider_tokens - keyword_tokens
99+ assert not missing_in_keywords , (
100+ f"{ task_name } : keywords do not include required_provider "
101+ f"{ provider !r} tokens { sorted (missing_in_keywords )} : { keywords !r} "
102+ )
103+ # No task may advertise another provider's full name in its
104+ # description or keywords. Check the contiguous normalized form so
105+ # "cgal" is not flagged by the word "c" in an unrelated description.
106+ description_norm = " " .join (
107+ description .lower ().replace ("-" , " " ).replace ("_" , " " ).split ()
108+ )
109+ keywords_norm = " " .join (
110+ " " .join (k .lower ().replace ("-" , " " ).split ()) for k in keywords
111+ )
112+ for other in PROVIDER_TASKS :
113+ other_norm = " " .join (other .lower ().replace ("-" , " " ).split ())
114+ if other_norm == " " .join (provider .lower ().replace ("-" , " " ).split ()):
115+ continue
116+ if other_norm in description_norm :
117+ raise AssertionError (
118+ f"{ task_name } : description references unrelated provider "
119+ f"{ other !r} : { description !r} "
120+ )
121+ if other_norm in keywords_norm :
122+ raise AssertionError (
123+ f"{ task_name } : keywords reference unrelated provider "
124+ f"{ other !r} : { keywords !r} "
125+ )
126+
127+
66128def test_reliability_recomputes_input_and_rejects_coerced_state_count (
67129 tmp_path : Path ,
68130) -> None :
0 commit comments