ReceiptsRecorded runs, model-free verdicts
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

VERIFIED

Agent branch

KindCommandExitDurationDigest
commandgit ls-files -z
exact command
git ls-files -z
00.004s5c1cc527
writewrite ariadne_codegen/client_generators/result_types.py
exact 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'
00.004s4d14159c
commandpytest tests/client_generators/result_types_generator/test_get_operation_as_str.py::test_get_operation_as_str_returns_representation_without_mixin_directive -v
exact 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
01.186s8f617d7e178c
commandpytest tests/client_generators/result_types_generator/test_get_operation_as_str.py -v
exact 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
11.258s8f617d7e178c
commandpytest tests/client_generators/result_types_generator/test_get_operation_as_str.py tests/main/clients/extended_models/expected_client/client.py
exact 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
11.234s8f617d7e178c
commandpytest tests/client_generators/result_types_generator/test_get_operation_as_str.py::test_get_operation_as_str_returns_representation_without_mixin_directive -v
exact 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
01.184s8f617d7e178c
diffcapture patch
exact command
compute 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
00.038s8f617d7e178c
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

KindCommandExitDurationDigest
applyapply patch e0484aa0cc17
exact command
git update-index -q --refresh; git apply -v --3way --recount --ignore-space-change --whitespace=nowarn /opt/receipts-b9b3cb1ad14c4593a15680585331ace0/incoming/e0484aa0cc173e988287f002e3e4e5326d7e6069986511d605c49981e230b5b5.diff
00.010s8f617d7e178c
verificationpytest (witness) tests/client_generators/result_types_generator/test_get_operation_as_str.py tests/main/clients/extended_models/expected_client/client.py
exact 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
11.228s8f617d7e178c

Gate predicate checklist

PredicateNameStatusEvidence
R1_fail_to_passFailing specification tests now passPASStarget 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_passPreviously passing tests keptPASS2 baseline-passing tests still pass
R3_no_shrinkNo removed tests or new skipsPASSall 4 baseline tests collected; skips unchanged (0)
R4_patch_scopePatch scopePASSpatch touches 1 file(s), all in scope
R5_provenanceWitness chain and patch digestPASSagent chain 3cb2ecec -> e8101032 unbroken over 7 receipt(s); witness chain 3cb2ecec -> 641fd3e7 unbroken over 2 receipt(s); applied digest matches
R6_claim_auditAgent claim audit (advisory)PASSclaimed 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 ~.