gd-tools-cli 0.5.0__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/PKG-INFO +93 -54
  2. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/README.md +92 -53
  3. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/pyproject.toml +8 -3
  4. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-coverage/coverage.gd +161 -0
  5. gd_tools_cli-0.6.0/src/gd_tools/addons/gd-tools-editor/coverage_overlay.gd +213 -0
  6. gd_tools_cli-0.6.0/src/gd_tools/addons/gd-tools-editor/dock.gd +313 -0
  7. gd_tools_cli-0.6.0/src/gd_tools/addons/gd-tools-editor/plugin.cfg +7 -0
  8. gd_tools_cli-0.6.0/src/gd_tools/addons/gd-tools-editor/plugin.gd +39 -0
  9. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test.gd +320 -1
  10. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test_preflight.gd +2 -2
  11. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test_runner.gd +50 -6
  12. gd_tools_cli-0.6.0/src/gd_tools/changes.py +117 -0
  13. gd_tools_cli-0.6.0/src/gd_tools/clean.py +264 -0
  14. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/cli.py +345 -22
  15. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/config.py +85 -6
  16. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/orchestrator.py +5 -5
  17. gd_tools_cli-0.6.0/src/gd_tools/coverage/playtest.py +244 -0
  18. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/doctor.py +85 -190
  19. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/errors.py +28 -0
  20. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/init.py +53 -314
  21. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/migration/reporter.py +11 -8
  22. gd_tools_cli-0.6.0/src/gd_tools/native_test/bridge_scan.py +49 -0
  23. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/native_test/command.py +145 -31
  24. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/native_test/discovery.py +29 -16
  25. gd_tools_cli-0.6.0/src/gd_tools/native_test/import_cache.py +185 -0
  26. gd_tools_cli-0.6.0/src/gd_tools/native_test/orchestrator.py +775 -0
  27. gd_tools_cli-0.6.0/src/gd_tools/native_test/preflight_cache.py +239 -0
  28. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/native_test/protocol.py +4 -4
  29. gd_tools_cli-0.6.0/src/gd_tools/schema.py +59 -0
  30. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/watch/loop.py +5 -18
  31. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/watch/mapping.py +36 -1
  32. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/watch/session.py +3 -0
  33. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools_cli.egg-info/PKG-INFO +93 -54
  34. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools_cli.egg-info/SOURCES.txt +10 -1
  35. gd_tools_cli-0.5.0/src/gd_tools/addons/gd-tools-test/gd_tools_gut_bridge.gd +0 -770
  36. gd_tools_cli-0.5.0/src/gd_tools/native_test/bridge_scan.py +0 -141
  37. gd_tools_cli-0.5.0/src/gd_tools/native_test/orchestrator.py +0 -504
  38. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/setup.cfg +0 -0
  39. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/__init__.py +0 -0
  40. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/__main__.py +0 -0
  41. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addon_check.py +0 -0
  42. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/__init__.py +0 -0
  43. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-coverage/post_run_hook.gd +0 -0
  44. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-coverage/pre_run_hook.gd +0 -0
  45. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-test/gd_tools_mock.gd +0 -0
  46. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-test/gd_tools_native_coverage.gd +0 -0
  47. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-test/gd_tools_parameter_naming.gd +0 -0
  48. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test_context.gd +0 -0
  49. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/__init__.py +0 -0
  50. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/cobertura_reporter.py +0 -0
  51. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/diff_reporter.py +0 -0
  52. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/html_reporter.py +0 -0
  53. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/lcov_reporter.py +0 -0
  54. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/omissions.py +0 -0
  55. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/plan_generator.py +0 -0
  56. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/reporter.py +0 -0
  57. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/templates/file.html +0 -0
  58. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/templates/index.html +0 -0
  59. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/coverage/terminal_reporter.py +0 -0
  60. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/file_discovery.py +0 -0
  61. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/format_runner.py +0 -0
  62. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/godot.py +0 -0
  63. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/lint_runner.py +0 -0
  64. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/migration/__init__.py +0 -0
  65. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/migration/apply.py +0 -0
  66. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/migration/gutconfig.py +0 -0
  67. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/migration/rewrite.py +0 -0
  68. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/migration/scan.py +0 -0
  69. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/migration/translate.py +0 -0
  70. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/native_test/__init__.py +0 -0
  71. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/native_test/artifacts.py +0 -0
  72. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/native_test/preflight.py +0 -0
  73. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/output.py +0 -0
  74. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/test_runner.py +0 -0
  75. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/update_check.py +0 -0
  76. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/verbosity.py +0 -0
  77. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/version.py +0 -0
  78. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/watch/__init__.py +0 -0
  79. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/watch/coalescer.py +0 -0
  80. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/watch/observer.py +0 -0
  81. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools/watch/scope.py +0 -0
  82. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools_cli.egg-info/dependency_links.txt +0 -0
  83. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools_cli.egg-info/entry_points.txt +0 -0
  84. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools_cli.egg-info/requires.txt +0 -0
  85. {gd_tools_cli-0.5.0 → gd_tools_cli-0.6.0}/src/gd_tools_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gd-tools-cli
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: A modern development workflow CLI for GDScript projects in Godot 4.5+
5
5
  Author-email: mansyar <m.ansyarafi@gmail.com>
