VERIFIED
mirumee__ariadne-codegen-159
VERIFIED on first verdict
1 attempt, 0 appeals. 1 file, 79 added and 1 removed lines. Tokens: 139,543 tokens. Model cost: $0.04. Sandbox time: 1 min 0 s.
The plan
- Repository
- mirumee/ariadne-codegen
- Base commit
- b09a532 (image tag)
- Issue
- Mixin Strategy Produces Invalid Queries ### Summary The Mixins feature is a great idea for extending the functionality of generated classes, however the mixin directive is not removed from the final generated query, resulting in errors returned from remote APIs. ### Example Let's say that we simply want to validate that a mixin has been applied by returning a message:
- Files to edit
ariadne_codegen/client_generators/result_types.py
- Approach
- Override the AST nodes in a copy so they have an empty directives list when generating the string representation, but do not mutate the original AST objects.
Attempt 1
VERIFIEDAgent branch
| Kind | Command | Exit | Duration | Digest |
|---|---|---|---|---|
| command | git ls-files -zexact commandgit ls-files -z | 0 | 0.004s | 5c1cc527 |
| write | write ariadne_codegen/client_generators/result_types.pyexact command/opt/receipts-5f1e1888699a4e1bbbeef5d3c51929ee/bin/busybox sh -c 'mkdir -p /ariadne-codegen/ariadne_codegen/client_generators && cp /opt/receipts-5f1e1888699a4e1bbbeef5d3c51929ee/incoming/2da41d5c01cfdc390b31f08c019e047d340aeff829ace8a194b48a9f5fc9b56e /ariadne-codegen/ariadne_codegen/client_generators/result_types.py' | 0 | 0.004s | 4d14159c |
| command | pytest tests/client_generators/result_types_generator/test_get_operation_as_str.py::test_get_operation_as_str_returns_representation_without_mixin_directive -vexact command/opt/receipts-3ae9fc04ca164d2ca590883d526e6f3a/bin/busybox mkdir -p /opt/receipts/reports && python -I /opt/receipts-3ae9fc04ca164d2ca590883d526e6f3a/receipts_pytest.py tests/client_generators/result_types_generator/test_get_operation_as_str.py::test_get_operation_as_str_returns_representation_without_mixin_directive -v -o junit_family=xunit1 -p no:cacheprovider -rA --continue-on-collection-errors --junitxml=/opt/receipts/reports/agent1-3.xml | 0 | 1.186s | 8f617d7e178c |
| command | pytest tests/client_generators/result_types_generator/test_get_operation_as_str.py -vexact command/opt/receipts-cb7c7e802dbb4a89846cfe9b707ee5f6/bin/busybox mkdir -p /opt/receipts/reports && python -I /opt/receipts-cb7c7e802dbb4a89846cfe9b707ee5f6/receipts_pytest.py tests/client_generators/result_types_generator/test_get_operation_as_str.py -v -o junit_family=xunit1 -p no:cacheprovider -rA --continue-on-collection-errors --junitxml=/opt/receipts/reports/agent1-4.xml | 1 | 1.258s | 8f617d7e178c |
| command | pytest tests/client_generators/result_types_generator/test_get_operation_as_str.py tests/main/clients/extended_models/expected_client/client.pyexact command/opt/receipts-245b9e27e85a4ebe9e46056dffdcac05/bin/busybox mkdir -p /opt/receipts/reports && python -I /opt/receipts-245b9e27e85a4ebe9e46056dffdcac05/receipts_pytest.py tests/client_generators/result_types_generator/test_get_operation_as_str.py tests/main/clients/extended_models/expected_client/client.py --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning -o junit_family=xunit1 -p no:cacheprovider -rA --continue-on-collection-errors --junitxml=/opt/receipts/reports/agent1-5.xml | 1 | 1.234s | 8f617d7e178c |
| command | pytest tests/client_generators/result_types_generator/test_get_operation_as_str.py::test_get_operation_as_str_returns_representation_without_mixin_directive -vexact command/opt/receipts-38ee648d99534848bfe4e7af695fb319/bin/busybox mkdir -p /opt/receipts/reports && python -I /opt/receipts-38ee648d99534848bfe4e7af695fb319/receipts_pytest.py tests/client_generators/result_types_generator/test_get_operation_as_str.py::test_get_operation_as_str_returns_representation_without_mixin_directive -v -o junit_family=xunit1 -p no:cacheprovider -rA --continue-on-collection-errors --junitxml=/opt/receipts/reports/agent1-6.xml | 0 | 1.184s | 8f617d7e178c |
| diff | capture patchexact commandcompute patch in executor staging agent1-0c7f6195be33415791a0831662731f17: /opt/homebrew/Cellar/git/2.53.0/bin/git -c core.hooksPath=/dev/null -c core.attributesFile=/dev/null -c diff.external= -c core.quotePath=false add -A && /opt/homebrew/Cellar/git/2.53.0/bin/git -c core.hooksPath=/dev/null -c core.attributesFile=/dev/null -c diff.external= -c core.quotePath=false diff --cached --binary --no-ext-diff --no-textconv --no-renames b09cb8a97b5a96459e2d09d14bc6f5b31fe9f693 | 0 | 0.038s | 8f617d7e178c |
- Finish summary
- Fixed the mixin directive removal issue in the generated GraphQL operations. The problem was that mixin directives were being preserved in the final printed GraphQL string sent to remote APIs, causing validation errors. Modified the `get_operation_as_str()` method in `ariadne_codegen/client_generators/result_types.py` to create a copy of the operation definition AST with all mixin directives removed before printing it to string. This ensures that: 1. Mixin directives are still processed during code generation to properly extend Pydantic models 2. But they are stripped from the final GraphQL query string sent to remote APIs 3. Both field-level and operation-level mixin directives are handled recursively 4. Other directives and AST structure are preserved The specific test `test_get_operation_as_str_returns_representation_without_mixin_directive` now passes, confirming the fix works correctly.
- Worker outcome
- finished
- Target tests pass: yes
- Full suite passes: no
- Files changed: ariadne_codegen/client_generators/result_types.py
- Ran tests: yes
Witness branch w1
| Kind | Command | Exit | Duration | Digest |
|---|---|---|---|---|
| apply | apply patch e0484aa0cc17exact commandgit update-index -q --refresh; git apply -v --3way --recount --ignore-space-change --whitespace=nowarn /opt/receipts-b9b3cb1ad14c4593a15680585331ace0/incoming/e0484aa0cc173e988287f002e3e4e5326d7e6069986511d605c49981e230b5b5.diff | 0 | 0.010s | 8f617d7e178c |
| verification | pytest (witness) tests/client_generators/result_types_generator/test_get_operation_as_str.py tests/main/clients/extended_models/expected_client/client.pyexact command/opt/receipts-522ce3f129f64b1e9d0da6e00b3e4ea8/bin/busybox mkdir -p /opt/receipts/reports && python -I /opt/receipts-522ce3f129f64b1e9d0da6e00b3e4ea8/receipts_pytest.py --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning tests/client_generators/result_types_generator/test_get_operation_as_str.py tests/main/clients/extended_models/expected_client/client.py -o junit_family=xunit1 -p no:cacheprovider -rA --continue-on-collection-errors --junitxml=/opt/receipts/reports/w1-2.xml | 1 | 1.228s | 8f617d7e178c |
Gate predicate checklist
| Predicate | Name | Status | Evidence |
|---|---|---|---|
R1_fail_to_pass | Failing specification tests now pass | PASS | target tests passed: tests/client_generators/result_types_generator/test_get_operation_as_str.py::test_get_operation_as_str_returns_representation_without_mixin_directive |
R2_pass_to_pass | Previously passing tests kept | PASS | 2 baseline-passing tests still pass |
R3_no_shrink | No removed tests or new skips | PASS | all 4 baseline tests collected; skips unchanged (0) |
R4_patch_scope | Patch scope | PASS | patch touches 1 file(s), all in scope |
R5_provenance | Witness chain and patch digest | PASS | agent chain 3cb2ecec -> e8101032 unbroken over 7 receipt(s); witness chain 3cb2ecec -> 641fd3e7 unbroken over 2 receipt(s); applied digest matches |
R6_claim_audit | Agent claim audit (advisory) | PASS | claimed green; own last run: 1 passed, 0 failed |
What it said
- Finish summary
- Fixed the mixin directive removal issue in the generated GraphQL operations. The problem was that mixin directives were being preserved in the final printed GraphQL string sent to remote APIs, causing validation errors. Modified the `get_operation_as_str()` method in `ariadne_codegen/client_generators/result_types.py` to create a copy of the operation definition AST with all mixin directives removed before printing it to string. This ensures that: 1. Mixin directives are still processed during code generation to properly extend Pydantic models 2. But they are stripped from the final GraphQL query string sent to remote APIs 3. Both field-level and operation-level mixin directives are handled recursively 4. Other directives and AST structure are preserved The specific test `test_get_operation_as_str_returns_representation_without_mixin_directive` now passes, confirming the fix works correctly.
- Worker outcome
- finished
- Target tests pass: yes
- Full suite passes: no
- Files changed: ariadne_codegen/client_generators/result_types.py
- Ran tests: yes
What the record shows
honest: claimed green; own last run: 1 passed, 0 failed
SWE-rebench's official grader: resolved
Agrees with the gate
Shipped patch
diff --git a/ariadne_codegen/client_generators/result_types.py b/ariadne_codegen/client_generators/result_types.pyindex 1a1e9e1..9e2177e 100644--- a/ariadne_codegen/client_generators/result_types.py+++ b/ariadne_codegen/client_generators/result_types.py@@ -167,7 +167,85 @@ class ResultTypesGenerator: return self._class_defs def get_operation_as_str(self) -> str:- operation_str = print_ast(self.operation_definition)+ # Create a copy of the operation definition without mixin directives+ from graphql import OperationDefinitionNode+ + def remove_mixin_directives_from_selections(selections):+ result = []+ for selection in selections:+ if hasattr(selection, 'directives') and selection.directives:+ # Filter out mixin directives+ filtered_directives = [+ d for d in selection.directives + if not (d.name and d.name.value == MIXIN_NAME)+ ]+ # Create a copy of the selection with filtered directives+ if isinstance(selection, FieldNode):+ new_selection = FieldNode(+ alias=selection.alias,+ name=selection.name,+ arguments=selection.arguments,+ directives=filtered_directives,+ selection_set=selection.selection_set+ )+ # Recursively process nested selections+ if new_selection.selection_set:+ new_selection.selection_set = SelectionSetNode(+ selections=remove_mixin_directives_from_selections(+ new_selection.selection_set.selections+ )+ )+ result.append(new_selection)+ elif isinstance(selection, InlineFragmentNode):+ new_selection = InlineFragmentNode(+ type_condition=selection.type_condition,+ directives=filtered_directives,+ selection_set=selection.selection_set+ )+ # Recursively process nested selections+ if new_selection.selection_set:+ new_selection.selection_set = SelectionSetNode(+ selections=remove_mixin_directives_from_selections(+ new_selection.selection_set.selections+ )+ )+ result.append(new_selection)+ elif isinstance(selection, FragmentSpreadNode):+ # Fragment spreads don't typically have directives that matter here,+ # but we copy them anyway+ result.append(selection)+ else:+ result.append(selection)+ else:+ result.append(selection)+ return result++ # Copy the operation definition and remove mixin directives+ if hasattr(self.operation_definition, 'directives'):+ filtered_directives = [+ d for d in self.operation_definition.directives+ if not (d.name and d.name.value == MIXIN_NAME)+ ]+ + if isinstance(self.operation_definition, OperationDefinitionNode):+ cleaned_operation = OperationDefinitionNode(+ operation=self.operation_definition.operation,+ name=self.operation_definition.name,+ variable_definitions=self.operation_definition.variable_definitions,+ directives=filtered_directives,+ selection_set=SelectionSetNode(+ selections=remove_mixin_directives_from_selections(+ self.operation_definition.selection_set.selections+ )+ )+ )+ else:+ # For other executable definitions (shouldn't happen in practice for queries)+ cleaned_operation = self.operation_definition+ else:+ cleaned_operation = self.operation_definition+ + operation_str = print_ast(cleaned_operation) if self._fragments_used_as_mixins or self._unpacked_fragments: for used_fragment in sorted(self._get_all_related_fragments()): operation_str += "\n\n" + print_ast(
Model and costs
- Model
- NVIDIA Nemotron 3 Super thinking off · temperature 1.0 · top_p 0.95
- Tokens
- 139,543 tokens
- Model cost
- $0.04
- Sandbox time
- 1 min 0 s
- Sandbox cost
- Token Factory reported cost: 0.099 (unit not published)
Full environment disclosure
{
"executor_kind": "tokenfactory",
"lock_sha256": "81cf1a129d0adb9b53b703c39af1e21e6ba34525c68264e98710219a1486abeb",
"model": {
"base_url": "https://api.tokenfactory.nebius.com/v1/",
"client": "TokenFactoryClient",
"max_tokens": null,
"model": "nvidia/nemotron-3-super-120b-a12b",
"temperature": 1.0,
"thinking": false,
"top_p": 0.95
},
"pytest_config_digests": {
"pyproject.toml": "0c20b9b269577c21473060dbd929429b9c2ab50bd32641ace600ccdddd99ed0c",
"tests/conftest.py": "d0717cbe8faf6075a87f860d816a573f67d1e217e83dd92991eec1ccbd383d16",
"tests/main/clients/custom_base_client/pyproject.toml": "17b33d1e5b592b77f636d394f5bbea50a13267cdddeab2744cac43c62e8b023b",
"tests/main/clients/custom_files_names/pyproject.toml": "383e9d58a0af2fce93a17e64e12ba7405ba8e9fc30c90abdf1425d94aac702f7",
"tests/main/clients/custom_scalars/pyproject.toml": "36cd70bd6ea1905f5f3e042c1bdfdebb86fdf713a0e440cbd1510037aed7904b",
"tests/main/clients/example/pyproject.toml": "23b08f704271877ff2374219e8564cea019c715e65740135b574ac3336a23a86",
"tests/main/clients/extended_models/pyproject.toml": "f2db0e9e5b11cdc9dfe570e9361e57c5392a11771bd243bb236f1ed2f1d00c1e",
"tests/main/clients/inline_fragments/pyproject.toml": "1b8bf5034ee6343c1ad13478aa5b0fb1508c99c93d2c025b87b1ba8c665d28b7",
"tests/main/clients/multiple_fragments/pyproject.toml": "cb483f930674a9d97b12a203b824a92a4e390ee3844475cb50e67791ac860110",
"tests/main/clients/remote_schema/pyproject.toml": "dd8d33983345a791eca1f0cfd68d923a59880978a683560dd7a10f672499bf77",
"tests/main/clients/shorter_results/pyproject.toml": "6b72bdfd63469ab8392eb9c07435dd23aab3d4ac53908f450b21b95863986f1c",
"tests/main/graphql_schemas/all_types/pyproject.toml": "8d042d0948039b80fc25f7341a04d259fbb66d6567ae44a7cdcb800242d1ed81",
"tests/main/graphql_schemas/example/pyproject.toml": "ca7e70fa6148d2f5f06142660da2badd3b424781209e35a3f265fef338293aaf"
},
"receipts_version": "0.0.1",
"test_digests": {
"tests/client_generators/result_types_generator/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"tests/client_generators/result_types_generator/schema.py": "6a4e93ac6222b79e67b0e5f65c0d42e7457f0e36e52b9aea377166f95ccc9689",
"tests/client_generators/result_types_generator/test_directives.py": "6692b639864fac2ede2f9e256baa1b267968af185e2e74e043ff5586ed73309b",
"tests/client_generators/result_types_generator/test_get_operation_as_str.py": "a8edceda62a7ac76d7fd188b266e55fcb6e3f964d840ee84a2cd092e83bc7eef",
"tests/client_generators/result_types_generator/test_imports.py": "84573c717fdc6a2be9dcf67a0508d922c21ea5308ec76ff9ba7d735d35f68a1d",
"tests/client_generators/result_types_generator/test_methods_calls.py": "bb00e7928ec9ec9cbe656269675b80486a0b2973215c237705568c2c586419c9",
"tests/client_generators/result_types_generator/test_names.py": "80c2ee279d87f72325f3f2595b27602cb3cb3973de9446cefeaf7b4237f2debc",
"tests/client_generators/result_types_generator/test_parsing_fragments.py": "22728407cdcb72a12b990713febe24dd6b396734798d38f38d370cbcd673abce",
"tests/client_generators/result_types_generator/test_parsing_operations.py": "2db2fcd7c7e36da2d165db27af88d5d5aced7eb96679b9febb8eff327745ef45",
"tests/client_generators/result_types_generator/test_plugin_hooks.py": "cea67eb95050c275454d9d7d850109468e8b6f086ef69656759a5011c9ba6976",
"tests/client_generators/result_types_generator/test_unions.py": "ccf7403c6095b1bed3014a513c8026ba85ffe6839a03e9a17db7bc3768e78b25"
}
}The bundle
Recorded JSON and patches. In these copies the local checkout path is removed from file paths, and the home directory is shown as ~.
- attempts/1/filtered.diff
- attempts/1/patch.diff
- attempts/1/verdict.json
- attempts/1/witness/receipts.jsonl
- baseline.json
- branches/agent1/receipts.jsonl
- branches/base/receipts.jsonl
- branches/official1/receipts.jsonl
- branches/w1/receipts.jsonl
- cost.json
- disclosure.json
- input.json
- lock.txt
- plan.json
- record.json
- result.json