Commit Graph
113 Commits
Author SHA1 Message Date
danusha2345andClaude Opus 5.5 b1e6c9767d test: move the test workspace to Vitest 4 and align the Vite toolchain
The repo ran two Vite stacks. ui/ builds the viewer with Vite 7 and
vite-plugin-svelte 6, while Vitest 2 at the root kept Vite 5.4 and plugin 4 with
their own esbuild, whose dev tree carried the critical audit findings. The move
leaves one stack.

Tests now run as test.projects in vitest.config.mts, so vitest.workspace.mts goes
away: engine extends the base (env, global setup, home sandbox), ui stands alone
with the Svelte plugin, jsdom and the browser conditions. The WASM flags move to
test.execArgv, because Vitest 4 ignores poolOptions.forks.execArgv with a
deprecation line and the #1779 worker death comes back. git-index-currency injects
its failures through the mocks' own vi.fn: under Vitest 4 a spy on a mocked module
is that vi.fn, so the captured real function recursed into itself, and
restoreAllMocks no longer resets one, so the injection leaked into later tests.
devEngines sets Node 22.12 as the floor for working in the repo, which is what
Vite 7 asks for; engines, what users run, is unchanged.

Changes on top of the contributor's commits:
- The lockfile is regenerated from main's, not taken from the PR: the PR's would
  have put devalue, postcss and ignore back below the fixes in issues 3044 and
  3050, and restored the @types/better-sqlite3 that 3044 dropped. ui's packages
  hoist to the root at the versions it already built with, and rollup stays.
- testTimeout and hookTimeout rise to 30 s and 60 s. Since Vitest 3 a synchronous
  test or hook that outlasts its limit fails; under Vitest 2 the timer could not
  fire until the body returned, so a body blocked in spawnSync never timed out. A
  6 s synchronous test passes on 2.1.9 and fails on 4.1.11, and an 11 s hook does
  the same and skips its tests. The first full run lost frontload-hook to this,
  the contributor's lost two bundle-launcher listings, and 31 tests passed 4 s on
  a quiet machine, so on a loaded one they would all flake.
- A new test reads the WASM flags from the worker's own command line, since the
  config can stop reaching workers with no failure, and a Vitest 5 move could
  repeat that.
- CONTRIBUTING and AGENTS state the new floor and the projects setup; two test
  files name TestProject, which replaced the removed GlobalSetupContext type.
- Left out as out of scope: a trailing blank line in ui/src/lib/trail-codec.ts.

Validated on Windows, Node 22.22, npm 10.9:
- what ships is unchanged: npm ci --omit=dev, the bundle's step, gives 193 files
  byte-identical to main's; npm run build:lib gives 171 byte-identical files;
  dist/viewer matches main's once Svelte's scope hashes, which come from the
  checkout path, are masked (main built in two folders differs the same way).
- every test is kept: at cd04b21a vitest list finds 9,719 tests on main (9,701
  engine, 18 ui) and those plus the new guard here, each in the same project, none
  twice.
- npm's own checks across Node versions: from 22.12 up, devEngines passes and no
  package warns EBADENGINE, the same as main; below it npm ci and npm run stop with
  EBADDEVENGINES. Node 20 could not run from source already, and Vite 7 rejects
  22.5 to 22.11. npm ci logs the one deprecation main logs. release.yml's lock sync
  changes only the version fields.
- dev tree audit: main 10 findings with 2 critical, here 7 with none critical;
  production stays at 0.
- red to green: main's git-index-currency fails 7 of 13 under Vitest 4; putting
  the flags back under poolOptions turns the guard red.

Original PR #1667 by @danusha2345.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 17:31:15 -05:00
Colby MchenryandClaude Opus 5.5 19b74d10f3 fix(deps): read .gitignore rules the way git does, with ignore 7.0.14 (#3050)
codegraph applies .gitignore rules itself, through the ignore package:
on the filesystem walk for every .gitignore, and in git repositories on
top of git ls-files for its built-in defaults merged with the root
.gitignore and git's exclude files. codegraph.json's include, exclude
and includeIgnored patterns go through it too. ignore 7.0.5 read several
forms differently from git: a backslash escape (\d was a regex digit),
POSIX classes and a ] or ! first in a bracket, and a run of three
asterisks. A lone ! line matched every path, so it re-included
everything the rules and the built-in defaults leave out, node_modules
included. 2,031 of 200,000 random patterns also threw at match time,
which readGitignorePatterns has to guard against (issue 682).

ignore 7.0.14, with the range raised to ^7.0.14, reads all of these as
git does, and none of the 200,000 patterns throws. Its code diff from
7.0.5 was read in full: pattern translation only, with no I/O, no
dependencies and no install scripts. The lockfile entry matches the npm
registry's own metadata on registry.npmjs.org. The package has no
provenance, like every release its maintainer has published.

Validation:
- New __tests__/gitignore-pattern-parity.test.ts checks scanDirectory
  against git's own answer for these patterns, on the filesystem walk
  and in a git repository: its 4 tests fail with 7.0.5 and pass with
  7.0.14.
- scanDirectory on react, astro and django, in git mode and in walk
  mode on a copy without .git, returns the same 4,631, 4,946 and 3,027
  files with either version.
- On a fixture of the changed forms, 7.0.14 leaves out exactly what git
  leaves out in both modes, node_modules aside, which codegraph's
  defaults always exclude. With a lone ! line, 7.0.5 kept 16 of the 18
  files on the walk, node_modules among them, where git keeps 6. Without
  that line it differed from git on 8 files on the walk and on 2 in git
  mode.