6
6
  License: MIT
@@ -63,9 +63,9 @@ coverage for GDScript that no existing tool provides.
63
63
  Tests are written against `GdToolsTest`, a native GDScript base class that runs
64
64
  inside your Godot project, so a test can touch the real scene tree, await real
65
65
  signals, and assert on real engine objects without leaving the engine. Existing
66
- suites that `extend GutTest` run through the built-in compatibility bridge --
67
- no GUT addon required -- while projects migrate. The bridge is deprecated as of
68
- v0.5.0 and will be removed in v0.6.0.
66
+ suites that `extend GutTest` are no longer runnable -- the GUT compatibility
67
+ bridge was removed in v0.6.0; run `gd-tools migrate` to move them onto
68
+ `GdToolsTest`.
69
69
 
70
70
  One install, one config, one mental model.
71
71
 
@@ -75,8 +75,8 @@ One install, one config, one mental model.
75
75
  |---------|-------------|
76
76
  | **Unified workflow** | One install, one config (`gd-tools.toml`), one mental model for test, lint, format, and coverage. Consistent terminal output with colored markers and summary footers across all commands. |
77
77
  | **Native test runtime** | Tests extend `GdToolsTest` and run inside Godot itself. Scene and resource integration tests reach the real scene tree through an explicit context object rather than a proxy. |
78
- | **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- native test and coverage addons deployed, configs generated. Existing `GutTest` suites run through the built-in compatibility bridge with no addon install. |
79
- | **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and Cobertura reports that integrate with CI and code review tools. `# gd-tools: no cover` annotations exclude debug-only code from the numbers. |
78
+ | **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- native test and coverage addons deployed, configs generated. |
79
+ | **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and Cobertura reports that integrate with CI and code review tools. `# gd-tools: no cover` annotations exclude debug-only code from the numbers. `coverage run` collects coverage during manual playtest sessions, not just automated tests. |
80
80
  | **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura), no interactive prompts in CI mode. |
81
81
  | **Standalone compatibility** | gdlint and gdformat continue to work if invoked directly. `gd-tools` is a layer on top, not a lock-in. |
82
82
 
@@ -119,11 +119,11 @@ directory. The command is idempotent -- safe to re-run. If you've modified
119
119
  coverage addon files, they are automatically backed up to
120
120
  `addons/gd-tools-coverage/.backups/` before being overwritten.
121
121
 
122
- The legacy GUT runtime has been replaced by the built-in compatibility bridge:
123
- suites extending `GutTest` run on the native runtime with no GUT addon
124
- installed. The bridge is deprecated as of v0.5.0 and will be removed in
125
- v0.6.0. See the [migration guide](./docs/gut-migration.md) for the
126
- supported subset and the steps to move fully onto `GdToolsTest`.
122
+ The GUT compatibility bridge was removed in v0.6.0: suites extending `GutTest`
123
+ are no longer runnable -- `gd-tools test` rejects them with exit 2 and
124
+ migration guidance. Run `gd-tools migrate` and see the
125
+ [migration guide](./docs/gut-migration.md) for the steps to move fully onto
126
+ `GdToolsTest`.
127
127
 
128
128
  A test suite is any class extending `GdToolsTest`:
129
129
 
@@ -139,13 +139,13 @@ func test_health_starts_at_full() -> void:
139
139
  | Command | Description |
140
140
  |---------|-------------|
141
141
  | `gd-tools init` | Bootstrap a Godot project -- deploy the native test and coverage addons, generate configs. |
142
- | `gd-tools doctor` | Diagnose the development environment -- Godot, native test addon, bridge-eligible GUT suites, coverage addon, tooling. |
143
- | `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites extending `GdToolsTest` and `GutTest` are detected and routed automatically (`GutTest` suites run through the compatibility bridge). Accepts optional path arguments to override configured test directories. `--watch` re-runs affected suites on `.gd` file changes. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
142
+ | `gd-tools doctor` | Diagnose the development environment -- Godot, native test addon, coverage addon, tooling; reports legacy GUT artifacts as migration advice. |
143
+ | `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites must extend `GdToolsTest`; `GutTest` suites are rejected with exit 2 and migration guidance. Accepts optional path arguments to override configured test directories. `--parallel N` runs suites through a bounded worker pool. `--changed` runs only the suites mapped from git-changed files. `--watch` re-runs affected suites on `.gd` file changes. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
144
144
  | `gd-tools migrate` | Guided GUT-to-native migration. Default: read-only report with unsupported-construct inventory and proposed base-class rewrites. `--apply` renames clean suites to `GdToolsTest` and translates `.gutconfig.json` into `gd-tools.toml` (merge, never clobber). `--config-only` translates config only. |
145
145
  | `gd-tools lint` | Lint GDScript files using gdlint with text or JSON output. Accepts one or more file or directory paths. |
146
146
  | `gd-tools format` | Format GDScript files using gdformat with check and diff modes. Accepts one or more file or directory paths. |
147
- | `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, and `diff` (baseline comparison for CI regression gates). |
148
- | `gd-tools config` | Configuration management -- `show` (display resolved config), `validate` (check config validity). |
147
+ | `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, `diff` (baseline comparison for CI regression gates), and `run` (collect coverage during a manual playtest session). |
148
+ | `gd-tools config` | Configuration management -- `show` (display resolved config), `validate` (check config validity), `schema` (print or write the JSON Schema for `gd-tools.toml`). |
149
149
  | `gd-tools version` | Display versions of all gd-tools components (gd-tools, Godot, gdtoolkit, Python, and GUT when installed) in a table or JSON. |
150
150
  | `gd-tools completion` | Generate shell completion scripts for bash, zsh, fish, or PowerShell. |
151
151
 
@@ -157,10 +157,39 @@ gd-tools test --suite PlayerTests # one suite, by class name
157
157
  gd-tools test --test test_takes_damage # one test method
158
158
  gd-tools test --tag smoke # suites with that class-level tag
159
159
  gd-tools test --test-timeout 30 # per-test timeout, in seconds
160
+ gd-tools test --parallel 4 # run suites with 4 concurrent workers
161
+ gd-tools test --changed # only suites mapped from git-changed files
162
+ gd-tools test --changed --base main # PR/CI mode: diff from merge-base with main
160
163
  ```
161
164
 
162
165
  `--tag` is repeatable, and `--test-timeout` (per test) is separate from
163
- `--timeout` (per suite process).
166
+ `--timeout` (per suite process). `--parallel` dispatches suites to a bounded
167
+ worker pool (1-32 workers; bare `--parallel` means 4) while keeping results,
168
+ JUnit XML, and merged coverage identical to a sequential run. Persist the
169
+ choice with `parallel = 4` under `[test]` in `gd-tools.toml`.
170
+
171
+ `--changed` selects suites from git instead of running everything: uncommitted
172
+ changes (staged, unstaged, and untracked) map to suites by the same
173
+ file→suite convention as `--watch` — `src/enemy.gd` selects
174
+ `tests/test_enemy.gd` or `tests/enemy_test.gd`. A change that maps to no
175
+ suite (e.g. `project.godot` or a scene file) falls back to the full suite
176
+ with an explicit notice, so the selection is safe for CI. The summary line
177
+ reports how many suites were selected; per-file mapping detail prints under
178
+ `--verbose`. Add `--base <ref>` to diff committed changes from
179
+ `merge-base(<ref>, HEAD)` instead of the working tree — the form to use on
180
+ pull-request CI. `--changed` composes with `--parallel`, `--coverage`, and
181
+ the `--suite`/`--test`/`--tag` filters (the active filters bound the
182
+ mapping domain); an empty change set exits 0 without launching Godot.
183
+
184
+ Repeat runs are faster: the `godot --headless --import` step is cached under
185
+ `.gd-tools/native/import-cache/` and skipped when `project.godot`, any
186
+ project source/resource file (scripts, scenes, import sidecars, addons), or
187
+ the Godot version is unchanged. The integration preflight is likewise cached
188
+ under `.gd-tools/native/preflight-cache/` and skipped when the suites, test
189
+ files, `project.godot`, Godot version, and bundled addons are unchanged. Cache
190
+ hit/miss reasons are reported under `--verbose`; `--no-cache` bypasses the
191
+ import, preflight, and coverage plan caches, and `gd-tools clean --cache`
192
+ removes the cache directory.
164
193
 
165
194
  Each run writes a machine-readable artifact index under
166
195
  `.gd-tools/artifacts/<run_id>/`, listing the manifest, result, event stream,
@@ -182,49 +211,33 @@ suite by convention — `src/enemy.gd` re-runs `tests/test_enemy.gd` or
182
211
  `tests/enemy_test.gd` — with a full-suite fallback (announced explicitly)
183
212
  when no suite matches. Rapid successive saves are coalesced into a single
184
213
  re-run, and a save during a running suite queues exactly one follow-up run.
214
+ The same file→suite mapping powers the non-interactive `gd-tools test
215
+ --changed` selection (see [Selecting and Filtering
216
+ Tests](#selecting-and-filtering-tests)).
185
217
 
186
218
  - Native runtime only: the removed legacy GUT runtime (`--runtime gut`) is
187
- rejected with exit 2; `GutTest` suites run through the compatibility bridge.
219
+ rejected with exit 2; `GutTest` suites must be migrated (`gd-tools migrate`).
188
220
  - Interactive only: `--watch` combined with `CI=true` exits 2.
189
221
  - The terminal is cleared between runs; the banner shows how many files are
190
- watched, and `Ctrl+C` always exits 0.
222
+ watched. While idle, `Ctrl+C` exits 0; interrupting an in-flight run kills
223
+ its Godot processes and exits 130.
191
224
  - Positional path arguments are not supported with `--watch`; the watched
192
225
  scope is the project root minus standard excludes (`.godot/`, `.gd-tools/`,
193
226
  `.git/`, and the gd-tools addons).
194
227
 
195
- ### Native Runtime vs. GUT Compatibility Bridge
196
-
197
- The native runtime is the default and the forward path. Suites extending
198
- `GutTest` run through the built-in compatibility bridge on the same native
199
- runner; the bridge is deprecated as of v0.5.0 and will be removed in v0.6.0.
200
-
201
- | Capability | Native runtime (`GdToolsTest`) | Bridge (`GutTest`) |
202
- |------------|----------------|--------------|
203
- | Base class | `GdToolsTest` extends `Node` | `GutTest`, provided by gd-tools (no GUT addon) |
204
- | Discovery | `test_*` methods, by directory or exact file selector | Same; routed automatically per file |
205
- | Lifecycle hooks | `before_all`, `after_all`, `before_each`, `after_each` | Same, plus `prerun_setup` and `postrun_teardown` |
206
- | Assertions | Full native assertion set plus `fail()`, `skip_test()`, `pending_test()` | Documented GUT core subset -- unsupported constructs fail at preflight |
207
- | Async waits | `wait_process_frame`, `wait_physics_frames`, `wait_seconds`, `wait_for_signal(signal, timeout)` | GUT helper family, incl. `wait_until`, `wait_while`, `yield_*` |
208
- | Tags | Class-level tags, filtered with `--tag` | Same |
209
- | Test selectors | `--suite`, `--test`, `--test-timeout` | Same |
210
- | Scene and resource integration | `const INTEGRATION` plus `GdToolsTestContext` for scene root, node lookup, named resources, and bounded signal waits | Not wired into the bridge shim |
211
- | Retries | Configurable per test (`[test].retries`) | Same |
212
- | Line and branch coverage | Yes | Yes |
213
- | JUnit XML output | Yes | Yes |
214
- | Mocking and stubbing | `double()`, `partial_double()`, `stub()` (`.to_return`/`.to_call_super`), `assert_called*` family | Same -- inherited from `GdToolsTest` with identical semantics |
215
- | Parameterized tests | `parameterize()` in `before_all`, values injected via `use_parameters` | Not supported -- preflight rejects `parameterize()` |
216
- | Skipping a test at runtime | `skip_test()` and `pending_test()` | Yes |
217
- | Parallel execution | Not yet -- suites run sequentially | Same |
218
- | Editor plugin | Not yet | Not applicable |
219
-
220
- **Known limitations.** Parameterized tests are native-only -- the bridge
221
- deliberately refuses `parameterize()` at preflight rather than mis-running
222
- them, so such suites must migrate to `GdToolsTest`. Suites run sequentially;
223
- parallel execution is planned but not yet available. The bridge itself is
224
- deprecated as of v0.5.0 and will be removed in v0.6.0. See the
225
- [migration guide](./docs/gut-migration.md) for the bridge's supported subset,
226
- [User Guide](./docs/USER_GUIDE.md#34-test) for the full flag reference, and
227
- [Roadmap](./docs/ROADMAP.md#8-temporary-native-test-runtime-migration-roadmap)
228
+ ### Migrating Legacy GUT Suites
229
+
230
+ The GUT compatibility bridge was removed in v0.6.0; the native runtime
231
+ (`GdToolsTest`) is the only supported runtime. Suites extending `GutTest` are
232
+ rejected by `gd-tools test` with exit 2 and migration guidance, and
233
+ `--runtime gut` is rejected the same way. Run `gd-tools migrate` and see the
234
+ [migration guide](./docs/gut-migration.md) to move legacy suites onto the
235
+ native runtime.
236
+
237
+ **Known limitations.** Parallel execution is opt-in and off by default
238
+ (`--parallel N` / `[test].parallel`); suites run sequentially without it. See
239
+ the [User Guide](./docs/USER_GUIDE.md#34-test) for the full flag reference and
240
+ [Roadmap](./docs/ROADMAP.md#native-runtime-transition-completed-foundation)
228
241
  for what is planned.
229
242
 
230
243
  ### Verbosity Control
@@ -320,10 +333,11 @@ binary = "" # Optional -- auto-detected if unset
320
333
  test_dirs = ["test", "tests"]
321
334
  prefix = "test_"
322
335
  suffix = ".gd"
323
- gutconfig = ".gutconfig.json" # legacy; not read by the native runtime or the bridge
336
+ gutconfig = ".gutconfig.json" # legacy; not read by any runtime
324
337
  runtime = "native" # native (default); "gut" is no longer a runnable runtime
325
338
  timeout_seconds = 5.0 # default per-test timeout for async native tests
326
339
  retries = 0 # opt-in retries per native test
340
+ # parallel = 4 # opt-in parallel suite execution (1-32; unset runs sequentially)
327
341
  tags = [] # native suite tag filters
328
342
 
329
343
  [lint]
@@ -341,6 +355,32 @@ exclude = ["addons", ".godot", ".gd-tools", ".git"]
341
355
  test_dirs = ["test", "tests"]
342
356
  ```
343
357
 
358
+ ### Editor Autocomplete & Validation
359
+
360
+ `gd-tools` publishes a JSON Schema for `gd-tools.toml` at
361
+ [`docs/gd-tools.schema.json`](./docs/gd-tools.schema.json). Add a
362
+ `"$schema"` key to your config to enable autocomplete and inline
363
+ validation in editors that support TOML schemas:
364
+
365
+ ```toml
366
+ "$schema" = "https://raw.githubusercontent.com/mansyar/gd-tools/main/docs/gd-tools.schema.json"
367
+ ```
368
+
369
+ The key is accepted and ignored by the CLI — it carries no runtime
370
+ meaning.
371
+
372
+ - **VS Code** (with [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml)):
373
+ the `"$schema"` key above is picked up automatically. Alternatively,
374
+ associate the schema by filename in your settings:
375
+ `"even-better-toml.schema.associations": {"gd-tools.toml": "https://raw.githubusercontent.com/mansyar/gd-tools/main/docs/gd-tools.schema.json"}`
376
+ - **taplo** (CLI / LSP): the `"$schema"` key works out of the box, or
377
+ add a `schema` entry to your `taplo.toml` pointing at the URL above.
378
+
379
+ The schema is regenerated with
380
+ `gd-tools config schema --output docs/gd-tools.schema.json`;
381
+ a unit test keeps the checked-in snapshot in sync with the installed
382
+ version's config model.
383
+
344
384
  See the [User Guide](./docs/USER_GUIDE.md) for a full configuration reference
