Hi @Kus-Sl! I’m Dosu and I’m helping the Tuist team.
This looks like a bug in DeleteDerivedDirectoryProjectMapper. On every tuist generate run, this mapper scans Derived/ and emits delete side effects for everything inside it — except directories listed in preservedDerivedDirectories, which only contains ModuleMaps and FrameworkSearchPaths [1]. The TestPlans subdirectory is not in that preserve list, so it gets scheduled for deletion.
Here’s what happens across two runs:
- First run: No
Derived/exists yet, so the mapper returns early with no side effects. The test plan side effect then createsDerived/TestPlans/GeneratedTestPlan.xctestplan. - Second run:
Derived/TestPlans/now exists on disk. The mapper sees it isn’t preserved and emits.directory(state: .absent)[2]. Side effects execute sequentially [3], so the test plan file gets written first and then the directory delete runs, removing it.
The fix would be to add Constants.DerivedDirectory.testPlans ("TestPlans") to the preservedDerivedDirectories set [4] — the same way ModuleMaps and FrameworkSearchPaths are preserved today [5].
Since this is a bug with generated projects, you can try using the debug-generated-project skill with a coding agent like Claude, Codex, or OpenCode (following the steps in this repo) to validate and implement the fix against your local Tuist build. The example project at examples/xcode/generated_app_with_generated_test_plan already reproduces it reliably.
To reply, just mention @dosu.
Share context across your team and agents. Try Dosu.