Conversation
…colbymchenry#1870) `readJsonFile` copied an unparseable file to `<path>.backup` and warned that it was about to be overwritten. That is the right thing to do just before a write, but every target's `detect()` reads its agent's config through the same helper — and `install --refresh` detects every target in order to skip the ones codegraph was never installed into. So an empty `~/.gemini/config/mcp_config.json`, sitting beside an Antigravity install codegraph does not manage, got a 0-byte `mcp_config.json.backup` and a warning about an overwrite that never came. Detection is meant to be read-only. `readJsonFile` is now a pure read. Preserving an unparseable config moves to `writeJsonFile`, the one place a target replaces a JSON config — so the backup still happens wherever it mattered, and only there. Reads that decide not to write (the legacy-entry cleanups, the uninstall sweeps) no longer leave one behind either. Unchanged on purpose: an install that really does overwrite an empty config still backs it up. Skipping the copy when there is nothing to preserve is a separate call.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1870
The defect
readJsonFileinsrc/installer/targets/shared.tscopied an unparseablefile to
<path>.backupand warned that it was about to be overwritten.That is the right thing to do immediately before a write — but every
target's
detect()reads its agent's config through the same helper,and
install --refreshdetects every target precisely so it can skipthe ones CodeGraph was never installed into.
refreshTargetsdocuments that contract in its own comment — "targetsthat aren't
alreadyConfiguredare skipped untouched" — and the CLI flaghelp says "for already-configured agents only". Detection was quietly
breaking it: the skip decision itself wrote a file.
So the reported setup — an empty
~/.gemini/config/mcp_config.jsonbesidean Antigravity install CodeGraph does not manage — produced a 0-byte
mcp_config.json.backupand a warning about an overwrite that never came.The fix
readJsonFileis now a pure read: missing or unparseable both return{},silently. Preserving an unparseable config moves to
writeJsonFile, thesingle place a target replaces a JSON config, so the backup still happens
everywhere it mattered and only there. Two read-then-decide paths that used
to leave a stray backup when they decided not to write — the
legacy-entry cleanups and the uninstall sweeps — no longer do.
AgentTarget.detectnow carries the read-only contract in its doc commentso a future target does not reintroduce this.
Not changed on purpose
The issue's second suggestion — treat an empty file as
{}with no warning— is deliberately left out of this PR. After this change it only affects the
write path: a real
codegraph installinto an agent whose config is a 0-bytefile still warns and still writes a 0-byte
.backup. Suppressing the copywhen there is genuinely nothing to preserve seems right to me, and the JSONC
targets already do exactly that (
parseConfig:if (!text.trim()) return {}),but it changes what a real install does rather than what detection does, so
it felt like your call rather than a drive-by. Happy to add it here if you want it.
Evidence
Built
main(58c07e8) and this branch, ran the reported command against asandboxed
HOMEcontaining an empty~/.gemini/config/mcp_config.jsonandno CodeGraph entry anywhere.
Before —
main@ 58c07e8After — this branch
The backup still happens where it should. Same sandbox, config set to
{ half a config, running a real install instead of a refresh:Tests
Three new tests in
__tests__/installer-targets.test.tsunderInstaller — detection never writes (#1870): a refresh over anunconfigured agent's unparseable config,
detect()on its own, and aguard that an install which really overwrites one still backs it up first.
The two detection tests fail on the merge base and pass here:
Full suite, macOS:
On Node 24.2.0 the same suite ends with one
Worker exited unexpectedlyin
extraction.test.ts— that reproduces identically onmain@ 58c07e8here (both 252 files passed, 1 error), and the file passes when run on its
own, so it is this machine under parallel load rather than anything in this
change. Test counts line up exactly:
main4445 passed, this branch 4448 —the three new tests and nothing else.
npx tsc --noEmitis clean. A CHANGELOG entry is under[Unreleased]→### Fixes→#### MCP / indexing.Not validated on Windows (no VM here); the change is path-independent
fsplumbing, and the reporter's Windows 11 repro is the same code path.