345
385
  with all keys, defaults, and examples.
346
386
 
@@ -397,8 +437,7 @@ hard parts.
397
437
 
398
438
  - **[GUT (Godot Unit Test)](https://github.com/bitwes/Gut)** by
399
439
  [bitwes](https://github.com/bitwes): the GDScript test framework whose
400
- core API the built-in compatibility bridge reproduces while projects
401
- migrate to the native runtime.
440
+ core API informed the native runtime's assertion surface.
402
441
  - **[gdtoolkit](https://github.com/Scony/godot-gdscript-toolkit)** by
403
442
  [Scony](https://github.com/Scony): provides `gdlint` and `gdformat`, which
404
443
  `gd-tools lint` and `gd-tools format` wrap.
@@ -22,9 +22,9 @@ coverage for GDScript that no existing tool provides.
22
22
  Tests are written against `GdToolsTest`, a native GDScript base class that runs
23
23
  inside your Godot project, so a test can touch the real scene tree, await real
24
24
  signals, and assert on real engine objects without leaving the engine. Existing
25
- suites that `extend GutTest` run through the built-in compatibility bridge --
26
- no GUT addon required -- while projects migrate. The bridge is deprecated as of
27
- v0.5.0 and will be removed in v0.6.0.
25
+ suites that `extend GutTest` are no longer runnable -- the GUT compatibility
26
+ bridge was removed in v0.6.0; run `gd-tools migrate` to move them onto
27
+ `GdToolsTest`.
28
28
 
29
29
  One install, one config, one mental model.
30
30
 
@@ -34,8 +34,8 @@ One install, one config, one mental model.
34
34
  |---------|-------------|
35
35
  | **Unified workflow** | One install, one config (`gd-tools.toml`), one mental model for test, lint, format, and coverage. Consistent terminal output with colored markers and summary footers across all commands. |
36
36
  | **Native test runtime** | Tests extend `GdToolsTest` and run inside Godot itself. Scene and resource integration tests reach the real scene tree through an explicit context object rather than a proxy. |
37
- | **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- native test and coverage addons deployed, configs generated. Existing `GutTest` suites run through the built-in compatibility bridge with no addon install. |
38
- | **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and Cobertura reports that integrate with CI and code review tools. `# gd-tools: no cover` annotations exclude debug-only code from the numbers. |
37
+ | **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- native test and coverage addons deployed, configs generated. |
38
+ | **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and Cobertura reports that integrate with CI and code review tools. `# gd-tools: no cover` annotations exclude debug-only code from the numbers. `coverage run` collects coverage during manual playtest sessions, not just automated tests. |
39
39
  | **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura), no interactive prompts in CI mode. |
40
40
  | **Standalone compatibility** | gdlint and gdformat continue to work if invoked directly. `gd-tools` is a layer on top, not a lock-in. |
41
41
 
@@ -78,11 +78,11 @@ directory. The command is idempotent -- safe to re-run. If you've modified
78
78
  coverage addon files, they are automatically backed up to
79
79
  `addons/gd-tools-coverage/.backups/` before being overwritten.
80
80
 
81
- The legacy GUT runtime has been replaced by the built-in compatibility bridge:
82
- suites extending `GutTest` run on the native runtime with no GUT addon
83
- installed. The bridge is deprecated as of v0.5.0 and will be removed in
84
- v0.6.0. See the [migration guide](./docs/gut-migration.md) for the
85
- supported subset and the steps to move fully onto `GdToolsTest`.
81
+ The GUT compatibility bridge was removed in v0.6.0: suites extending `GutTest`
82
+ are no longer runnable -- `gd-tools test` rejects them with exit 2 and
83
+ migration guidance. Run `gd-tools migrate` and see the
84
+ [migration guide](./docs/gut-migration.md) for the steps to move fully onto
85
+ `GdToolsTest`.
86
86
 
87
87
  A test suite is any class extending `GdToolsTest`:
88
88
 
@@ -98,13 +98,13 @@ func test_health_starts_at_full() -> void:
98
98
  | Command | Description |
99
99
  |---------|-------------|
100
100
  | `gd-tools init` | Bootstrap a Godot project -- deploy the native test and coverage addons, generate configs. |
101
- | `gd-tools doctor` | Diagnose the development environment -- Godot, native test addon, bridge-eligible GUT suites, coverage addon, tooling. |
102
- | `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites extending `GdToolsTest` and `GutTest` are detected and routed automatically (`GutTest` suites run through the compatibility bridge). Accepts optional path arguments to override configured test directories. `--watch` re-runs affected suites on `.gd` file changes. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
101
+ | `gd-tools doctor` | Diagnose the development environment -- Godot, native test addon, coverage addon, tooling; reports legacy GUT artifacts as migration advice. |
102
+ | `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites must extend `GdToolsTest`; `GutTest` suites are rejected with exit 2 and migration guidance. Accepts optional path arguments to override configured test directories. `--parallel N` runs suites through a bounded worker pool. `--changed` runs only the suites mapped from git-changed files. `--watch` re-runs affected suites on `.gd` file changes. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
103
103
  | `gd-tools migrate` | Guided GUT-to-native migration. Default: read-only report with unsupported-construct inventory and proposed base-class rewrites. `--apply` renames clean suites to `GdToolsTest` and translates `.gutconfig.json` into `gd-tools.toml` (merge, never clobber). `--config-only` translates config only. |
104
104
  | `gd-tools lint` | Lint GDScript files using gdlint with text or JSON output. Accepts one or more file or directory paths. |
105
105
  | `gd-tools format` | Format GDScript files using gdformat with check and diff modes. Accepts one or more file or directory paths. |
106
- | `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, and `diff` (baseline comparison for CI regression gates). |
107
- | `gd-tools config` | Configuration management -- `show` (display resolved config), `validate` (check config validity). |
106
+ | `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, `diff` (baseline comparison for CI regression gates), and `run` (collect coverage during a manual playtest session). |
107
+ | `gd-tools config` | Configuration management -- `show` (display resolved config), `validate` (check config validity), `schema` (print or write the JSON Schema for `gd-tools.toml`). |
108
108
  | `gd-tools version` | Display versions of all gd-tools components (gd-tools, Godot, gdtoolkit, Python, and GUT when installed) in a table or JSON. |
109
109
  | `gd-tools completion` | Generate shell completion scripts for bash, zsh, fish, or PowerShell. |
110
110
 
@@ -116,10 +116,39 @@ gd-tools test --suite PlayerTests # one suite, by class name
116
116
  gd-tools test --test test_takes_damage # one test method
117
117
  gd-tools test --tag smoke # suites with that class-level tag
118
118
  gd-tools test --test-timeout 30 # per-test timeout, in seconds
119
+ gd-tools test --parallel 4 # run suites with 4 concurrent workers
120
+ gd-tools test --changed # only suites mapped from git-changed files
121
+ gd-tools test --changed --base main # PR/CI mode: diff from merge-base with main
119
122
  ```
120
123
 
121
124
  `--tag` is repeatable, and `--test-timeout` (per test) is separate from
122
- `--timeout` (per suite process).
125
+ `--timeout` (per suite process). `--parallel` dispatches suites to a bounded
126
+ worker pool (1-32 workers; bare `--parallel` means 4) while keeping results,
127
+ JUnit XML, and merged coverage identical to a sequential run. Persist the
128
+ choice with `parallel = 4` under `[test]` in `gd-tools.toml`.
129
+
130
+ `--changed` selects suites from git instead of running everything: uncommitted
131
+ changes (staged, unstaged, and untracked) map to suites by the same
132
+ file→suite convention as `--watch` — `src/enemy.gd` selects
133
+ `tests/test_enemy.gd` or `tests/enemy_test.gd`. A change that maps to no
134
+ suite (e.g. `project.godot` or a scene file) falls back to the full suite
135
+ with an explicit notice, so the selection is safe for CI. The summary line
136
+ reports how many suites were selected; per-file mapping detail prints under
137
+ `--verbose`. Add `--base <ref>` to diff committed changes from
138
+ `merge-base(<ref>, HEAD)` instead of the working tree — the form to use on
139
+ pull-request CI. `--changed` composes with `--parallel`, `--coverage`, and
140
+ the `--suite`/`--test`/`--tag` filters (the active filters bound the
141
+ mapping domain); an empty change set exits 0 without launching Godot.
142
+
143
+ Repeat runs are faster: the `godot --headless --import` step is cached under
144
+ `.gd-tools/native/import-cache/` and skipped when `project.godot`, any
145
+ project source/resource file (scripts, scenes, import sidecars, addons), or
146
+ the Godot version is unchanged. The integration preflight is likewise cached
147
+ under `.gd-tools/native/preflight-cache/` and skipped when the suites, test
148
+ files, `project.godot`, Godot version, and bundled addons are unchanged. Cache
149
+ hit/miss reasons are reported under `--verbose`; `--no-cache` bypasses the
150
+ import, preflight, and coverage plan caches, and `gd-tools clean --cache`
151
+ removes the cache directory.
123
152
 
124
153
  Each run writes a machine-readable artifact index under
125
154
  `.gd-tools/artifacts/<run_id>/`, listing the manifest, result, event stream,
@@ -141,49 +170,33 @@ suite by convention — `src/enemy.gd` re-runs `tests/test_enemy.gd` or
141
170
  `tests/enemy_test.gd` — with a full-suite fallback (announced explicitly)
142
171
  when no suite matches. Rapid successive saves are coalesced into a single
143
172
  re-run, and a save during a running suite queues exactly one follow-up run.
173
+ The same file→suite mapping powers the non-interactive `gd-tools test
174
+ --changed` selection (see [Selecting and Filtering
175
+ Tests](#selecting-and-filtering-tests)).
144
176
 
145
177
  - Native runtime only: the removed legacy GUT runtime (`--runtime gut`) is
146
- rejected with exit 2; `GutTest` suites run through the compatibility bridge.
178
+ rejected with exit 2; `GutTest` suites must be migrated (`gd-tools migrate`).
147
179
  - Interactive only: `--watch` combined with `CI=true` exits 2.
148
180
  - The terminal is cleared between runs; the banner shows how many files are
149
- watched, and `Ctrl+C` always exits 0.
181
+ watched. While idle, `Ctrl+C` exits 0; interrupting an in-flight run kills
182
+ its Godot processes and exits 130.
150
183
  - Positional path arguments are not supported with `--watch`; the watched
151
184
  scope is the project root minus standard excludes (`.godot/`, `.gd-tools/`,
152
185
  `.git/`, and the gd-tools addons).
153
186
 
154
- ### Native Runtime vs. GUT Compatibility Bridge
155
-
156
- The native runtime is the default and the forward path. Suites extending
157
- `GutTest` run through the built-in compatibility bridge on the same native
158
- runner; the bridge is deprecated as of v0.5.0 and will be removed in v0.6.0.
159
-
160
- | Capability | Native runtime (`GdToolsTest`) | Bridge (`GutTest`) |
161
- |------------|----------------|--------------|
162
- | Base class | `GdToolsTest` extends `Node` | `GutTest`, provided by gd-tools (no GUT addon) |
163
- | Discovery | `test_*` methods, by directory or exact file selector | Same; routed automatically per file |
164
- | Lifecycle hooks | `before_all`, `after_all`, `before_each`, `after_each` | Same, plus `prerun_setup` and `postrun_teardown` |
165
- | Assertions | Full native assertion set plus `fail()`, `skip_test()`, `pending_test()` | Documented GUT core subset -- unsupported constructs fail at preflight |
166
- | Async waits | `wait_process_frame`, `wait_physics_frames`, `wait_seconds`, `wait_for_signal(signal, timeout)` | GUT helper family, incl. `wait_until`, `wait_while`, `yield_*` |
167
- | Tags | Class-level tags, filtered with `--tag` | Same |
168
- | Test selectors | `--suite`, `--test`, `--test-timeout` | Same |
169
- | Scene and resource integration | `const INTEGRATION` plus `GdToolsTestContext` for scene root, node lookup, named resources, and bounded signal waits | Not wired into the bridge shim |
170
- | Retries | Configurable per test (`[test].retries`) | Same |
171
- | Line and branch coverage | Yes | Yes |
172
- | JUnit XML output | Yes | Yes |
173
- | Mocking and stubbing | `double()`, `partial_double()`, `stub()` (`.to_return`/`.to_call_super`), `assert_called*` family | Same -- inherited from `GdToolsTest` with identical semantics |
174
- | Parameterized tests | `parameterize()` in `before_all`, values injected via `use_parameters` | Not supported -- preflight rejects `parameterize()` |
175
- | Skipping a test at runtime | `skip_test()` and `pending_test()` | Yes |
176
- | Parallel execution | Not yet -- suites run sequentially | Same |
177
- | Editor plugin | Not yet | Not applicable |
178
-
179
- **Known limitations.** Parameterized tests are native-only -- the bridge
180
- deliberately refuses `parameterize()` at preflight rather than mis-running
181
- them, so such suites must migrate to `GdToolsTest`. Suites run sequentially;
182
- parallel execution is planned but not yet available. The bridge itself is
183
- deprecated as of v0.5.0 and will be removed in v0.6.0. See the
184
- [migration guide](./docs/gut-migration.md) for the bridge's supported subset,
185
- [User Guide](./docs/USER_GUIDE.md#34-test) for the full flag reference, and
186
- [Roadmap](./docs/ROADMAP.md#8-temporary-native-test-runtime-migration-roadmap)
187
+ ### Migrating Legacy GUT Suites
188
+
189
+ The GUT compatibility bridge was removed in v0.6.0; the native runtime
190
+ (`GdToolsTest`) is the only supported runtime. Suites extending `GutTest` are
191
+ rejected by `gd-tools test` with exit 2 and migration guidance, and
192
+ `--runtime gut` is rejected the same way. Run `gd-tools migrate` and see the
193
+ [migration guide](./docs/gut-migration.md) to move legacy suites onto the
194
+ native runtime.
195
+
196
+ **Known limitations.** Parallel execution is opt-in and off by default
197
+ (`--parallel N` / `[test].parallel`); suites run sequentially without it. See
198
+ the [User Guide](./docs/USER_GUIDE.md#34-test) for the full flag reference and
199
+ [Roadmap](./docs/ROADMAP.md#native-runtime-transition-completed-foundation)
187
200
  for what is planned.
188
201
 
189
202
  ### Verbosity Control
@@ -279,10 +292,11 @@ binary = "" # Optional -- auto-detected if unset
279
292
  test_dirs = ["test", "tests"]
280
293
  prefix = "test_"
281
294
  suffix = ".gd"
282
- gutconfig = ".gutconfig.json" # legacy; not read by the native runtime or the bridge
295
+ gutconfig = ".gutconfig.json" # legacy; not read by any runtime
283
296
  runtime = "native" # native (default); "gut" is no longer a runnable runtime
284
297
  timeout_seconds = 5.0 # default per-test timeout for async native tests
285
298
  retries = 0 # opt-in retries per native test
299
+ # parallel = 4 # opt-in parallel suite execution (1-32; unset runs sequentially)
286
300
  tags = [] # native suite tag filters
287
301
 
288
302
  [lint]
@@ -300,6 +314,32 @@ exclude = ["addons", ".godot", ".gd-tools", ".git"]
300
314
  test_dirs = ["test", "tests"]
301
315
  ```
302
316
 
317
+ ### Editor Autocomplete & Validation
318
+
319
+ `gd-tools` publishes a JSON Schema for `gd-tools.toml` at
320
+ [`docs/gd-tools.schema.json`](./docs/gd-tools.schema.json). Add a
321
+ `"$schema"` key to your config to enable autocomplete and inline
322
+ validation in editors that support TOML schemas:
323
+
324
+ ```toml
325
+ "$schema" = "https://raw.githubusercontent.com/mansyar/gd-tools/main/docs/gd-tools.schema.json"
326
+ ```
327
+
328
+ The key is accepted and ignored by the CLI — it carries no runtime
329
+ meaning.
330
+
331
+ - **VS Code** (with [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml)):
332
+ the `"$schema"` key above is picked up automatically. Alternatively,
333
+ associate the schema by filename in your settings:
334
+ `"even-better-toml.schema.associations": {"gd-tools.toml": "https://raw.githubusercontent.com/mansyar/gd-tools/main/docs/gd-tools.schema.json"}`
335
+ - **taplo** (CLI / LSP): the `"$schema"` key works out of the box, or
336
+ add a `schema` entry to your `taplo.toml` pointing at the URL above.
337
+
338
+ The schema is regenerated with
339
+ `gd-tools config schema --output docs/gd-tools.schema.json`;
340
+ a unit test keeps the checked-in snapshot in sync with the installed
341
+ version's config model.
342
+
303
343
  See the [User Guide](./docs/USER_GUIDE.md) for a full configuration reference
304
344
  with all keys, defaults, and examples.
305
345
 
@@ -356,8 +396,7 @@ hard parts.
356
396
 
357
397
  - **[GUT (Godot Unit Test)](https://github.com/bitwes/Gut)** by
358
398
  [bitwes](https://github.com/bitwes): the GDScript test framework whose
359
- core API the built-in compatibility bridge reproduces while projects
360
- migrate to the native runtime.
399
+ core API informed the native runtime's assertion surface.
361
400
  - **[gdtoolkit](https://github.com/Scony/godot-gdscript-toolkit)** by
362
401
  [Scony](https://github.com/Scony): provides `gdlint` and `gdformat`, which
363
402
  `gd-tools lint` and `gd-tools format` wrap.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gd-tools-cli"
7
- version = "0.5.0"
7
+ version = "0.6.0"
8
8
  description = "A modern development workflow CLI for GDScript projects in Godot 4.5+"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -61,7 +61,12 @@ gd-tools = "gd_tools.cli:cli"
61
61
  where = ["src"]
62
62
 
63
63
  [tool.setuptools.package-data]
64
- "gd_tools.addons" = ["gd-tools-coverage/*.gd", "gd-tools-test/*.gd"]
64
+ "gd_tools.addons" = [
65
+ "gd-tools-coverage/*.gd",
66
+ "gd-tools-test/*.gd",
67
+ "gd-tools-editor/*.gd",
68
+ "gd-tools-editor/plugin.cfg",
69
+ ]
65
70
  "gd_tools.coverage" = ["templates/*.html"]
66
71
 
67
72
  [tool.pytest.ini_options]
@@ -100,7 +105,7 @@ target-version = ["py310"]
100
105
 
101
106
  [tool.commitizen]
102
107
  name = "cz_conventional_commits"
103
- version = "0.5.0"
108
+ version = "0.6.0"
104
109
  version_files = ["pyproject.toml:version"]
105
110
  changelog_file = "CHANGELOG.md"
106
111
  tag_format = "v$version"