- The gitignore and scope test files (extraction,
  git-ignored-dirs-scope, the include, exclude and includeIgnored
  configs, src-build-folders and others): 853 passed.

Raised by PR 2885 (@johnhldiver-beep).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 07:49:46 +00:00
Colby MchenryandClaude Opus 5.5 4e7a221089 chore(deps): take the security fixes for devalue and postcss, drop an unused types package (#3044)
devalue 5.9.1 (root, through svelte) and 5.8.1 (site/, through astro)
fall in seven advisories published 2026-10-01 and fixed in 5.9.3, among
them GHSA-j22f-vq7h-c4qm (CVE-2026-92708, high). postcss 8.5.6 (root,
through vite) and 8.5.15 (site/) fall in GHSA-r28c-9q8g-f849
(CVE-2026-73646, high, fixed in 8.5.18) and GHSA-fxqj-rqcc-2cmp (fixed
in 8.5.23); the root copy also in GHSA-6g55-p6wh-862q and
GHSA-qx2v-qp2m-jg93. All of these are build-time dependencies.

Lockfile-only updates inside the existing ranges: npm update devalue and
npm update postcss, in the root and in site/. devalue goes to 5.9.4 and
postcss to 8.5.32, whose own ranges move nanoid to 3.3.20 and
source-map-js to 1.2.2, which clears their advisories as well
(GHSA-28wg-ghj8-5hjv, GHSA-2v37-7h3g-55p8, GHSA-68fv-2mgg-jv7q). The
@types/better-sqlite3 devDependency goes: nothing has imported
better-sqlite3 since the switch to node:sqlite. In site/, npm 10 also
drops five "peer": true markers that the npm which wrote that lockfile
had added; they are metadata only, and npm ci installs the same tree.

Validation:
- npm audit: root 14 advisories before, 10 after; site/ 13 before, 9
  after. devalue, postcss, nanoid and source-map-js are gone from both.
- npm run build on main's lockfile and on this one: all 1,264 files of
  dist/, the viewer included, are byte-identical. The site builds its
  21 pages, and its 101-file dist/ is byte-identical too.
- The release bundle's install (npm ci --omit=dev --ignore-scripts on
  the staged lockfile) installs the same 12 packages, file for file.
- All 8 changed resolved/integrity entries match the npm registry's own
  metadata and sit on registry.npmjs.org. No git, URL or tarball
  sources, and no new install scripts. devalue, postcss and nanoid carry
  provenance from their own repositories' release workflows.

Raised by PR 2885 (@johnhldiver-beep) and PR 1477 (@anupamme).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>


[skip actions]
2026-10-30 07:13:13 +00:00
Aaron QueenandClaude Opus 5.5 69af19ace2 fix(build): building from source with bun finishes instead of starting itself over
build:ui and build:lib ran npm run build --workspace ui. Under bun, a
package script's npm run becomes bun run, and bun ignores --workspace,
so build:ui ran the ROOT build again, which ran build:ui again. bun run
build:ui on main nests without end: with bun 1.3.8 here, 13 bun
processes deep after 62 s, when a watchdog killed the tree. npm is
unaffected, which is why it went unnoticed.

The scripts now name the workspace by directory: cd ui && npm run build
(and cd ui && npm run build:lib), which runs the same ui script under
either tool.

Validation: with the fix, bun run build, build:ui and build:lib finish
by themselves in 16 s, 6 s and 6 s, and check-ui-build and
check-ui-package pass. npm run build plus npm run build:lib give the
same output before and after, under npm's default script shell
(cmd.exe here) and under bash (npm --script-shell bash): dist/ (1,260
files) and ui/dist (171) are identical by SHA-256 in all four runs,
built in one checkout from clean outputs, and bun's build gives that
same tree. check-ui-build and check-ui-package pass in every run.
scripts/pack-npm.sh still runs npm run build:lib --workspace ui; that
runs only under npm, in the release workflow, so it is left as is.

