mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-25 12:00:02 +08:00
013b91c1be37ca6a6ee2c19bb89be56dd0faa37a
10
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
57ce5b9cdc |
fix(upgrade): a global npm install is upgraded with -g from any folder, even home (#2777)
codegraph upgrade told a global npm install from a local one by whether the running file sat under the current folder. npm's global folder is often inside the home folder (Windows %APPDATA%\npm, nvm, fnm, ~/.npm-global), so run from home every such global install was taken for a local one: npm ran without -g, the global copy stayed on the old version and a second copy landed in the home folder. The same test sent a project's own install to npm -g when upgrade ran from one of its subfolders or from outside it, and installed into the parent folder instead when it ran from one. The scope now comes from npm's layout around the outermost node_modules. A global launcher beside it (<prefix>\codegraph.cmd on Windows, <prefix>/bin/codegraph next to <prefix>/lib on POSIX) means global. A project around it (node_modules/.bin/codegraph or a package.json) means local, and npm then runs in that project, wherever upgrade was run from; the version npm left there is read back, with a warning when it did not change. A pnpm, yarn or bun install (a .pnpm layout, or that manager's lockfile beside node_modules) is named and given that manager's command, since npm run in its folder would only add a second copy. Validation: on Windows, the real CLI was run with a private USERPROFILE, HOME, APPDATA and LOCALAPPDATA (npm config get prefix = the private AppData\Roaming\npm) against installs laid out the way npm lays them out, with a fake npm first on PATH that logs its command and folder. main ran the wrong npm command in 6 of 9 cases (a global install under %APPDATA%\npm or ~\.npm-global run from home, and project installs run from a subfolder, from home, from the drive root or from another project), the fix ran the right one in 9 of 9; an npx cache run and the bundled runtime are detected the same by both. On main's code 14 of the 91 upgrade tests fail on assertions (12 new ones, and 2 existing ones that now also expect the project folder); all pass with the fix. Fixes #2477 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0abae11959 |
fix(installer): a symlinked instructions or config file is written through, not replaced (#2768)
Root cause: every installer write goes through one helper that writes
`<path>.tmp.<pid>` and renames it onto the path. A rename replaces a
symbolic link itself, not the file it points to. So a `~/.codex/AGENTS.md`
or `~/.claude.json` linked from a dotfiles repo became a detached regular
copy on install: the shared file never got CodeGraph's settings, and later
edits to it no longer reached the agent. This held for every target (Claude
Code, Codex, opencode, Cursor, Gemini, Antigravity, Kiro, Hermes and the
Copilot family) and for install, the refresh that `codegraph upgrade` runs,
and uninstall. Uninstall also deleted a link whose file it had emptied,
leaving CodeGraph's entry behind in the shared file.
Fix:
- The write helper resolves a link to the file at the end of its chain and
writes and renames there, so the link stays exactly as it was, relative
or absolute.
- A link to a file that doesn't exist yet gets that file created, but only
in a folder that already exists, as writing through it in a shell would.
No folder is ever created where a link points.
- A dangling chain is followed hop by hop from the real folder holding each
link, so a relative link under a linked folder lands where the OS would
put it.
- When the linked file can't be written (a read-only file, a folder that
doesn't exist), the error names the link and its target and nothing
changes.
- Where uninstall used to delete a user's file it had emptied (an
instructions file, Codex's config.toml, Copilot CLI's mcp-config.json,
the legacy project .claude.json), a link is kept and the emptied content
is written through it.
- The refresh sweep catches a failure per agent, reports it, still
refreshes the others, and exits non-zero, so the upgrade warns.
Decided: links to CodeGraph's own legacy files (Cursor's codegraph.mdc,
Kiro's steering doc), which install only ever deletes, are still removed.
Validation:
- 28 new tests. 25 are in installer-targets.test.ts:
- every target and location: install and uninstall keep each of its
files that is a link (18 cases);
- the shared files' content through install and uninstall for Claude
Code, Codex, opencode (two agents sharing one AGENTS.md) and Cursor;
- relative links under a linked folder;
- a link into a missing folder;
- a link to a read-only file;
- uninstall emptying through links;
- a failing link in a refresh;
- a folder link guard.
The other 3:
- 1 in upgrade.test.ts, where the refresh runs the built CLI;
- 2 in a new installer-links-simulated.test.ts, which simulates the
link with spied lstat/realpath/readlink, so it runs on machines that
can't create file symlinks.
With main's sources put back, 27 fail; the folder-link guard passes on
both. All pass with the fix. The real-link tests are skipped, with the
reason in their names, where file symlinks can't be created (Windows
without Developer Mode or admin).
- This Windows machine has Developer Mode on, so the real-link tests ran
for real.
- The real CLI against a private home (`install --yes`, `install
--refresh`, `uninstall --yes --keep-cli`), 10 linked files for five
agents plus relative, dangling and read-only links:
- on main, all 29 link checks found the link replaced by a copy;
- with the fix, none did, every link's text was unchanged, the shared
files got CodeGraph's settings and lost them again on uninstall, and
the missing-folder and read-only cases exited 1 with the new message
and changed nothing.
Fixes #2721
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
d6e8c91e0a |
fix(installer): upgrade keeps everything around CodeGraph's section in instructions files (#2765)
Root cause: the write that refreshes CodeGraph's marker-fenced section in an agent's instructions file (CLAUDE.md, AGENTS.md, GEMINI.md) located the section with two independent searches: the first start marker anywhere in the file and the first end marker anywhere in the file. Everything between them was treated as CodeGraph's and replaced. A stray start marker above the real section (what is left when part of an older section is deleted by hand, or the marker quoted in the user's own notes) therefore stretched the "section" over the user's text, and when that marker was the first line the file came back as just the block, which is the report. The `codegraph upgrade` refresh (`codegraph install --refresh`) and plain `codegraph install` both go through this write, for the Claude Code, Codex, Gemini and opencode targets. The same pairing made a lone end marker look like "no section", so every run appended another block, and left a second block stale. Uninstall (and the npm preuninstall hook) and the Cursor rules-file cleanup used the same pairing to delete the same span. Fix: one parser finds the well-formed sections. Each end marker closes the nearest start marker before it, and a marker counts only when it is alone on its line, as every block codegraph has written puts it. A stray start or end marker is left as plain text. The refresh rewrites only the bytes between the first section's markers, using the line breaks that section already has, so a CRLF file stays CRLF and a current CRLF block is unchanged. Further sections are duplicates and are removed, keeping the text around them. With no section yet the block is appended after the existing bytes, which are no longer trimmed. Uninstall and the Cursor cleanup strip only well-formed sections. Validation: - 18 new tests (17 in installer-targets.test.ts: exact bytes for a stray start marker on line 1, a stray start marker with no section after it, a marker quoted in prose, a lone end marker, two sections, CRLF, no final newline, appending, a BOM, uninstall; a refresh plus uninstall per target for Claude Code, Codex, Gemini and opencode; the Cursor rules file. 1 in upgrade.test.ts: an npm upgrade whose refresh runs the built CLI against a private home). 16 fail on main's sources (the other 2 are guards that hold on both), all pass with the fix. - The real CLI on this Windows machine against private temp homes: `codegraph install --refresh`, 14 file shapes x 4 targets x 2 runs. Main had 28 bad results of 112 (the user's text lost in 3 shapes, a block added on every run after a lone end marker, a stale second block kept), the fix 0. With the fix, the bytes outside the section are identical in every single-section shape, and the input stays a byte prefix in every append. - `codegraph install --yes` and `codegraph uninstall --yes --keep-cli` on the reported shape: main kept none of the notes (install left only the 802-byte block, uninstall left 19 bytes); the fix kept them all. Fixes #2506 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
273e5cdc4c |
fix(upgrade): a Windows upgrade no longer breaks the install while CodeGraph is running (#2185) (#2294)
* fix(upgrade): a Windows upgrade no longer breaks the install while CodeGraph is running (#2185) On Windows, `codegraph upgrade` renamed only node.exe aside and then Copy-Item'd the new bundle over current\. Any open agent session runs a CodeGraph MCP server from current\, which keeps the native kernel loaded, so the copy failed on lib\kernel\codegraph-kernel.node halfway through, leaving no node.exe and a mix of versions that no codegraph command could repair. Re-running install.ps1 failed the same way, because it Remove-Items current\. Both now share one PowerShell function (a test pins the two copies equal). The bundle is unpacked next to current\ (same volume), then swapped in file by file: every file being replaced or dropped is first renamed aside (Windows allows renaming a running exe or a loaded DLL, just not overwriting or deleting it), then the staged file is moved in. Any failure or interruption undoes every step. Renamed-aside files, including the node.exe.old-* left by earlier upgrades, are deleted on the next successful run once nothing holds them. The upgrade's exit code now tells whether the install was left unchanged or needs a reinstall, and the message says which. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changelog): Windows upgrade with CodeGraph running (#2185) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7bbc1fb7f6 |
fix(tests): the test suite no longer writes to the developer's real home dir (#2275) (#2295)
Running the suite on a machine with Claude Code configured could wire the CodeGraph prompt hook into the developer's own ~/.claude/settings.json: every upgrade test whose fake upgrade succeeded ran the real post-upgrade prompt-hook self-heal, which detected the real global Claude profile and wrote it. Daemon suites likewise left records in the real ~/.codegraph/daemons. On Windows a HOME-only redirect would not have helped, since os.homedir() reads USERPROFILE there. - The prompt-hook writer is now injected through UpgradeDeps (wirePromptHook); the CLI passes the real defaultWirePromptHook and the upgrade tests a recorder. New tests pin that a successful upgrade calls the recorder and that the real writer never touches a configured profile. - A vitest setupFiles entry gives every engine test file a throwaway home: HOME/USERPROFILE (plus HOMEDRIVE/HOMEPATH/APPDATA/LOCALAPPDATA on Windows), XDG_CONFIG_HOME, and GIT_CONFIG_GLOBAL (seeded with a dummy identity) point into it, and CLAUDE_CONFIG_DIR/CODEX_HOME/COPILOT_HOME/ HERMES_HOME are cleared. Spawned CLI/MCP children inherit it. A sandbox test asserts os.homedir(), the Claude profile, the daemon registry, a child process and git's global config all resolve inside it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a66683d3eb |
feat(installer): offer CodeGraph Pro beta signup after install and upgrade (#1297)
One-time, strictly opt-in prompt at the end of codegraph install and codegraph upgrade to join the CodeGraph Pro beta waitlist (same list as the getcodegraph.com homepage form). Nothing is sent unless the user answers yes AND enters an email; either answer is recorded machine-wide so no later install or upgrade re-asks, and --yes / non-interactive / CI runs never see the prompt. Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
40aa092f5b |
fix(uninstall): remove the CLI binaries too, not just agent configs (#1254)
* fix(uninstall): remove the CLI binaries too, not just agent configs (#1071) `codegraph uninstall` swept agent configurations and stopped — every installed binary stayed behind, so `codegraph` still ran afterward. Three disconnected paths each removed a fraction of an installation (uninstall: configs; install.sh --uninstall: the bundle; npm preuninstall: configs + npm's own package), and none cleared a shadowed second install — the uninstall edition of the #1071 PATH shadow. The uninstall now PLANS every install present on the machine — the bundle layout(s) (running binary's own, the platform default, a custom CODEGRAPH_INSTALL_DIR), the npm global package (found by asking `npm root -g`, so nvm/fnm/volta prefixes resolve correctly), and the bin-dir launcher link (only when it verifiably points into a detected install) — confirms with the user, then removes them all. `--yes` skips the prompt; the new `--keep-cli` flag keeps the old configs-only behavior. Safety rules: a source checkout is reported, never deleted; a project-local npm install is left to the project; on unix the default install dir doubles as the machine state dir, so only the install artifacts (versions/, current) are removed there — telemetry choice and daemon records survive. Windows can't delete a running exe but can rename it (the in-place upgrade's trick): a locked node.exe is renamed aside and surfaced as a one-file leftover instead of failing the removal, and npm is routed through cmd.exe (a direct .cmd spawn EINVALs on modern Node). Planner/executor are split with injected side effects (the upgrade orchestrator's convention) and unit-tested across the shadow case, state-dir preservation, custom dirs, foreign-shim protection, and the locked-exe dance; validated end-to-end on macOS against a fake HOME. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(uninstall): key path math on the target platform, not the host Real-Windows validation caught it: the planner/executor used the host path module, so win32 fixtures were meaningless on a POSIX host and POSIX fixtures failed on the Windows VM. Same convention as detectInstallMethod now — path.win32/path.posix chosen by the injected platform. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(upgrade): route npm through cmd.exe on Windows — a direct npm.cmd spawn EINVALs on modern Node Found while validating the uninstall change on the Windows VM: upgradeNpm spawned npm.cmd without a shell, which every current Node rejects with EINVAL (the CVE-2024-27980 hardening) — so `codegraph upgrade` on a Windows npm install failed before doing anything. Verified live on the VM: spawnSync('npm.cmd') → EINVAL; cmd.exe /d /s /c npm → works. npmInvocation moves into the upgrade orchestrator (remove-binary imports it from there — same direction as its existing imports, no cycle), and the win32 test now pins the WORKING invocation instead of the broken one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
386bff0f84 |
fix(upgrade): refresh installer-written agent surfaces after a binary upgrade (#1238) (#1239)
* fix(upgrade): refresh installer-written agent surfaces after a binary upgrade codegraph upgrade swapped the binary but never revisited what earlier installs wrote into CLAUDE.md / AGENTS.md / GEMINI.md and the agent configs, so sections written by a pre-1.0 installer kept teaching agents a multi-tool surface (including tools that no longer exist) months of releases later. The install path already self-heals everything it owns, but nothing ever called it on upgrade. - codegraph install --refresh: non-interactive sweep that re-runs install() for already-configured targets only — never a first install; permissions and prompt-hook choices are preserved. - codegraph upgrade spawns it via the freshly-installed binary after a successful swap (the still-running old process would only rewrite its own stale template). Gated on PATH resolution and the CODEGRAPH_NO_INSTALL_REFRESH=1 kill-switch; never fatal to the upgrade. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(installer): clarify refresh change reporting --------- Co-authored-by: xuing <np2v9bvbbs@privaterelay.appleid.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Colby McHenry <me@colbymchenry.com> |
||
|
|
63eb488ed4 |
fix(upgrade): stop npm installs self-shadowing on upgrade; verify the resolved version after every upgrade (#1238, #1071) (#1245)
Two fixes to make `codegraph upgrade` trustworthy in the terminal it ran in: 1. detectInstallMethod checked the bundle layout before the node_modules path check, but the npm thin-installer's per-platform package IS a complete bundle inside node_modules — so every npm install misdetected as a standalone bundle, and upgrade curled install.sh into ~/.codegraph: a second install that never wins the PATH race against npm's shim, leaving `codegraph -v` permanently on the old version. Path-based checks (_npx, node_modules) now win over layout sniffing, so npm installs upgrade through npm again, in place. 2. After a successful swap, runUpgrade now probes the PATH-resolved `codegraph --version` and reports the real outcome: a green confirmation that this terminal already serves the new version, a loud shadow warning naming the fix (`which -a codegraph`) on mismatch, or the old soft new-terminal hint only when the probe is inconclusive. Replaces the unconditional "open a new terminal if the version looks unchanged" hedge. Skipped for npm-local installs, whose binary PATH never serves. Companion to #1239: the misdetection also broke its post-upgrade `install --refresh` for npm users (the spawn resolved the stale shim). Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4e5cf2de56 |
feat(cli): add codegraph upgrade self-update + stale-index re-index hint (#710)
`codegraph upgrade [version]` detects how the CLI was installed — the standalone install.sh/install.ps1 bundle, npm-global, npx, or a source checkout — and updates in place: re-running the canonical install.sh on macOS/Linux, an in-place rename-and-extract swap on Windows (a running node.exe can't be deleted, only renamed, so the detached-helper approach is avoided), and npm/npx/source-specific guidance otherwise. Flags: `--check` (report only), `--force`, and a positional version to pin. Each full index is now stamped with the engine's EXTRACTION_VERSION in project_metadata; `codegraph status` (and `--json`) flags an index built by an older engine and recommends re-indexing, and `upgrade` prints the same reminder. Gated on EXTRACTION_VERSION so it never nags on extraction-neutral releases. Validated end-to-end on macOS (real bundle upgrade), Linux (Docker, real curl|sh) and Windows (Parallels VM, real in-place swap). 32 new unit tests. Closes #679 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |