Commit Graph

6 Commits

Author SHA1 Message Date
Giancarlo Erra 4e41b4604e feat(impact): wire Phase F into watcher; fix prototype-key crash; add real scale test
Closes the four reviewer-flagged gaps from the previous round:

1. **Phase F wired into the watcher / `codebase_update`.**
   `rebuildGraph(path, { skipSymbolGraph: true })` now exposes a
   file-import-only build mode. `services/indexer.ts` calls it +
   `updateChangedFilesSymbolGraph(...)` when meta exists AND ≤ 50 files
   changed (`INCREMENTAL_SYMBOL_THRESHOLD`); falls back to full rebuild
   above that. Measured speedup on a 1000-file synthetic repo: full
   rebuild 6.55 s → Phase F single-file update 197 ms (~33×).

2. **Real end-to-end scale test.**
   New `tests/integration/symbol-graph-scale.test.ts` generates 1000
   synthetic Python files × 20 symbols/file (20k symbols) against a real
   Qdrant, asserts (a) full rebuild within budget, (b) cold listSymbols /
   getImpactRadius queries within budget, (c) Phase F update ≥ 4× faster
   than full rebuild. `SCALE_LARGE=1` pushes to 10k files / 200k symbols.

3. **Smoke benchmark numbers captured.**
   New `scripts/benchmark-graph.ts` runs `rebuildGraph` against any
   target dir and emits JSON + a Markdown row. Numbers for SocratiCode
   itself (82 files / 571 symbols / 9914 call edges / 0.90 s / 167 MB
   RSS) and the synthetic 1000-file repo are now in DEVELOPER.md
   § "Real-world benchmark numbers".

4. **Logger test flake fixed.**
   `services/logger.ts` exposes `setLogLevel` / `getLogLevel`;
   `tests/unit/logger.test.ts` pins the level in beforeEach and restores
   in afterEach. Verified deterministic with `SOCRATICODE_LOG_LEVEL=debug`
   set in the shell environment.

### Bug discovered + fixed by the new benchmark

Running `scripts/benchmark-graph.ts` against SocratiCode itself crashed
the symbol graph build with `TypeError: existing.push is not a function`.
Root cause: shard maps used `shard[name]` bracket access on a plain
`{}`, which returned `Object.prototype.constructor` (a function) for
common method names like `constructor`, `toString`, `hasOwnProperty`.
Fixed by guarding all reads with `Object.hasOwn` in
`services/code-graph.ts` and `services/symbol-graph-incremental.ts`.
Added a regression test in
`tests/integration/symbol-graph-incremental.test.ts`.

### QA

- Biome lint: clean (auto-fixed 1 file).
- VS Code Problems panel: clean.
- Unit tests: 676/676 pass (29 files); reproducible.
- Integration tests touched: 45/45 pass (incremental, scale,
  indexer, code-graph).
- CodeRabbit review: no findings.
- Snyk Code: 0 issues.

### Doc updates

- DEVELOPER.md: removed "watcher still triggers full rebuild" wording,
  added "Real-world benchmark numbers" subsection with measured table.
- CHANGELOG.md: removed "Known Limitations" block; added new
  Bug Fixes entries (prototype keys, logger flake) and a Performance
  entry for the wired Phase F path with measured numbers.
2026-04-21 15:59:55 +01:00
Giancarlo Erra 2d686a2688 feat(impact): close gaps from review — Phase F API, scale + integration tests, language coverage
Addresses six gaps in the prior Impact Analysis work:

1. **Scale benchmarks** (was missing): tests/unit/symbol-graph-scale.test.ts
   exercises sharding/hashing at 10k–100k symbol volumes with loose
   regression thresholds (>10× slowdown to fail).

2. **Per-language symbol-extraction tests** (was ~15% of plan):
   tests/unit/graph-symbols.test.ts now covers Rust, Java/Kotlin/Scala (JVM),
   C#, C/C++, Ruby, PHP, Swift, Bash, and the regex fallback path.

3. **Phase F (per-file incremental updates)** — implemented as
   src/services/symbol-graph-incremental.ts with
   updateChangedFilesSymbolGraph(). Re-extracts changed files, diffs against
   persisted payloads via contentHash, patches only affected name (≤27) and
   reverse-call (≤256) shards, and updates meta counts incrementally.
   Integration tests in tests/integration/symbol-graph-incremental.test.ts.
   Watcher wiring is documented as a follow-up in CHANGELOG (still does
   full rebuild on save).

4. **Integration tests for the four new MCP tools**: codebase_impact,
   codebase_flow, codebase_symbol, codebase_symbols added to
   tests/integration/tools.test.ts.

5. **Symbol-graph store unit tests**: tests/unit/symbol-graph-store.test.ts
   covers nameShardKey, allNameShardKeys, reverseShardKey, reverseShardHex,
   contentHashOf — 14 tests.

6. **Bug fix**: Java/Kotlin/Swift/Scala silently failed because ast-grep
   throws 'Invalid Kind' when a queried node-kind doesn't exist for that
   grammar (e.g. object_declaration is Kotlin-only). The outer try/catch in
   extractSymbolsAndCalls swallowed the error and returned only <module>.
   Fixed via safeFindAll wrapper applied to all 36 call sites in
   src/services/graph-symbols.ts.

Also fixes a CodeRabbit-flagged comment/code mismatch in
src/services/graph-entrypoints.ts (now actually checks for it/describe
test names as the comment claimed).

Tests: 676 unit pass. Lint clean. CodeRabbit clean. Snyk clean.
2026-04-21 15:27:16 +01:00
Giancarlo Erra 00f7be169c fix: address CodeRabbit PR review feedback
- Use Object.hasOwn() instead of `in` for log level validation
- Normalize relativePath in shouldIgnore() for Windows compatibility
- Reject zero/negative/decimal values in embedding config (Number() instead of parseInt())
- Update aggregate test count to 765
- Harden code-graph test assertion with explicit toBeDefined()
2026-04-12 21:31:45 +01:00
Giancarlo Erra bb5e6c3e19 fix: address CodeRabbit review findings 2026-04-12 20:21:36 +01:00
Csaba Tuncsik 505fbd722b fix: use relative paths for index keys to support shared worktree indexes
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).
2026-03-16 08:39:22 +01:00
Giancarlo Erra 3f0ed5a286 feat: SocratiCode v1.0.0 — initial release 2026-02-28 17:06:21 +00:00