- Scope dedupe key to label::relativePath in mergeMultiCollectionResults
so same file in different projects is not collapsed
- Compute embedding once in searchMultipleCollections via internal
searchChunksWithVector helper (avoids N redundant API calls)
- Compare base project hashes (not branch-suffixed names) when skipping
duplicate linked projects in resolveLinkedCollections
- Use path.resolve() for platform-neutral assertion in query-tools tests
- Update multi-collection-search tests for new cross-project dedup semantics
- Refactor git temp repos into initTempRepo() helper using git config
instead of env vars (resolves Critical finding)
- Restore SOCRATICODE_LINKED_PROJECTS and SOCRATICODE_PROJECT_ID to
original values in resolveLinkedCollections afterEach
- Fix TypeScript 'never' type errors in query-tools mocks by adding
explicit SearchResult[] return types
CI runners have no git user.name/email configured, causing
'git commit --allow-empty' to fail with 'Author identity unknown'.
Pass GIT_AUTHOR_NAME/EMAIL and GIT_COMMITTER_NAME/EMAIL env vars.
CI checks out in detached HEAD state, causing detectGitBranch(process.cwd())
to return null. Replace process.cwd() with temporary git repos that have a
known branch and initial commit, making tests deterministic everywhere.
- query-tools.test.ts: 6 new tests for includeLinked parameter:
- omitted/false → calls searchChunks (not searchMultipleCollections)
- true → calls searchMultipleCollections via resolveLinkedCollections
- passes collections and args correctly
- project label appears in output
- no project tag when field absent
- multi-collection-search.test.ts: 1 new test for searchMultipleCollections
empty-input short-circuit (internal searchChunks calls cannot be mocked
from the same module — integration covered by query-tools tests)
resolveLinkedCollections() was calling projectIdFromPath() for linked
projects, which with SOCRATICODE_BRANCH_AWARE=true appended the linked
project's git branch to its ID. Linked projects indexed without
branch-aware mode don't have __branch collections, so lookups failed.
Extract coreProjectId() helper (hash-only, no branch suffix) and use
it for linked projects. Also fix dedup to compare collection names
instead of raw IDs to handle the branch suffix mismatch.
Adds unit test verifying linked collection names are branch-agnostic.
- README: new Features entries, full sections with config examples
- README: new env vars SOCRATICODE_BRANCH_AWARE, SOCRATICODE_LINKED_PROJECTS
- README: updated codebase_search tool description for includeLinked
- DEVELOPER.md: updated config.ts description, branch-aware and linked projects sections
- detectGitBranch() detects current git branch via git rev-parse
- sanitizeBranchName() converts branch names to Qdrant-safe suffixes
- When SOCRATICODE_BRANCH_AWARE=true, projectIdFromPath appends __branch
to create separate indexes per branch
- Explicit SOCRATICODE_PROJECT_ID takes precedence (no branch suffix)
- 14 unit tests for sanitization, detection, and integration
Relates to #19
- loadLinkedProjects() reads .socraticode.json config and env var
- resolveLinkedCollections() maps linked projects to collection names
- codebase_search gains includeLinked parameter for cross-project queries
- Results tagged with [project-label] when searching across projects
- 10 unit tests for config loading and collection resolution
Relates to #20
Add searchMultipleCollections() and mergeMultiCollectionResults() to qdrant.ts.
Queries multiple Qdrant collections in parallel, merges results using Reciprocal
Rank Fusion (k=60), and deduplicates by relativePath (first collection wins).
Add optional 'project' field to SearchResult type for source attribution.
This is the shared foundation for linked projects (#20) and branch-aware
indexing (#19).
Refs: #19, #20
Single-module resolution (src/main/java/…) already worked.
Multi-module layouts like:
module-a/sub/src/main/java/com/example/Foo.java
were silently unresolved because the three fixed src-dir prefixes
never matched. The dependency graph therefore always produced 0
edges for any Java/Kotlin/Scala project that follows the standard
Maven/Gradle multi-module layout.
Fix: introduce `buildJvmSuffixMap()` which scans `fileSet` once
(O(n)) and registers every JVM source file by its class-path key
(i.e. everything after src/main/<lang>/). `resolveImport` accepts
the map as an optional last argument and falls back to it when the
existing prefix-based approach yields no result.
- `buildJvmSuffixMap` exported for reuse / testing.
- Map is built once per `buildCodeGraph` call, only when the
project contains at least one JVM file — zero cost for other
language projects.
- Lookup is O(1) per import, replacing a worst-case O(n) linear
scan on every miss.
- Works on both Windows (backslash) and POSIX (forward-slash)
because the map key is built with `path.sep`.
- 7 new unit tests covering: map construction, test-source
exclusion, multi-module Java resolution, Kotlin resolution,
unresolvable class, stdlib guard.
Fixes: enterprise Java/Spring Boot codebases (30+ Maven modules)
reporting 0 edges in codebase_graph_stats.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The published npm package has stale dist/ files that don't include
the SOCRATICODE_PROJECT_ID environment variable support added in source.
This causes the env var to be silently ignored when installed via npm.
Adding a prepublishOnly script ensures tsc runs before every publish,
keeping dist/ in sync with source.
feat: add CSS @import tracking and path alias resolution to dependency graph
Thanks cstuncsik, it was in my notes as a known limitation of the previous attempt, thanks for covering this up, very clean and comprehensive, much appreciated!
- Move Svelte/Vue from "Indexing Only" to "Full Support" in README
- Move SASS/LESS to "Code Graph via Regex" in README
- Add graph-aliases.ts to DEVELOPER.md service file listing
- Update DEVELOPER.md data flow with CSS @import, path alias, and SCSS
partial resolution steps
Add CSS @import extraction from Svelte/Vue <style> blocks and standalone
CSS/SCSS/SASS/LESS files. Add path alias resolution from tsconfig.json /
jsconfig.json compilerOptions.paths with extends chain support.
ensureOllamaReady() was called unconditionally on every search and context
operation, causing failures for OpenAI and Google embedding users. Now only
called when embeddingProvider is ollama; otherwise the configured provider
is initialized via getEmbeddingProvider().
Fixes#7
Co-authored-by: pineapplestrikesback <pineapplestrikesback@users.noreply.github.com>
Svelte and Vue files were included in the graph as leaf nodes (targets
of import edges) but their own imports were never extracted because
no ast-grep grammar exists for these languages.
This adds support by parsing .svelte/.vue files as HTML (built-in
grammar), extracting <script> block content, and re-parsing it as
TypeScript to extract imports using the existing JS/TS logic.
Changes:
- code-graph.ts: register .svelte and .vue in getAstGrepLang()
- graph-imports.ts: add Svelte/Vue script extraction handler; refactor
JS/TS import extraction into shared extractJsTsImportsFromNode()
helper to avoid duplication
- graph-resolution.ts: add "svelte" and "vue" cases to resolveImport(),
with .svelte/.vue as first-priority extension resolution
- graph-imports.test.ts: add tests for Svelte (static, dynamic, module,
no-script, JS-only) and Vue import extraction
Zero new dependencies — uses the built-in Lang.Html and Lang.TypeScript
grammars from @ast-grep/napi.
Known limitation: path aliases ($lib/, @/) are not resolved and will be
treated as external packages (same as current JS/TS behavior).
When SOCRATICODE_PROJECT_ID is set to share a Qdrant collection across
git worktrees, the indexer still used absolute paths as keys in the file
hash map, chunk IDs, and for deleting file chunks. This caused every
worktree to see all files as "new" and trigger a full re-index, defeating
the purpose of the shared project ID feature.
Switch all internal keying from absolute paths to relative paths:
- chunkId() now hashes on relativePath for stable IDs across worktrees
- File hash map (change detection) keyed by relativePath
- deleteFileChunks() filters on relativePath Qdrant field
- Deleted file detection uses relative path sets
Absolute paths are now only used for actual file I/O (stat, readFile).
- Add .claude-plugin/plugin.json with MCP server reference and hooks
- Add codebase-exploration skill with search-before-reading workflow
- Add codebase-management skill with indexing and troubleshooting guides
- Add codebase-explorer delegatable subagent for deep analysis
- Add SessionStart hook for duplicate MCP detection
- Add .mcp.json for plugin-bundled MCP server config
- Update package.json files array to include plugin assets in npm package
- Add release-it after:bump hook to sync plugin.json version
- Update README with plugin install badge, instructions, and guidance