Fix the schema diff for a public API
Your task
You asked an AI agent to "clean up and tighten types" in your public REST API, and thousands of customers parse its responses. Tightening types is exactly the prompt that makes a model change a field's type or let it be null to please the compiler. Before merging, you diff the response schema from the main branch against the one from the pull request.
An assistant wrote diff_api_contract(baseline_fields, candidate_fields). It is in the editor. It has a bug. Find it and fix it.
Input and output:
baseline_fields: the response fields on the main branch.candidate_fields: the response fields in the pull request. Each is writtenpath|type|required, where the last part isrequiredoroptional.- Return the findings, sorted.
Rules the tests check:
- Split a descriptor on
|. It is malformed unless it has exactly 3 parts, the path and the type are not empty, and the last part is exactlyrequiredoroptional. A malformed descriptor, on either side, givesmalformed:<descriptor>and is otherwise ignored. - If a path appears more than once on one side, use its first descriptor and ignore the rest.
- For each path in
baseline_fields:- not in
candidate_fields:breaking:removed:<path> - a different type:
breaking:type_changed:<path> - required before and optional now:
breaking:now_optional:<path> - optional before and required now:
compatible:now_required:<path>
- not in
- A path can get a type finding and a required or optional finding at the same time.
- A path in
candidate_fieldsthat is not inbaseline_fieldsgivescompatible:added:<path>. - Sort the findings by plain string comparison.
Examples
diff_api_contract(baseline_fields: list[str], candidate_fields: list[str]) -> list[str]Example 1
Input
diff_api_contract(["id|string|required", "email|string|optional"], ["id|string|required", "email|string|optional"])Output
[]Example 2
Input
diff_api_contract(["id|string|required", "email|string|required", "legacy|number|optional"], ["id|number|required", "email|string|optional", "added|string|optional"])Output
["breaking:now_optional:email", "breaking:removed:legacy", "breaking:type_changed:id", "compatible:added:added"]