Skip to content

Add Svelte language support#23

Merged
colbymchenry merged 1 commit into
mainfrom
svelte-support
Feb 10, 2026
Merged

Add Svelte language support#23
colbymchenry merged 1 commit into
mainfrom
svelte-support

Conversation

@colbymchenry
Copy link
Copy Markdown
Owner

Summary

  • Add Svelte language support with SvelteExtractor that parses <script> blocks and delegates to the existing TS/JS TreeSitterExtractor
  • Add SvelteKit framework resolver handling Svelte 5 runes ($state, $derived, $effect, etc.), store auto-subscriptions, $lib/$app/$env module aliases, and SvelteKit route file detection
  • Update README to list Svelte and Dart in supported languages table

Test plan

  • npm run build compiles cleanly
  • Existing extraction tests pass (no regressions)
  • Manual test: index a Svelte project and verify component nodes, script block extraction, and rune call expressions

🤖 Generated with Claude Code

- Add 'svelte' to Language type, DEFAULT_CONFIG includes, grammars, and config validation
- Add SvelteExtractor that extracts <script> blocks and delegates to TS/JS TreeSitterExtractor
- Add Svelte framework resolver for runes ($state, $derived, $effect, etc.), store auto-subscriptions, SvelteKit module aliases ($app/*, $env/*, $lib/*), and SvelteKit route detection
- Update README to list Svelte and Dart in supported languages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@colbymchenry colbymchenry mentioned this pull request Feb 10, 2026
@colbymchenry colbymchenry merged commit 9f431c8 into main Feb 10, 2026
@colbymchenry colbymchenry deleted the svelte-support branch February 10, 2026 22:47
andreinknv added a commit to andreinknv/codegraph that referenced this pull request May 3, 2026
…henry#23)

Flip the SQLite backend default. Pre-PR, createDatabase tried
better-sqlite3 first and fell back to node:sqlite; the package
shipped better-sqlite3 in optionalDependencies so npm install
attempted to compile native bindings on every fresh install.
Post-PR, node:sqlite is the built-in default (Node 22.5+,
zero native compile, zero platform binaries); better-sqlite3
remains supported as a perf opt-in (~1.5× faster on indexing)
when the user installs it explicitly.

The Node 22 floor is already in place (engines.node = ">=22.5.0"),
so this isn't a forced version bump — just exercising what the
existing floor enabled.

Why this is a win
- Fresh installs no longer compile native bindings (the #1 cause
  of "npm install fails on Apple Silicon" issues per the dep audit).
- 22 MB net install savings versus the previous default path
  on platforms that pulled prebuilt better-sqlite3 binaries.
- Users who want the perf opt-in still get it via a single
  explicit `npm install better-sqlite3 --save`.

Adapter shims required
- node:sqlite throws on unused named parameters; better-sqlite3
  silently ignored them. Several call sites pass
  `bindingsFromObject(record, FULL_SCHEMA)` where the SQL only
  binds a subset (notably upsertFile excludes churn-managed
  columns). Added `extractNamedPlaceholders` to filter the
  bindings object on each prepare()'d statement's run/get/all.
- node:sqlite throws on double-close; better-sqlite3 was
  silently a no-op. Made `NodeSqliteAdapter.close()` idempotent
  to match the existing contract.

Surfaces flipped
- src/db/sqlite-adapter.ts createDatabase priority order +
  banner text (now flags failed perf opt-in, not active
  fallback).
- src/mcp/tools/status.ts reports `node:sqlite (built-in default)`
  vs `better-sqlite3 (perf opt-in, native)`.
- src/bin/codegraph.ts CLI status display same.
- package.json dropped better-sqlite3 from optionalDependencies.
- @types/better-sqlite3 kept in devDependencies for compile-time
  SqliteDatabase interface.

Test fallout addressed
- wasm-savepoint banner-text assertions: updated for the new
  framing.
- mcp-llm-visibility + sqlite-vec backend assertions: now match
  either flavor so the test stays portable across both dev
  environments.
- cochange + search-quality migration tests that directly
  `require('better-sqlite3')`: now `it.skipIf(!hasBetterSqlite3)`.
  21 tests skip when the perf opt-in isn't installed (they all
  poke the migration path against a raw better-sqlite3 handle;
  production uses the adapter regardless).

Reviewer pass — fixed before commit
- buildFallbackBanner said "Or remove the perf opt-in" then
  printed `npm install better-sqlite3 --save` — that's INSTALL,
  not remove. Bug. Fixed to `npm uninstall better-sqlite3`. Test
  assertion flipped to match.
- extractNamedPlaceholders JSDoc now notes that node:sqlite's
  "Unknown named parameter" diagnostic for typo'd keys is
  silenced as a deliberate trade.
- Sixth consecutive review where memo content (scrutiny-area #1
  docstring rot) drove the catch.

Verification
- npm run typecheck (tsgo) — clean.
- npx vitest run — 1371 passed / 34 skipped / 0 failed
  (vs 1392/13/0 baseline; +21 skipped reflect direct-handle
  migration tests that need better-sqlite3).
- npm run eval:self --compare baseline-self.json — within
  budget, +0.121 mean recall (B colbymchenry#19 ranking arc holds on
  the new default backend).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
andreinknv added a commit to andreinknv/codegraph that referenced this pull request May 9, 2026
… intent coverage hint + compare_to_ref skipped/suppress flags

Five friction-tracker items addressed. Three sub-agents in parallel
on disjoint files; reviewer pass with .claude/reviewer-memo.md
prepended caught two real correctness bugs and two info-level items
which are all addressed in this commit.

## colbymchenry#17 — dead_code static excludes test-bed fixtures

src/mcp/tools/dead-code.ts gains an excludeFixtures: boolean arg
(default true). When true, formatStaticDeadCode requests 4× overscan
from findGraphCandidates, runs filterFixtureNodes (regex match
against docs/test-beds/, __tests__/fixtures/, test/fixtures/,
spec/fixtures/), then slices to the user's maxCandidates. New
helper filterFixtureNodes is module-private (no speculative export).

Reviewer-caught correctness gap: the schema described excludeFixtures
as a general filter but llmFindDeadCode in mode='judge' was called
with only { maxCandidates }, so fixture filtering silently no-op'd
in judge mode. Fixed by extending the schema description to caveat
"applies to mode='static' only — judge mode tracked as follow-up";
the wider judge-mode wiring is non-trivial (llmFindDeadCode's args
interface needs extending) and is left as a tracked task.

Reviewer-caught info gap: 4× overscan doesn't suffice when fixture
density exceeds 75% of the candidate set. Now surfaces a warning
when overscan was exhausted AND we still under-filled — the agent
sees "raise maxCandidates if you need more" instead of silently
truncating.

New test file __tests__/mcp-dead-code-fixtures.test.ts (3 cases):
filter on, filter off, spec/fixtures pattern.

## colbymchenry#19 — search mode='intent' attaches coverage hint on 0 hits

src/mcp/tools/_search-intent.ts. When handleSearchIntent returns
empty, computes summary coverage and appends one of two hints:
- coverage < 50%: "intent-search depends on LLM summaries (current
  coverage X%) — run codegraph summarize to expand the corpus, or
  fall back to mode='exact' / codegraph_grep"
- coverage >= 50%: "0 hits at X% coverage — concept may not be
  summarised yet, or may not exist in the codebase. Try
  codegraph_explore"

Non-empty results unchanged. Coverage-stat errors are caught and
logged so they don't fail the search.

Reviewer-caught correctness bug: getSummaryCoverage(cg.queries) was
called WITHOUT a kinds filter; the helper's own JSDoc warns that
"counting parameters/imports/files in the denominator would
understate coverage and confuse the user". Fixed by passing
SUMMARIZABLE_KINDS (already exported from src/llm/summarizer.ts and
used by status.ts the same way). Three OTHER call sites in the
codebase also pass no kinds — filed as colbymchenry#49 follow-up since they're
out of scope for this commit.

New tests added to __tests__/search-intent.test.ts (2 cases:
low-coverage hint, high-coverage hint).

## colbymchenry#23 — compare_to_ref surfaces skipped (non-TS / non-indexed) files

src/compare/index.ts adds filesSkipped: number to CompareResult.
The compare logic counts files git reports as changed but cg can't
structurally diff (non-indexed languages, .md/.json, binary, etc.).
Formatter src/mcp/tools/compare.ts surfaces "> N file(s) skipped
(non-indexed or non-TS)" only when count > 0 (no noise on clean
diffs). Manual eyeball on HEAD~5 confirmed correct count.

## colbymchenry#24 — compare_to_ref suppressLineRangeOnly flag

src/compare/index.ts adds suppressLineRangeOnly: boolean (default
false for backward compat — existing callers asserting on
result.totals.modified would break). Adds lineRangeOnlyCount to
FileDelta. New helpers isPureLineRangeOnly / applyLineRangeOnlySuppression
(module-private). When true, FileDeltas where every modified symbol's
reasons are exactly ['line range changed'] (no signature change, no
modifier flip, no body diff) collapse into a single per-file
roll-up: "src/foo.ts: 14 symbols renumbered (no content change)".
Mixed files (real change + renumber) keep real changes individually
shown. MCP schema in compare.ts exposes the flag.

Manual eyeball on HEAD~5 of this repo: 96/174 modified symbols
(55%) were pure-renumber noise that suppression collapsed cleanly
into 7 roll-up lines.

New tests added to __tests__/compare.test.ts (4 cases): filesSkipped
counts non-TS files, filesSkipped: 0 doesn't add the line, suppress
collapses pure-renumber, mixed files keep real changes individually.

## colbymchenry#34 — at_range rejects paths outside project root

src/mcp/tools/at-range.ts. New validateFileWithinRoot helper:
path.resolve canonicalization on both sides, checks "equals root OR
starts with root + sep". Single-range and bulk-range forms both
validate; bulk form fails the whole call if ANY range is out-of-root
(no silent filtering). Reviewer-caught info: documented symlink
limitation in JSDoc — within-root symlinks pointing OUTSIDE the root
will pass; if untrusted symlinks become an issue, swap to
fs.realpathSync.

New tests added to __tests__/at-range.test.ts (2 cases: traversal
'../../etc/passwd' rejected, bulk form with one out-of-root range
fails the whole call).

## Reviewer-caught items beyond the original 5

- New friction colbymchenry#48 filed: typescript-lsp plugin reverts sub-agent
  Edit calls on first application (not a codegraph defect; harness
  interaction). Sonnet caught it during colbymchenry#23/colbymchenry#24 work and re-applied
  successfully on second pass.
- New friction colbymchenry#49 filed: 3 other getSummaryCoverage call sites in
  status.ts and bin/codegraph.ts have the same denominator-inflation
  bug — out of scope for this commit, tracked separately.

## Verification

- 9 files (8 modified + 1 new test), +398/-13
- npm run typecheck — clean
- 50/50 tests pass in focused slice (compare / at-range /
  mcp-dead-code-fixtures / search-intent)
- New module-private helpers (filterFixtureNodes, isPureLineRangeOnly,
  applyLineRangeOnlySuppression, validateFileWithinRoot) all have
  concrete in-tree callers in the same diff — no speculative
  exports per reviewer-memo item #7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.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.

1 participant