Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ Never `unwrap_or_default()` a store error on a search path — "no results" and

## Changelog highlights (recent)

- **v1.4.4** — resident C# workspace pool no longer serves stale `find_impact` results after a rebuild: `WorkspacePool::evict` bumps a per-solution generation counter closing a spawn-in-flight race, and `scip_ref_cache` is now cleared unconditionally on both full and incremental rebuilds
- **v1.3.37** — per-index embedding models end-to-end: serve queries, `POST /repos` and CLI index/stats/status honour the model each index records in its `metadata.json`; `serve --model` sets the default for newly created indexes; unrecorded indexes are queried with the built-in model plus a caller-facing warning; mid-rebuild indexes no longer report ready (PR #248)
- **v1.3.23–v1.3.36** — dependency + platform wave: rmcp 3.3, fastembed 6.1 + ort rc.13, tantivy 0.26, axum 0.8, ratatui 0.30 + crossterm 0.29, thiserror 2, notify 8, tree-sitter 0.27, dirs/sha2/scip/sysinfo refresh + dependabot (weekly); clears the open Aikido/RUSTSEC advisories
- **v1.3.19** — `find_impact` ambiguity envelope + `resolved_symbol`; partial-results `warnings`; C# symbol-key uniqueness (index v2.0)
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ more PRs land; when the release is actually tagged, the same section is
finalized in place with a date — no renaming/migration step needed.
-->

## [1.4.4]

### Fixed

- **A resident C# workspace can no longer answer `find_impact` from source that predates the latest change.** The resident Roslyn workspace pool (todo #115) is keyed only by solution path and reused across `find_refs` calls, with no tie to repo state beyond an idle TTL. A symbol rebuild advanced `index_head_sha` to the new commit, but the resident workspace kept answering from the compilation loaded before it — a newly extracted method's call site went missing from `find_impact` with `index_head_sha == current_head_sha` and no warning (found via todo #165's end-to-end test). `WorkspacePool::evict` now runs at the end of every rebuild, full or incremental; a per-solution generation counter closes the window where a spawn already in flight for that solution would otherwise still install stale. `scip_ref_cache` is now also cleared in full on every incremental rebuild (previously only full rebuilds did): the old selective invalidation could purge a cache entry whose *existing* reference list pointed at a changed file, but could never catch an unrelated cached symbol gaining a brand-new reference *from* that file — reading the new content is Roslyn's job, not the cache's, so the selective scheme was removed once the blanket clear subsumed it.

- **LMDB keys may now be ~1980 bytes instead of 511 — C# symbol rebuilds stop failing on their own signatures.** heed's `longer-keys` feature builds LMDB with `MDB_MAXKEYSIZE=0`, deriving the limit from the page size. The scip-csharp helper writes fully qualified parameter types into the SCIP key, so real methods reach 912 bytes (`MasterDataSyncService#EnhanceCountryProductAsync(System.Collections.Generic.List<global::…>)`); at 511 LMDB answered `MDB_BAD_VALSIZE`, which failed the entire rebuild for that repo and — until the classifier learned better — wiped and reindexed the whole database, on every serve start, for five repos at a time. A key that still exceeds the limit is now skipped with a counted warning instead of failing the rebuild: `find_impact` loses that one symbol, the other ~40 000 are indexed. Note: a build without the feature cannot read the long keys this one writes.

- **A repo is wiped at most once per process for "storage-format corruption".** `MDB_BAD_VALSIZE` was read as "data written by an older arroy/heed major" and answered with a full wipe + rebuild. On 2026-09-17 the same five C# repos were wiped twice in one day: the second failure hit a database this process had created hours earlier, so the error was written by the *current* binary (LMDB rejects an empty or >511-byte key), not by an old format. Each misdiagnosis cost ~20 minutes of reindex per repo and re-armed itself on the next symbol rebuild. A second format recovery for the same alias is now refused and reported as a writer bug, the raw LMDB error is logged instead of only the conclusion, and every SCIP `put` carries its table name plus the offending key's size so the next occurrence names its own cause.

- **The last MDB_MAP_FULL retry no longer fails in silence.** After two resize doublings the third attempt returned its error without a single log line, which is why a wedged insert looked exactly like a crash (a 3.4 GB database at 0 chunks, no error in the log). All three retry loops — insert, delete and index build — now log the final give-up with the map size and the batch size, and announce each retry. A failed attempt also hands back the chunk ids it consumed: the transaction aborted, so the retry no longer pushes the id space (and arroy's item range) further out on every round.

- **A leaked indexing task no longer keeps a repo's LMDB env and writer lock open forever.** Evicting a stale `active_reindexes` marker only corrected what the TUI and the reindex guard believed — the background task behind it kept running and kept the `Arc<SharedStores>` it captured, so the env and `.writer.lock` stayed held for the process lifetime. The repo then logged as idle and "DB closed" while every write (`reindex`, format recovery, `POST /repos`) failed with "Database is locked by another process", indefinitely: observed on a repo left at 0 chunks for two days after a format-recovery rebuild wedged. The staleness check now cancels the task's token (cooperatively — the handle is still never aborted), format recovery reports a cancelled rebuild as a failure instead of logging "rebuild complete" over an empty index, and idle eviction warns with the holder list when the env is still open after the repo was evicted. The post-build self-cleanup that deletes an orphaned `.codesearch.db` now keys on the alias actually being gone from the config instead of on a cancelled token — a cancelled token no longer implies "repo removed", so the old rule would have wiped a live repo's index whenever a rebuild outlived its 30-minute marker.

## [1.4.3] - 2026-09-17

### Security
Expand Down
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ num_cpus = "1.16"
async-trait = "0.1"
# Vector database
arroy = "0.8"
heed = "0.22"
# `longer-keys` builds LMDB with MDB_MAXKEYSIZE=0, so the key limit is derived
# from the page size (~1980 bytes on 4KB pages) instead of the 511-byte default.
# C# SCIP symbols carry fully qualified parameter types and reach 900+ bytes;
# at 511 a single such method failed the whole symbol rebuild. Note: a build
# WITHOUT this feature cannot read the long keys it writes.
heed = { version = "0.22", features = ["longer-keys"] }
bincode = "1.3"
# SCIP symbol indexing — parses standard SCIP protobuf (.scip) emitted by
# Sourcegraph indexers (e.g. scip-typescript) for the TypeScript symbol adapter.
Expand Down
13 changes: 9 additions & 4 deletions src/index/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1233,12 +1233,14 @@ impl IndexManager {
}
}
Err(e) => {
// `{:#}` — the whole chain. Plain `{}` prints only the outermost
// context, which hides the LMDB error under its put context.
warn!(
"⚠️ [{}] {} symbol rebuild failed: {}",
"⚠️ [{}] {} symbol rebuild failed: {:#}",
repo_label, lang_label, e
);
if let Some(n) = notifier {
n(SymbolRebuildSignal::Failed(e.to_string()));
n(SymbolRebuildSignal::Failed(format!("{e:#}")));
}
}
}
Expand Down Expand Up @@ -1713,14 +1715,17 @@ impl IndexManager {
}
}
Err(e) => {
// `{:#}` for the same reason as the
// full-rebuild path: the put context
// would otherwise hide the MDB_* code.
warn!(
"⚠️ [{}/{}] Symbol rebuild failed ({}): {}",
"⚠️ [{}/{}] Symbol rebuild failed ({}): {:#}",
i + 1,
total_groups,
csproj_name,
e
);
last_error = Some(e.to_string());
last_error = Some(format!("{e:#}"));
}
}
}
Expand Down
Loading
Loading