Original PR #1764 by @bompus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 02:16:17 +00:00
Colby MchenryandClaude Opus 5.5 0f0af7bf22 release: 1.6.2 (#2318)
Bumps package.json and ui/package.json (the component library is versioned
with the engine; ui-package.test.ts pins it) to 1.6.2, and the matching
version fields in package-lock.json — the top level, packages[""] and the ui
workspace, whose entry was still at 1.6.0. Only those three fields change;
`npm ci` accepts the lock.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 06:35:17 +00:00
Colby MchenryandClaude Opus 5.5 4a8eb6314e release: 1.6.1 (#2090)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 05:01:56 +00:00
Colby McHenry c15413f200 feat(ui): the viewer's screens as @colbymchenry/codegraph-ui, behind one adapter (CG-61)
`ui/src` now builds two ways from one tree: the static app `codegraph ui`
serves, and — via `svelte-package` — a Svelte library the Pro app imports.
A forked component would be a second answer to the same question about the
same graph, so there is no fork.

Everything a screen knows arrives through a `GraphAdapter`: eleven methods
answering the wire shapes verbatim, with `createHttpAdapter()` (the loopback
JSON API) as the default and a host's in-process engine reads as the point.
`lib/api.ts` became a one-line-per-call facade over it, which is why no call
site in the views changed. The payload types moved to `lib/wire.ts` — no
imports, no runtime — so a host can depend on the vocabulary alone.

Two more seams and one guard:

- `lib/navigation.ts` holds the href builders behind a `NavigationDriver`, so
  a host addresses its own URL space. The app's half — the hash parser and the
  live route, which attach window listeners at module scope — stays in
  `router.svelte.ts` and is pruned out of the package: rendering a Symbol view
  must not install a hash router in somebody else's application.
- `lib/theme.css` carries the design tokens and maps Svelte Flow's `--xy-*`
  variables onto them, so a host never sees library defaults. Dark now also
  answers to a bare `[data-theme]`, which is how `<CodegraphUi theme>` themes
  a container rather than the document.
- `scripts/check-ui-package.mjs` prunes the app's shell, resolves the
  extensionless specifiers svelte-package leaves behind, and asserts that
  nothing but `lib/adapter.js` reaches the network.

The search box, its keyboard and its panel are one component now
(`SearchPalette`), because splitting them is what breaks a palette.

`__tests__/ui-package.test.ts` mounts the three screens from the package entry
against a mock adapter in jsdom; it runs as a second vitest project so the
`browser` resolve condition it needs cannot reach the engine's suites.

Versioned with the engine. Prepared, not published: `private: true` is the
guard and `pack-npm.sh` only packs a tarball under CODEGRAPH_PACK_UI=1.
2026-08-27 06:52:57 -05:00
Colby McHenry ad91c8fdd8 feat(ui): classify code from the engine's own tree-sitter parse, retiring Shiki (CG-57)
The viewer ran a second highlighter over source the engine had already parsed
with a real grammar: Shiki, plus 56 pruned TextMate grammars shipped in
dist/textmate/. The classification now comes off that tree instead, so a file is
read by exactly the grammar that decided what its symbols are.

The swap is complete rather than flagged: @shikijs/core, @shikijs/engine-javascript
and @shikijs/langs are off the dependency list, scripts/prune-grammars.mjs and
`npm run build:textmate` are deleted, and check-ui-build.mjs asserts the
tree-sitter grammars in dist/extraction/wasm instead of dist/textmate.

The wire contract is unchanged — `[classId, text]` pairs with the class names
alongside — so the viewer's decoder and code blocks did not have to be rewritten.
Two classes are added to the six: `type` (a named type reference, painted at
plain ink) and `def` (the name a definition declares, weight 600), the latter
taken from the extractors' own definition tables so it cannot drift from what
indexing calls a definition.

Three differences are not cosmetic:

* Interpolations (`${…}`, `#{…}`, `$"{…}"`, f-strings) are classified as code,
  not as string. The call-site overlay refuses to claim a token classed string,
  so calls written inside interpolated strings now link.
* Built-in type words are emitted whole and classed `type` in every language.
  The grammars disagree about whether `string` is a type_identifier or an
  anonymous token inside a predefined_type, and TextMate scoped them
  inconsistently too.
* 3 000 lines of TypeScript cost 24-41 ms instead of ~700 ms.

Given up deliberately: Liquid, Razor, YAML, Twig, XML and .properties render
plain. .svelte/.vue/.astro are classified through their <script> blocks, the same
delegation the SFC extractors do. Pulling html/css/vue out of tree-sitter-wasms
would cover them, but those ABI-13 builds are the known cause of shared-WASM-heap
corruption for every other language in the same process.

Measured parity, per-language before/after screenshots and the reproduction
recipe: docs/design/cg57-highlighting-parity.md.
2026-08-27 06:22:11 -05:00
Colby McHenry 2ad836d935 feat(ui): highlight source server-side with a near-monochrome Shiki theme (CG-43)
The viewer's code block stops lexing with a hand-rolled dialect table and
reads real TextMate grammars instead, run once in `/api/source`.

Three things make that safe to depend on:

* Highlighting never fails a request. A missing grammar, an oversized
  slice, an ESM import that did not resolve — every one of them answers
  `engine: 'plain'` with a reason and the source still goes out.
* Identifiers survive whatever token boundaries a grammar chose. Every
  code token is split into identifier runs before it goes on the wire, so
  the graph's call-site overlay claims a token the highlighter produced
  rather than re-cutting the line. `assignRefs` now matches on a token's
  text rather than on the class a grammar gave it, so a language that
  scopes type names as `storage.type` still links.
* The theme classifies rather than colours: its foregrounds are sentinels
  the server maps back to class names, and the viewer paints them from
  CSS custom properties — one token stream serves light and dark with no
  refetch, and the ramp lives only in app.css.

Comments move from --ink-3 to a new --code-comment. --ink-3 measures
3.46:1 on paper and 3.00:1 on the hot-line tint, both under AA for 12.5px
text; --code-comment is the smallest step along the same ramp that clears
4.5:1 on every background a code line can have, and stays quieter than
the strings and numbers above it.

Shipping: @shikijs/core and @shikijs/engine-javascript are runtime
dependencies (no wasm, no native module); @shikijs/langs stays a
devDependency and `npm run build:textmate` writes only the closure the
engine's 40-odd languages reach — 56 grammars, 2.6 MB, against 11 MB for
all 722. check-ui-build.mjs asserts the tree after every build and inside
every release archive.
2026-08-27 01:23:10 -05:00
Colby McHenry a72f22a6d3 feat(ui): scaffold the codegraph ui viewer as a Svelte 5 + Vite workspace (CG-40)
Adds `ui/` as an npm workspace (Svelte 5.56 + Vite 7, devDependencies only —
the engine's runtime dependencies are untouched) and chains its build into
`npm run build`, so the browser viewer ships inside `dist/` with everything
else: `build-bundle.sh` already copies `dist` wholesale and `pack-npm.sh`
packs that bundle.

Output is `dist/viewer/`, NOT `dist/ui/`: `src/ui/` is the engine's terminal
ui (shimmer progress + its worker) and tsc compiles it to `dist/ui/`, so
emitting there both deletes those modules — the CLI then dies at startup with
`Cannot find module '../ui/shimmer-progress'` — and would leave the static
server handing out compiled engine internals. The design spec is corrected to
match.

`scripts/check-ui-build.mjs` is the release guard: index.html must exist, be
non-trivial, and every local asset it references must be on disk, and the
compiled engine next door must still be intact. It runs after every UI build,
again in `build-bundle.sh` once the bundle stage has copied `dist`, and again
in `pack-npm.sh` once each archive is unpacked — so a broken viewer fails the
release instead of shipping a CLI that serves a 404.

`vite build` does not override an ambient NODE_ENV, so a shell or runner with
NODE_ENV=development silently shipped dev-mode Svelte (~13 kB of dev-only
runtime checks, warning in the user's console). The config now pins production
for `command === 'build'`; macOS and Windows ARM64 then emit byte-identical
bundle hashes.

The shell itself follows docs/design/codegraph-ui-design-spec.md §2–§3.1:
design tokens as CSS custom properties (light on bare `:root`, dark under both
`prefers-color-scheme` and `[data-theme="dark"]`), square corners, hairline
rules, one oxblood accent; top bar 48px / trail bar 34px / main; a hash router
over `#/s/<id>`, `#/file/<path>`, with `#/map` and `#/flow` reserved for phase
2. Fonts are vendored through @fontsource rather than fetched, so a local
reader works offline and never announces the project to a CDN.

Verified: clean `npm run build` from an empty dist on macOS and on the Windows
ARM64 VM (forward-slash asset URLs, CLI still starts, both assertion failure
modes exit 1); `dist/viewer` present in a real darwin-arm64 bundle and in the
packed npm platform package; shell geometry, tokens, all seven routes, both
themes and font loading checked in headless Chromium with no console errors;
`npm test` unaffected.
2026-08-26 15:55:10 -05:00
Colby McHenry b59023f01b chore(release): bump version to 1.6.0 2026-08-26 11:59:36 -05:00
Colby MchenryandClaude Fable 5 7d4a3d0f2d docs(release): README polish + v1.5.0 (#1400)
- Hero: larger theme-aware standalone Rust logo (new assets/rust-logo{,-dark}.svg
  — gear only, no tile card; <picture> swaps by GitHub theme), tagline text
  trimmed to 'Kernel powered by Rust'
- 'Built for speed' section: removed the floated language-tile logo (its baked-in
  paper card rendered as an odd box on dark theme and pushed the text)
- Removed the '1.0 Released!' banner and the Star History section (+ its
  Contents entry)
- package.json → 1.5.0 for the Rust-engine release

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:57:55 -05:00
Colby McHenryandClaude Fable 5 c5eebe6beb feat(kernel): R1 scaffold — napi-rs extraction kernel, buffer contract, routing + fallback, grammar-parity CI
Phase 0 of the Rust extraction-kernel migration (docs/design/
rust-kernel-migration-plan.md, now checked in with §3a recording the
shipped state):

- codegraph-kernel/ napi-rs crate: extractFile(path, content, language)
  → five flat buffers (meta/nodes/edges/refs/arena), one JS boundary
  crossing per file. Node ids computed Rust-side, byte-identical to
  generateNodeId (pinned by test vector). Reserved per-node metrics slot
  for the Arc 3.2 code-metrics work.
- Generic .scm-driven emitter (@def.<kind>/@name/@ref.<kind> captures,
  byte-range scope stack → ::-joined qualified names, contains edges,
  refs attributed to the innermost enclosing symbol). Seed TS/JS queries
  are smoke-level; R2 replaces them with the full port.
- Routing seam in extractFromSource with per-file wasm fallback.
  DEFAULT_ROUTED is empty — no behavior change until a language passes
  its equivalence gate (R3). Dev opt-in: CODEGRAPH_KERNEL_LANGS. Kill
  switch: CODEGRAPH_KERNEL=0. Loader verifies ABI + kind tables before
  routing; EDGE_KINDS became a runtime array because kind order is now
  wire contract.
- Grammar-source parity: vendored TS/TSX/JS wasm grammars built from the
  exact crate revisions (tree-sitter-typescript v0.23.2,
  tree-sitter-javascript v0.25.0, checked-in parser.c, ts-cli 0.25.10) —
  the tree-sitter-wasms builds were 2023-era, which the new
  kernel-grammar-parity test caught on day one. Production TS/JS parsing
  gets 2.5 years of grammar fixes; full suite green (2456 tests).
- Build/release wiring: scripts/build-kernel.sh + npm run build:kernel;
  release.yml kernel prebuild matrix (continue-on-error — the kernel is
  optional everywhere, bundles fall back to the wasm path); bundles stage
  lib/kernel/codegraph-kernel.node; release job runs the kernel suites
  with CODEGRAPH_KERNEL_EXPECT=1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 20:13:51 -05:00
Colby MchenryandClaude Fable 5 2b0b4b587e ci(release): publish npm packages with provenance and attest release bundles (#1296)
Every published artifact is now cryptographically verifiable as built by
this repo's Release workflow: npm publishes carry npm provenance (OIDC,
shows the Provenance badge on npmjs.com), and the GitHub Release bundles
+ SHA256SUMS get signed build attestations via
actions/attest-build-provenance, verifiable with
`gh attestation verify <file> -R colbymchenry/codegraph`.

pack-npm.sh now writes a repository field into the generated shim and
per-platform package.jsons — npm --provenance refuses to publish without
one matching the repo — and the root package.json gains the same field.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 19:10:34 -05:00
Colby McHenryandClaude Fable 5 f8a47bdd79 chore: bump version to 1.4.1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 17:37:44 -05:00
Colby McHenryandClaude Fable 5 50e978ee81 release: 1.4.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 03:42:55 -05:00
Colby McHenryandClaude Fable 5 6a8463f502 chore(release): 1.3.1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 23:18:36 -05:00
Colby McHenryandClaude Opus 4.8 bbf0f90083 chore(release): 1.3.0
Ships Nix language support and a batch of fixes staged under [Unreleased],
including the Java/Kotlin (Spring) resolution performance fix (#1180).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 14:25:38 -05:00
Colby McHenryandClaude Opus 4.8 6c50e968dc chore: bump version to 1.2.0
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 22:07:58 -05:00
Colby MchenryandClaude Opus 4.8 fedb5641b4 chore: bump version to 1.1.6 (#1076)
Patch release: installer prunes old version bundles (#1074) and
`codegraph index` rebuilds an oversized index without wedging (#1067).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 23:41:38 -05:00
Colby McHenryandClaude Opus 4.8 9e5f466714 chore: bump version to 1.1.5
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 21:06:32 -05:00
Colby McHenryandClaude Opus 4.8 1c67ac0878 chore: bump version to 1.1.4
Cut 1.1.4 for the #1065 fix (gitignored tracked-gitlink embedded repos).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:56:53 -05:00
Colby MchenryandClaude Opus 4.8 c0284aeffa chore: bump version to 1.1.3 (#1055)
Release the four CLI/indexing fixes triaged from @jcrabapple's reports
(#1044 node -f, #1045 query %, #1046 explore count, #1047 Android res XML)
plus the rest of [Unreleased]. The Release workflow promotes the
changelog and publishes.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 23:01:45 -05:00
Colby Mchenry fcc275ee0a Bump version from 1.1.1 to 1.1.2 2026-06-27 15:49:00 -05:00
Colby McHenryandClaude Opus 4.8 ec0c62522d chore(release): bump version to 1.1.1
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 14:52:21 -05:00
Colby McHenryandClaude Opus 4.8 ec42aa76b0 chore(release): bump version to 1.1.0
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:43:38 -05:00
Colby McHenry 2f3188eb49 docs: reframe value prop around precision/speed, update Node floor to 20, and expand language/framework coverage
- Benchmark table reordered to lead with tool calls, time, and file reads (the universal wins); cost and tokens moved right with a note that savings are scale-dependent, not a headline claim
- README/introduction/quickstart/installation messaging updated to "surgical context · fewer tool calls · faster answers" framing, dropping the "16% cheaper" headline
- Node engine floor raised from 18 to 20 in CLAUDE.md, package.json description updated
- `codegraph init` now creates and indexes in one step; the `-i` flag is retired (still accepted as a no-op)
- CLI reference expanded with new commands: `explore`, `node`, `unlock`, `daemon`, `telemetry`, `upgrade`, `version`, `help`
- MCP server docs clarified: single `codegraph_explore` tool exposed by default, others unlisted but re-enableable via `CODEGRAPH_MCP_TOOLS`
- Language support adds Objective-C, Astro, and R; framework routes adds Play, Vue Router/Nuxt, and Astro
- API reference documents lower-level exports and embedding requirements (Node 22.5+ for `node:sqlite`)
- Troubleshooting adds WSL/Windows dual-checkout guidance
- How-it-works updated: SQLite backend is now Node's built-in `node:sqlite` in WAL mode, not better-sqlite3/WASM
2026-06-22 09:45:57 -05:00
Colby MchenryandClaude Opus 4.8 b35a292c90 chore(release): bump version to 1.0.1 (#869)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 16:06:55 -05:00
Colby MchenryandClaude Opus 4.8 b9eff08c77 chore(release): 1.0.0 — README banner + X account (#840)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 13:21:46 -05:00
Colby MchenryandClaude Opus 4.8 c9559d9991 fix(watcher): bound fd/watch cost with a native fs.watch hybrid (#644, #496, #555, #628, #579) (#650)
chokidar v4 holds one OS file descriptor per watched file on macOS (libuv's
kqueue backend registers an fd per vnode; fsevents is installed but v4 no
longer uses it). On a large project the `serve --mcp` daemon accumulated tens
of thousands of open REG descriptors and exhausted kern.maxfiles — crashing
unrelated processes system-wide with ENFILE. #276 only trimmed the count by
ignoring directories; the source tree still cost one fd per file.

Replace chokidar with a pure-JS native fs.watch hybrid, keeping codegraph's
zero-native-addon "any OS builds any bundle" invariant:

  - macOS / Windows: a single recursive fs.watch (one FSEvents stream /
    ReadDirectoryChangesW handle) -> O(1) descriptors regardless of repo size.
  - Linux: one inotify watch per directory (O(dirs), dynamic add for new
    dirs, capped via CODEGRAPH_MAX_DIR_WATCHES) instead of per-file watches.

Validated empirically: macOS 0 extra fds at 6k and 12k files; Linux 31 inotify
watches at 6k files (per-file would be 6k); Windows recursive catches nested
and new-directory edits. Full test suite green.

Tests drive the watcher through an inertForTests seam (no OS watcher) for
determinism under parallel vitest, with one real-fs end-to-end test exercising
the genuine native path.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 14:21:29 -05:00
Colby McHenryandClaude Opus 4.8 0cc7ba902f chore(release): bump version to 0.9.9
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 10:31:47 -05:00
Colby MchenryandClaude Opus 4.8 081a6fcaca chore(release): bump version to 0.9.8 (#604)
Cuts the 0.9.8 release, which carries the restored embedded/programmatic
SDK API (#354) along with the rest of the [Unreleased] changelog. The
Release workflow promotes [Unreleased] -> [0.9.8] and appends the link
reference; only the version fields are bumped here.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 19:19:11 -05:00
Colby McHenryandClaude Opus 4.8 15dbcdbac0 chore(release): bump version to 0.9.7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 15:24:38 -05:00
Colby McHenryandClaude Opus 4.7 6e4949838a Bump version from 0.9.5 to 0.9.6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 18:33:06 -05:00
Colby Mchenry 318cda18d1 Bump version from 0.9.4 to 0.9.5 2026-05-26 02:57:41 -05:00
b09b23cf54 fix(watcher): exclude ignored dirs before watching to prevent inotify exhaustion (#276)
The file watcher registered a recursive watch over the entire project (node_modules, build output, caches included) and filtered only in the callback — exhausting the Linux inotify budget on large repos (#276). It now uses chokidar and excludes the same directories the indexer ignores (built-in default-ignore set + the project .gitignore) BEFORE registering a watch, so the watch count on a 900-dir node_modules drops from ~1200 to ~14 even with no .gitignore. Stacks with the shared daemon (#411): one watcher across agents, now small.

Also hardens the #411 daemon lockfile against a concurrent-startup race the new watcher timing made reproducible — the lock is now created atomically with its content (temp-write + hard-link), so racing daemons can never both win. Validated on macOS, Linux (Docker), and Windows (chokidar + fs.linkSync on NTFS).

Co-Authored-By: Colby McHenry <me@colbymchenry.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 20:12:44 -05:00
Colby MchenryandClaude Opus 4.7 15072aa29f fix: self-heal missing platform bundle from GitHub Releases (#303) (#335)
Installing from a registry mirror (npmmirror/cnpm) that hadn't mirrored the
per-platform optionalDependency left codegraph failing with "no prebuilt
bundle for <platform>" — npm treats an unfetchable optional dep as success and
silently skips it. The npm-shim now self-heals: when the bundle is missing it
downloads the matching archive from GitHub Releases (checksum-verified, with a
download timeout) and caches it, so a global install works on any registry.

release.yml now publishes SHA256SUMS and triggers an npmmirror sync after
publish. Adds hermetic tests for the shim (resolution, cache reuse, disable
knob, download + checksum match/mismatch/absent).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 11:38:28 -05:00
Colby MchenryandClaude Opus 4.7 c09dfd071e release: roll WASM Zone OOM fix into 0.9.3 (not 0.9.4) (#323)
0.9.3 was prepped in the repo but never released (latest published is
0.9.2), so the turboshaft WASM Zone OOM fix ships as part of 0.9.3.
Fold its changelog entry into [0.9.3] and revert the version bump.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 05:44:37 -05:00
Colby MchenryandClaude Opus 4.7 e5d633075c fix: prevent V8 turboshaft WASM Zone OOM during indexing (#298, #293) (#322)
Large multi-language indexes crashed with `Fatal process out of memory:
Zone` on Node 22/24 (including the bundled runtime) — V8's turboshaft
optimizing WASM compiler exhausts its per-compilation Zone arena while
compiling tree-sitter grammars on a background thread, even with tens of
GB free (the Zone is a V8-internal arena, not the JS heap).

Run node with V8 `--liftoff-only`, which keeps grammar compilation on the
Liftoff baseline and never reaches the optimizing tier. Delivered via the
bundled launcher + a one-shot CLI re-exec guard for all other launch
paths. Empirically only `--liftoff-only` stops it (`--no-wasm-tier-up` /
`--no-wasm-dynamic-tiering` do not), and it must be on node's command
line (setFlagsFromString / worker execArgv / NODE_OPTIONS all fail).

Reproduced the exact crash with the real indexer on Node 24.16 against a
2,880-file / 18-language repo and confirmed the fix eliminates it; full
suite + 7 new tests pass. Bumps to 0.9.4.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 05:39:24 -05:00
Colby MchenryandClaude Opus 4.7 bf73f4d05c feat(installer): add codegraph uninstall command (#313) (#318)
Adds a cross-channel uninstall that removes CodeGraph from every agent it's
configured on (Claude Code, Cursor, Codex CLI, opencode, Hermes). Prompts
global-vs-local up front (no flags required) and reports which providers it
actually hit; --location / --target / --yes supported for non-interactive use.
Removes only what install wrote; leaves the .codegraph/ index to `uninit`.

Also fixes Cursor uninstall leaving an orphaned .cursor/rules/codegraph.mdc
(its description: CodeGraph frontmatter lingered); the dedicated rules file is
now deleted outright while user content outside our markers is preserved.

Validated end-to-end on macOS and Docker Linux (global + local sweeps clean).
Adds 8 tests; full suite 730 passing. Bumps to 0.9.3 with CHANGELOG entry.

Resolves #313.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 04:51:42 -05:00
Colby MchenryandClaude Opus 4.7 c41559a9d0 fix(installer): Windows npm launcher EINVAL on modern Node (#289) (#292)
The npm thin-installer shim spawned the per-platform bundle's `.cmd`
launcher directly. Modern Node on Windows refuses to spawn `.cmd`/`.bat`
without `shell: true` (the CVE-2024-27980 hardening), so every `codegraph`
command failed with `spawnSync …\codegraph.cmd EINVAL` (seen on Node 24).

On Windows the shim now invokes the bundled `node.exe` against the app
entry point directly, bypassing the `.cmd` (and avoiding the arg-quoting
pitfalls of `shell: true`). Unix is unchanged.

Validated end-to-end against a real win32-x64 bundle: `npm install` of the
packed tarballs + `codegraph init -i`/`status` run on the bundled Node 24.

Also cuts release 0.9.2, rolling up the pending Drupal, zero-config,
config-removal, Hermes-installer, and symlink-security changes.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 21:22:50 -05:00
Colby MchenryandClaude Opus 4.7 f6772dac7c feat: zero-config indexing driven by .gitignore (#283) (#285)
Remove .codegraph/config.json and the entire config surface. CodeGraph now
indexes every file whose extension maps to a supported language and respects
.gitignore everywhere — git repos via git itself, non-git projects via the
`ignore` library (root + nested .gitignore files, the same way git does).

- Remove CodeGraphConfig/DEFAULT_CONFIG, src/config.ts, and the public config
  API (the `config` option on init, getConfig/updateConfig/getConfigPath).
- Derive the source-file allowlist from EXTENSION_MAP (isSourceFile); maxFileSize
  is now a constant. Drop the .codegraphignore marker.
- Behavior change: committed, non-gitignored dirs (vendor/, a committed dist/)
  are now indexed — .gitignore is the single source of truth.

Earlier inert fields (languages, frameworks, extractDocstrings, trackCallSites,
customPatterns) and their dead helpers are removed as part of this.

Resolves #283.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:06:02 -05:00
Colby McHenryandClaude Opus 4.7 b8d9aaef16 release: 0.9.1 (fix curl-install launcher; publish all platform packages)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:08:02 -05:00
Colby McHenryandClaude Opus 4.7 6bc745b196 release: 0.9.0 (self-contained bundled distribution; node:sqlite)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 15:54:36 -05:00
Colby MchenryandClaude Opus 4.7 ac52fd76c0 Self-contained distribution: bundle Node + node:sqlite, drop better-sqlite3/wasm (closes #238) (#282)
* fix(db): eliminate concurrent-read "database is locked"; add node:sqlite backend (#238)

WAL + busy_timeout were already enabled, so the issue's suggested fix was a
no-op. The real causes, addressed here:

- busy_timeout is now set first (before journal_mode) and lowered 120s -> 5s,
  so open-time pragmas wait out a lock instead of hanging for two minutes.
- getCodeGraph no longer opens a second connection to the default project when
  a tool passes its own projectPath (the in-process lock amplifier).
- The wasm fallback (no WAL) gets a bounded read-retry on SQLITE_BUSY.
- New: node:sqlite backend, preferred over wasm, so installs whose native
  better-sqlite3 build fails land on a real-WAL backend instead of no-WAL wasm.
- codegraph status / codegraph_status now report the effective journal mode, so
  a lock report is triageable (wal vs delete).
- CLI hard-blocks Node < 20 to actually enforce the engines floor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(db)!: node:sqlite is the sole backend; drop better-sqlite3 + wasm

Now that distribution will bundle a Node 24 runtime, node:sqlite (real SQLite
with WAL + FTS5) is always available. Collapse the three-backend adapter to
node:sqlite only and remove the machinery the other two needed:

- Remove better-sqlite3 (optionalDependency) and node-sqlite3-wasm (dependency).
- Remove WasmDatabaseAdapter, the named->positional param translation, the
  SQLITE_BUSY read-retry, the wasm fallback banner, the backend env override,
  and the native/node-sqlite/wasm selection chain.
- createDatabase now opens node:sqlite directly, with a clear error pointing at
  the bundled release / Node 22.5+ when the module is absent.
- NodeSqliteAdapter.close() is idempotent and pragma() supports { simple }, to
  match the better-sqlite3 behavior callers relied on.
- status (CLI + MCP) reports the single node:sqlite backend; journal-mode
  diagnostics and the getCodeGraph single-connection fix are retained.
- Tests repointed off better-sqlite3 onto node:sqlite.

Net -1044 lines. Running from source now requires Node 22.5+.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(dist): self-contained bundle prototype (vendored Node + install channels)

Phase 3 of the node:sqlite migration: ship a vendored Node runtime so CodeGraph
runs with no system Node and no native build (node:sqlite is built in).

- scripts/build-bundle.sh: build a per-platform archive (official Node + dist +
  prod deps + launcher). Same recipe per platform; pins Node v24.16.0.
- install.sh: curl|sh installer (no Node required) — detects os/arch, pulls the
  archive from Releases, symlinks onto PATH; re-run to upgrade, --uninstall to
  remove. The VPS/SSH path.
- scripts/npm-shim.js: thin launcher for the npm channel — resolves the
  per-platform optionalDependency bundle and execs it, so `npm i -g` keeps
  working and the real work runs on the bundled Node regardless of the user's.
- BUNDLING.md: distribution design + release-pipeline TODO (CI matrix, platform
  packages, code signing, brew, retiring the Node-version gate).

Validated end-to-end: darwin-arm64 and linux-x64 bundles both run init + index +
status (Backend: node:sqlite, Journal: wal) + FTS query with NO system Node —
linux-x64 verified in a clean ubuntu:24.04 amd64 container. Release archives are
gitignored; CI will produce and upload them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(dist): add Windows PowerShell installer (install.ps1)

The `irm … | iex` one-liner for Windows, mirroring install.sh: detect arch,
pull the matching bundle from Releases, extract to %LOCALAPPDATA%\codegraph,
add it to user PATH. Re-run to upgrade. (Windows bundle production in
build-bundle.sh is still TODO.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(dist): release workflow + npm packaging; README/CHANGELOG for bundled distro

- .github/workflows/release.yml: manually-triggered (workflow_dispatch) release
  matrix. Builds a self-contained bundle per platform on its own runner
  (darwin-arm64/x64, linux-x64/arm64), publishes a GitHub Release with all
  archives, and publishes the npm thin-installer (shim + per-platform packages).
  Windows targets are TODO (build-bundle.sh is unix-only).
- scripts/pack-npm.sh: assemble the npm packages from built bundles — per-platform
  packages tagged os/cpu + the main shim package with them as optionalDependencies
  (esbuild pattern). Proven locally: npm-install the tarballs, run via the shim,
  resolves the bundle and runs on the bundled Node 24 (node:sqlite / WAL).
- README: install section now leads with the no-Node one-liners (curl|sh, irm|iex)
  then npm/npx; "bundled · none required" badge.
- CHANGELOG: standout headline for the self-contained release, plus Added/Changed/
  Removed for the install channels, node:sqlite backend, and dropped deps.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(dist): Windows bundles + single-trigger release workflow

- build-bundle.sh: add win32-x64 / win32-arm64 targets — download Node's Windows
  zip, bundle node.exe + a .cmd launcher, output a .zip. Verified structurally
  (PE32+ node.exe, CRLF .cmd, portable node_modules). Since there are no native
  addons, any target builds on any OS, so the whole matrix builds on one runner.
- pack-npm.sh: handle .zip bundles and win32 packages (os: win32, node.exe).
- release.yml: simplified to your spec — manual trigger reads the version from
  package.json, builds all platform bundles, creates the GitHub Release with notes
  pulled from CHANGELOG.md, and publishes the npm shim + platform packages.
- BUNDLING.md: Windows + build-anywhere notes; release pipeline documented.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 15:48:04 -05:00
Colby McHenry c3f1e273d4 release: 0.8.0 2026-05-20 18:41:42 -05:00
Colby MchenryandClaude Opus 4.7 9b06b0edde fix(db): require better-sqlite3 ^12.4.1 so Node 24 gets the native backend (#203) (#216)
better-sqlite3 ^11.0.0 (latest 11.10.0) ships no prebuilt binary for
Node 24's ABI (node-v137) and predates Node 24, so every Node 24 install
silently fell back to the 5-10x-slower WASM backend. Bump to ^12.4.1 —
the first 12.x with the Node 24 prebuild — and raise the engines floor to
Node 20 (Node 18 is EOL and dropped from better-sqlite3 12.x prebuilds).

Verified on macOS Node 24.15.0 (ABI 137): prebuilt binary used with no
compiler (installs even with CC/CXX sabotaged), `codegraph init -i` shows
no WASM banner, and `codegraph status` reports Backend: native. 639/639
tests pass on Node 22.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:54:19 -05:00
Colby MchenryandClaude Opus 4.7 2c1a314b84 feat(mcp): line numbers in explore output + per-file cluster fixes (#188)
* feat(mcp): line numbers in explore output + per-file cluster fixes

Follow-up to #185. Three changes to codegraph_explore:

1. Source sections now carry cat -n style line-number prefixes
   (<num>\t<code>), so the agent can cite file:line straight from the
   payload instead of re-Reading the file just to recover a line number.
   Isolated A/B: the no-line-numbers arm spent 2 Reads + a grep to find a
   line number the line-numbered arm cited with zero follow-up calls.
   Payload cost ~3-5%. Toggle off with CODEGRAPH_EXPLORE_LINENUMS=0.

2. Per-file cluster selection now ranks clusters containing a query entry
   point ahead of dense declaration blocks. Density-only ranking buried
   the relevant methods (perform/didCreateURLRequest/task in Alamofire's
   Session.swift) under the top-of-file class header + property list.

3. Whole-file "envelope" nodes (a class/struct/etc. spanning >50% of the
   file) are excluded from clustering. The Session class spans ~1,400
   lines; keeping it collapsed every method into one giant cluster that
   tail-trimmed down to just the class header, hiding the methods.

Net vs the 0.7.10 baseline, line numbers on: Alamofire -60%, Excalidraw
-32%, VS Code -12% per explore call.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(mcp): language-neutral omission markers in explore output

The gap separator and the two tail-trim markers used C-style `//`
comments, which aren't comments in Python, Ruby, etc. Switch to plain
`... (gap) ...` / `... (trimmed) ...` so they read correctly inside any
language's fenced source block. With line numbers on, the line-number
jump already corroborates a gap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(mcp): language-neutral truncation marker in codegraph_context

Sibling to the explore marker fix: codegraph_context's code-block
truncation used a C-style `// ... truncated ...`. Switch to
`... (truncated) ...` so it reads correctly in any language's fenced
source block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(release): bump version to 0.7.11

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:16:12 -05:00
Colby McHenry fb8fb0ea8b release: 0.7.10 (Windows mojibake fix, module-qualified symbol lookups, MCP handshake) 2026-05-19 11:32:47 -05:00
Colby McHenry 662bb1ece8 release: 0.7.9 2026-05-18 08:29:16 -05:00