Skip to content

fix(config): deep-compare arrays in config diff to eliminate reload false-positives#154

Open
Gucc111 wants to merge 2 commits into
OpenBMB:mainfrom
Gucc111:fix/147-config-reload-false-positive
Open

fix(config): deep-compare arrays in config diff to eliminate reload false-positives#154
Gucc111 wants to merge 2 commits into
OpenBMB:mainfrom
Gucc111:fix/147-config-reload-false-positive

Conversation

@Gucc111
Copy link
Copy Markdown
Collaborator

@Gucc111 Gucc111 commented Jun 4, 2026

Summary

  • Fix diffValues in classifyChanges.ts to recursively compare arrays element-by-element instead of using Object.is() reference equality. This eliminates false-positive config change detection that caused unnecessary runtime invalidation and always-on restart cycles.
  • Add 15 unit tests covering array deep comparison, issue Config reload false-positive causes runtime invalidation and always-on restart #147 scenario reproduction, object diff regression, and edge cases.

Closes #147

Root Cause

diffValues used isDiffableObject() which explicitly excludes arrays (!Array.isArray(value)), causing arrays to fall through to the Object.is() leaf comparison. Since every loadPilotConfig() call creates new array instances via [...DEFAULT_*] / .map() / .filter(), identical arrays with different references were always reported as changed.

The 6 affected fields — alwaysOn.dormancy.ignoreGlobs, model.providers.*.models.*.multimodal.input, router.autoOrchestrate.allowedTools, router.autoOrchestrate.triggerTiers, router.fallback.default, router.tokenSaver.rules — are all array-typed config values that get freshly allocated on each parse.

Test plan

  • 15 new unit tests all pass (node --test)
  • Start PilotDeck, click "Reload Current" in Settings without modifying config — no Config reloaded, invalidating runtimes log should appear
  • Send a chat message — no spurious config reload log on turn start
  • Edit a scalar field in pilotdeck.yaml (e.g. alwaysOn.dormancy.debounceMs) — only that field is reported, no array fields leak into the diff

Made with Cursor

Gucc111 and others added 2 commits June 4, 2026 14:54
…alse-positives (OpenBMB#147)

diffValues treated arrays as leaf values and compared them by reference
(Object.is), so every reload created new array instances that were
always reported as changed. This caused spurious runtime invalidation
and always-on stop/start cycles. Add recursive element-wise comparison
for arrays alongside the existing object diff logic.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

Config reload false-positive causes runtime invalidation and always-on restart

1 participant