Skip to content

harden(plugin): stop JSON config re-sort, honor UI opt-out over falsey env#549

Merged
dsarno merged 2 commits into
mainfrom
harden/config-telemetry
Jun 10, 2026
Merged

harden(plugin): stop JSON config re-sort, honor UI opt-out over falsey env#549
dsarno merged 2 commits into
mainfrom
harden/config-telemetry

Conversation

@dsarno

@dsarno dsarno commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Wave 2 hardening — review findings TC-2 / TC-4 (#528, #530).

Test

New test_server_lifecycle case for the falsey-env opt-out (20/20). clients (93), settings, telemetry_toggle, plugin_telemetry all green; parse clean.

Closes #528, #530.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

… falsey env

Config/telemetry correctness fixes from the pre-release review.

JSON client-config writes (#528 / TC-2):
- Default JSON.stringify(sort_keys) is true, so every rewrite alphabetically
  reordered the user's whole file (unrelated MCP entries and, for ~/.claude.json,
  the entire CLI state). Pass sort_keys=false.
- Godot parses every JSON number as a float, so the same round-trip re-emitted
  the user's integer fields as "8080.0" — rejected by strict consumers and
  churning every number in their other entries. A _narrow_integral_numbers pass
  re-narrows exactly-representable integral floats back to int before serializing
  so ints stay ints. (Values above 2^53 already lost precision at parse and are
  left as-is — byte-perfect preservation would mean not parsing the file, and
  such magnitudes don't occur in client configs.)

Telemetry opt-out (#530 / TC-4):
- _inject_telemetry_env() skipped injection whenever GODOT_AI_DISABLE_TELEMETRY /
  DISABLE_TELEMETRY was *present*, even set to a falsey "0". The Python server
  parses those truthily (falsey => enabled), so a dock UI opt-out silently
  shipped telemetry. Now only a *truthy* env var counts as "already disabled"
  (matching McpSettings.telemetry_enabled / the server); a falsey/absent value
  falls through so the opt-out reaches the spawn. The truthy guard is kept so
  post-spawn cleanup doesn't strip a user's own var. Fixed the contradicting
  telemetry.gd comment too.

Tests (live Godot 4.6.x): clients 94/94 incl. new integer-preservation case;
server_lifecycle 20/20 incl. new falsey-env opt-out case; parse clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens the Godot plugin’s MCP client configuration and telemetry spawning behavior to avoid unintended user config churn and to ensure the dock UI telemetry opt-out is correctly propagated to the spawned Python server.

Changes:

  • Prevent JSON config rewrites from re-sorting keys by writing with JSON.stringify(..., sort_keys=false).
  • Add _narrow_integral_numbers() to re-narrow integral floats back to ints before stringifying, avoiding 8080.0-style churn.
  • Fix telemetry env injection logic to only treat truthy disable env vars as “already disabled”, and add regression tests.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
plugin/addons/godot_ai/clients/_json_strategy.gd Writes JSON without key sorting and narrows integral floats back to ints before stringifying.
plugin/addons/godot_ai/utils/server_lifecycle.gd Treats only truthy disable env vars as “already disabled” when deciding whether to inject GODOT_AI_DISABLE_TELEMETRY.
plugin/addons/godot_ai/telemetry.gd Aligns the header comment with the “truthy env disables, else fall through to EditorSetting” semantics.
test_project/tests/test_clients.gd Adds coverage for preserving integer formatting in JSON configs.
test_project/tests/test_server_lifecycle.gd Adds coverage for the falsey-env + UI opt-out telemetry injection case.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugin/addons/godot_ai/clients/_json_strategy.gd
Comment on lines 372 to 376
## Sets GODOT_AI_DISABLE_TELEMETRY in the process environment for the
## upcoming OS.create_process call if: (a) neither GODOT_AI_DISABLE_TELEMETRY
## nor DISABLE_TELEMETRY is already set, and (b) the EditorSettings key
## "godot_ai/telemetry_enabled" is set to false. Returns true if the var was
## injected so the caller can unset it after spawning.
Comment thread test_project/tests/test_clients.gd Outdated
Comment on lines +848 to +850
assert_false(content.contains('"retries": 3.0'), "retries must not be floatified")
assert_false(content.contains('"numStartups": 47.0'), "top-level int must not be floatified")
assert_false(content.contains("1.0,") or content.contains("2.0,"), "array ints must not be floatified")
- _narrow_integral_numbers: include exactly 2^53 in the narrow bound (< -> <=).
  2^53 is exactly representable as a double, so it should serialize as an int;
  the previous strict-less bound left it as "9007199254740992.0", contradicting
  the comment that only values *above* 2^53 are kept as floats.
- Update the _inject_telemetry_env outer doc comment to match the implementation
  (only a *truthy* disable env var counts as "already disabled"; a falsey "0"
  falls through so the UI opt-out still reaches the spawn).
- Strengthen the array-int test to check each element regardless of trailing
  comma, so a floatified last element ("3.0" with no comma) is also caught.

Live Godot 4.6.x: clients 94/94, server_lifecycle 20/20.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@dsarno dsarno merged commit a74c1c9 into main Jun 10, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[robustness] JSON config rewrite mangles every number (int -> 8080.0), re-sorts all keys, loses int64 precision

2 participants