Repository navigation
sync: catch up fork to upstream develop v1.5.32 + harden the macOS dev loop - #5
Conversation
…lupkede#135) The incremental-refresh and watcher paths constructed a fresh EmbeddingService per call; in serve the process-global LMDB registry refused the second open of the persistent cache, silently degrading every refresh to cache-less re-embedding. Thread the serve-wide pool through and reuse pool.get(model) so the process-shared cache is hit; CLI/standalone-MCP processes keep direct construction (no pool there).
- Chunk paths stored relative to the indexed project root so built DBs are portable across machines/containers (snapshot federation previously worked only because build path == serve path). One-time consequence: existing DBs refreshed by this binary see all files as changed and re-embed once. - index add --local: skip serve delegation, always build in-process. - index/index add: write a clean, unmangled build log to <project>/.codesearch.db/build.log when stdout is not a TTY (or --log-file). - current_git_head: strip GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_OBJECT_DIRECTORY from the child env so repo discovery keys off the given root (pre-existing test failure under push hooks).
…ocal, pool reuse)
…locks, status labels 2c13826 made chunk paths project-relative, which re-embedded every legacy index and duplicated chunks; it also exposed three latent failure modes. One commit carries four fixes for that fallout: - Key migration (index/key_migration.rs, cache/file_meta.rs): re-key legacy absolute FileMetaStore keys to project-relative form, rewrite the chunk paths in both stores, and sweep chunks no tracked file references — unchanged files are recognised as up to date instead of re-embedded, and the duplicates an earlier interrupted re-embed left are removed. - FTS writer (fts/tantivy_store.rs): prepare_commit joins and respawns the indexing workers and can abort half-way, leaving zero workers behind a live 10k-doc pipeline; that writer is now discarded and an error returned instead of silently dropping every later batch and blocking add_document. - Warmup (serve/mod.rs): register Warm and release the per-alias open_lock before the refresh so queries are answered from existing data; track the refresh with begin/end_indexing so the reaper leaves the repo alone and FSW does not start mid-warmup; queries acquire open_lock with a deadline instead of queueing behind a cold open forever. - Status (mcp/status.rs): report indexing/busy/held-in-process instead of mislabelling our own activity as locked-externally, and fetch live stats via try_read so status answers while a batch holds the store lock.
The orphan sweep ran on every refresh and could delete chunks a concurrent refresh had inserted but not yet recorded; it now runs only after a real migration, and the FSW no longer starts while warmup indexes. Path rewrites lock per batch so queries interleave, every re-keyed chunk is mirrored into FTS so a failed mirror is retried, and a killed FTS writer now returns an error instead of silently dropping documents.
BOIN-scale warmups run past MAX_INDEXING_SECS (30 min), so the lazy stale-marker eviction dropped the marker mid-refresh and the idle reaper could evict the repo while the refresh still held its stores (LMDB double-open / todo flupkede#131 shape). perform_incremental_refresh_with_stores now fires an IndexingHeartbeat at start, before each slow phase, and per batch; warmup passes a closure that renews its marker via ServeState::renew_indexing (upsert, so a raced eviction cannot strip protection for the rest of the run). Other callers pass None for now.
The FSW's completion callback cleared the whole alias entry with a plain bool, so a watcher refresh finishing mid-run erased a concurrent force reindex's marker — the reaper could then evict a repo the reindex still held (LMDB double-open shape). active_reindexes now maps alias -> owner -> last heartbeat (IndexingOwner: Warmup/Watcher/Reindex/Symbol); begin/end/ renew are owner-scoped, is_indexing evicts only stale owners and still cancels a leaked index task, and begin_indexing keeps rejecting while any owner's marker is fresh. Adds the race, exclusivity and per-owner eviction tests. Review-fixes: - [Critical] Empty-map cleanup dropped the shard guard before remove(alias), so a concurrent begin_indexing insert landing in the gap was erased (re-opened the plain-bool marker race) → all three sites (is_indexing, end_indexing, FSW callback) now use atomic remove_if(alias, |_, m| m.is_empty()) which holds the shard lock across predicate + removal.
index_status_impl's group fan-out still blocked on vector_store.read(): an indexing run holds the write lock for whole batches (build_index for minutes), so a group status call queued behind it. It now uses try_read like list_projects; a busy store counts as a failed stats read with a caller-facing warning naming the busy lock — never silently skipped.
… reader A live indexer holds vector_store's write lock for the whole batch; every read-side caller blocked on it forever, so one slow/stuck reindex hung every query. New CODESEARCH_STORE_LOCK_WAIT_SECS-configurable bounded_vector_read() (default 300s) wraps every direct vector_store.read().await in mcp/mod.rs (with_vector_store_read_for, with_vector_store_read_multi), mcp/runtime.rs (require_prebuilt_index_ready) and every per-store fan-out site in mcp/find.rs, mcp/get_chunk.rs, mcp/graph.rs, mcp/literal_search.rs, mcp/search.rs, mcp/explore.rs — each site now attributes a timeout the same way it already attributes a store error (note_store_failure / push_store_warning, per its existing warnings channel), so a busy store degrades one caller's answer instead of hanging it. FTS store reads are left unbounded — short-duration ops, out of scope.
The prior commit bounded vector_store reads but deliberately left fts_store.read().await unbounded. A live indexing batch holds both locks for its duration, so a stuck reindex could still hang every literal-search/find caller through the FTS side alone. New bounded_fts_read() (src/mcp/mod.rs, same CODESEARCH_STORE_LOCK_WAIT_SECS wait as bounded_vector_read) wraps the FTS lock at all four direct read sites: with_fts_store_read_for's two branches, the per-store loop in with_fts_store_read_multi (attributes the timeout into `failures`, same as its vector-store sibling), and runtime.rs's require_prebuilt_index_ready.
Final review of the 6-stage fallout fix found a narrow window: warmup registered RepoState::Warm before calling begin_indexing(Warmup), so a concurrent query landing in that gap could see is_indexing() == false and let FSW start a Watcher-owned refresh racing warmup's still-loading file_meta — the exact hazard the per-owner marker refactor exists to prevent. Fix: acquire the Warmup marker before the repo becomes visible in self.repos, so FSW's gate always sees it.
Pre-push leak scan flagged 'BOIN' (client codename) in three rationale comments about warmup duration at scale. Reworded to 'large repos' / 'large-repo' — no behavior change.
find(kind="usages") names its target via 'symbol', not file/path — edit-guard-post hooks now recognize it so both find_impact and find attribute to the same key.
…ath-migration Fix warmup-lock fallout after path migration
`Path::has_root()` only recognizes a Windows drive-letter path (`C:/...`) as rooted on Windows. On the Linux CI runner it saw such a path as relative, so `prefix_path_with_alias` wrongly alias-prefixed an out-of-root Windows path instead of leaving it unprefixed — failing mcp::tests::test_path_prefix_preserves_path_outside_root in CI. Added `is_portable_absolute()`, a platform-independent textual check (leading `/` or drive-letter + `:`), used instead of `has_root()`.
…rts ready Small models misread "Closed"/indexed:false as "index unavailable" and wrongly fall back to grep. Idle = index on disk, stores evicted by the idle reaper, auto-reopen on next query — i.e. searchable, first query slightly slower. Aggregated index_status now reports indexed:true + status:"ready" when any repo has an index on disk, with an explicit "Indexed and searchable: N" hint; "no_index" only when nothing is on disk. Wire string becomes "idle" (TUIs keep tolerating legacy "closed"). Review-fixes: - [Important] aggregation branches untested → extracted pure helper aggregate_serve_index_status (responses.rs), index_status_impl calls it, 3 unit tests pin all-idle→ready/indexed, nothing-on-disk→no_index, empty hub→no_repos - [minor, pre-existing] all-Readonly hub still reports no_index → deferred, out of this change's scope (requirement enumerated open+warm+idle); follow-up candidate
status_cell's string match now delegates to pure status_cell_spec -> (String, Style) so tests can assert text+style without a Cell style getter (ratatui 0.30 Cell::style is a setter). 3 tests: idle+closed gray cell, Idle label mapping, unknown-status fallback distinct from idle. Review-fixes: - [Important] status_cell/detail_status_style string arms (idle | closed) had no test — silent _ fallback could regress legacy-peer tolerance unnoticed → 3 tests in src/serve/tui_common.rs pin cell text/style and label mapping for idle, legacy closed, and the fallback arm
…status Direct push to develop bypassed bump-develop.yml (fires on PR merges only), so the patch bump is done by hand; CHANGELOG gains the pending [1.4.11] section (finalized with a date at tag time, per the file's convention note).
…de#192) - .cargo/config.toml: [target.x86_64-pc-windows-msvc] linker = "rust-lld" Bin-crate rebuild+link: 2m56s -> 1m32s (x2 faster dev cycle) - build.ps1: -Release now throws (debug-only policy); release artifacts are built by CI (release.yml) only - sccache: REJECTED — caches compilation, not linking (linking is the bottleneck), and disables incremental compilation; same verdict as audit flupkede#191 - tests/*.rs consolidation (53-binaries item in flupkede#191): N/A here — codesearch has 5 integration test binaries, consolidation not warranted - README.md "cargo build --release" (end-user build-from-source) kept: end users want optimized binaries; debug-only applies to the dev loop (AGENTS.develop.md already mandates it, CI builds debug)
…TS.develop.md; branch-local plan
…uilds build: debug-only policy + rust-lld linker (issue flupkede#192)
Bumps the cargo-minor-and-patch group with 4 updates: [thiserror](https://github.com/dtolnay/thiserror), [fastembed](https://github.com/Anush008/fastembed-rs), [rand](https://github.com/rust-random/rand) and [rmcp](https://github.com/modelcontextprotocol/rust-sdk). Updates `thiserror` from 2.0.20 to 2.0.21 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](dtolnay/thiserror@2.0.20...2.0.21) Updates `fastembed` from 7.0.1 to 7.1.0 - [Release notes](https://github.com/Anush008/fastembed-rs/releases) - [Commits](anush008/fastembed-rs@v7.0.1...v7.1.0) Updates `rand` from 0.10.2 to 0.10.3 - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](rust-random/rand@0.10.2...0.10.3) Updates `rmcp` from 3.4.0 to 3.4.1 - [Release notes](https://github.com/modelcontextprotocol/rust-sdk/releases) - [Changelog](https://github.com/modelcontextprotocol/rust-sdk/blob/main/release-plz.toml) - [Commits](modelcontextprotocol/rust-sdk@rmcp-v3.4.0...rmcp-v3.4.1) --- updated-dependencies: - dependency-name: thiserror dependency-version: 2.0.21 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-minor-and-patch - dependency-name: fastembed dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: cargo-minor-and-patch - dependency-name: rand dependency-version: 0.10.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-minor-and-patch - dependency-name: rmcp dependency-version: 3.4.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-minor-and-patch ... Signed-off-by: dependabot[bot] <support@github.com>
…ipeline, find_impact self-heal, tests - trigger_symbol_rebuild generalized per language with a per-(alias,lang) in-flight claim (DashMap, stale takeover past indexing timeout); C#-only TUI status / last_scip bookkeeping stays gated on the language - evaluate_symbol_rebuild: generic gate (applies_to before availability); C# delegates to evaluate_csharp_rebuild; non-C# rebuilds only a MISSING index (drift stays watcher/branch driven — no-thrash) - run_phase_2_symbols (was run_phase_2_csharp_scip) iterates all installed languages; TypeScript now gets its initial build at startup - reindex_handler: maybe_rebuild_symbols gate-driven for every language, symbols=true still forces (previous unconditional behaviour) - add_repo_handler: maybe_rebuild_symbols after restart_fsw — closes the runtime-add gap (registered while serve runs never saw the startup pass) - find_impact: missing definitions index (has_index false) starts a fire-and-forget heal_missing_symbol_index (serve mode, alias re-resolved from config so remote mounts are never healed locally) and the empty NotFound answer carries a warning marking it UNKNOWN; a successful resolution keeps its payload to the persisted-warnings channel - tests: claim reject/stale-takeover, gate applicability-before-availability, heal no-op outside remit, force skips non-applicable, never-built index warns on the empty answer (fails without the fix), phase-2 composition wires candidate through to trigger, serve-mode self-heal runs the rebuild Review-fixes: - [Test] no coverage reached run_phase_2_symbols wiring or the serve-mode heal spawn → added run_phase_2_symbols_wires_candidate_through_to_trigger and find_impact_self_heal_runs_the_rebuild_in_serve_mode (dummy helper via env override; rebuild failure observable as CSharpIndexStatus::Error) Validation: cargo fmt --check clean, clippy --all-targets -D warnings clean, cargo test --lib --bins: 761 passed / 0 failed.
Pressing 'q' stopped the HTTP server but orphaned running helper children: a one-shot rebuild (index / find-refs / batch-find-refs) kept computing for minutes on a dead host and held the helper exe locked — the intermittent 'file in use' failure in copy-to-common — and a resident workspace child sat waiting on its stdin pipe forever. Static clients are not dropped at process exit, so the existing Drop-impl kill never ran on this path. - LiveHelperChild RAII registry tracks one-shot helper PIDs; kill_live_helper_children() taskkills (tree) whatever is still live. - WorkspacePool::kill_all() drains and kills resident clients. - run_serve calls both after the graceful-shutdown select.
…the repo
When dotnet restore fails on SDK resolution (NETSDK1045-class: CLI SDKs
older than the repo TFM, or global.json unsatisfiable) scip-csharp now
retries the solution restore once with the newest VS MSBuild located via
vswhere - VS ships its own MSBuild + SDK targets independent of
C:\Program Files\dotnet, so it restores what the CLI cannot even
evaluate. SDK-resolution detection reads stdout AND stderr: NETSDK1045
prints to stdout on current dotnet hosts (verified live with a net99.0
probe). Bounded wait with the existing pending-marker/gated-exit
contract; on failure the per-project fallback still runs (mixed-TFM
recovery preserved).
The MSBuild instance choice for the workspace load is now
capability-aware too: when every CLI SDK instance is older than the
repo's raw-text TFM floor (max over all TFMs + global.json major), the
highest VS instance is registered instead - the SDK preference stands
everywhere else, including its net472-BuildHost-crash rationale.
Motivated by the 2026-10-15 HUSQ worktree incident (hollow 10.0.101 SDK
dir left the CLI blind to net10 while VS built fine).
Deliberate behavior change: SDK-instance pick is the HIGHEST qualifying
SDK (was first-enumerated, an undocumented order); single-SDK machines
unaffected.
Review-fixes:
- [Important] NETSDK1045/global.json detection read stderr only while the
trigger text prints to stdout on current hosts -> classify over both
streams; match current ('compatible .NET SDK') and legacy
('compatible installed .NET SDK') global.json wordings.
- [Important] multi-target floor took the FIRST TFM (net8.0;net10.0
floored at 8) -> take the max over all TFMs.
- [Important] inline 10_000 vswhere wait -> VsWhereWaitMs const.
- [Important] healthy-machine invariant weakened on multi-SDK machines ->
kept highest-qualifying (matches the original 'highest available
MSBuild' intent) and recorded the change in the branch plan.
17 tests over the fallback's pure logic: SDK-resolution detection pinned against the live host wordings (NETSDK1045 on stdout, current and legacy global.json phrasings; NU11xx feed/auth failures must NOT trigger), vswhere -find parsing, the capability-aware instance choice (qualifying SDK beats newer VS, floor-miss falls to VS, no-VS keeps SDK as last resort, highest sibling wins), and the repo TFM floor scan (multi-target max, project/global.json composition, parent-dir walk-up, null paths). The multi-target pin was defect-probed: first-TFM-only fails the floor assert as predicted. Also fixes the vswhere probe bound (round-1 review note): async drain before the bounded WaitForExit, and a KILL on timeout — vswhere is a local metadata probe, not a restore, so its death costs one failed probe; the kill also closes the pipes so the stdout read cannot block. Review-fixes: - [Important] WaitForExit timeout result was discarded and the stdout GetResult still blocked until process exit, so VsWhereWaitMs never actually bounded a hung vswhere -> kill(entireProcessTree) on timeout and return null.
CHANGELOG entry under the pending 1.5.31 heading, highlights line in AGENTS.develop.md, and the branch registered in the active-branches table. Plan stage 3 ticked in the branch-local AGENTS.md. Validation: dotnet build 0w/0e; dotnet test 99/99; cargo fmt --check clean; cargo clippy --all-targets -D warnings clean; cargo test --lib --bins all green (Rust side untouched by this branch).
The floor regex ^net(\d+)(?:\.|$) matched the extension-less .NET Framework spellings (net48 -> 48, net472 -> 472), so a solution with one net4x project floored at 48: no CLI SDK qualifies, and healthy SDK+VS machines flipped to the VS MSBuild instance for no reason (exposing the documented net472-BuildHost crash risk where the SDK path loaded those projects fine). The minor dot is now required (^net(\d+)\.) - every net-core TFM has one, no net4x spelling does. Pinned by NetFrameworkSpellingsDoNotRaiseTheFloor (net48 alone -> null, net48;net10.0 -> 10); defect-probed: the old regex fails the mixed case with a 48 floor. Final-review fix (round 1 finding). Round-2 re-review executed by the worker itself (reviewer subagent hit its 5h usage limit); scope was the fix diff only - verified: regex at HEAD, diff touches solely MsbuildRestore.cs + tests, 100/100 green, round-1 met-rows untouched.
…uild-fallback feat: VS-MSBuild restore fallback when the CLI SDK set cannot target the repo
… bad project= alias now returns a structured project_unresolved envelope with available_projects/groups instead of the bare "Unknown alias 'x'" string; + unit test (cargo test 812 pass, 1 pre-existing macOS /private symlink failure in db_discovery, unrelated) Signed-off-by: Tony Rose <174962249+tony-nexartis@users.noreply.github.com>
Merges upstream develop (143 commits, v1.5.3..v1.5.32) onto release/v1.5.2. Carries every upstream fix/feature since v1.5.2, including the quinn-proto GHSA-53rm-773f-4q8c security refresh (e61b2cd). Conflict resolution (2 files, both touched by our 2 fork-local commits): - src/mcp/tests.rs: keep BOTH tests (our project_unresolved classification test + upstream's single_index_status rebuild test). - helpers/csharp/RestorePolicy.cs: take upstream's evolved restore policy (FindWalkRoot repo-root walk, case-insensitive input enumeration, HasUsableAssets, ExtractRestoreErrors) and re-apply our fork delta (packages.lock.json as a restore input, 237a73c P2). Fork-local commits preserved: 237a73c (group= repo attribution, auto-merged with upstream a0c00b1) and 7b47a9b (project_unresolved NEE-P-CONSISTENT).
…2 catch-up evidence) Ranked catch-up list with per-commit SHA evidence, the fork-local deltas preserved through the sync, and the not-yet-in-develop perf branch as a follow-up. Answers the ToRFO codesearch audit mission step 2 durably.
The pre-push hook (scripts/qc.ps1) blocked EVERY push from a Mac. Two causes, both measured: 1. register_leaves_unix_path_untouched compared register()'s canonicalized output against the raw temp path. On macOS the temp dir lives under the /var -> /private/var symlink, so the two never matched. Compare against std::fs::canonicalize(repo) so the test pins its real intent (no Windows/MSYS rewrite on Unix), not the host's symlink layout. 2. `git push` exports GIT_DIR/GIT_WORK_TREE to the pre-push hook, and the QC gate runs `cargo test` inside it. Every git call that keys off an explicit path (-C dir / current_dir) was overridden by the ambient GIT_DIR and read the WRONG repo; worse, the tests' own `git commit` landed spurious 'initial' commits on the checkout under test. The class was already fixed at ONE site (src/symbols/mod.rs current_git_head); six others never got it. Scrub GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_OBJECT_DIRECTORY at all of them: db_discovery/repos.rs, watch/mod.rs, db_discovery/repos_tests.rs, tests/helpers/mod.rs, cli/mod.rs, serve/mod.rs. Measured before/after: qc.ps1 FAILED (7 lib tests red under the hook env, and the hook committed into the repo under test); after, 870/870 lib tests pass under a poisoned GIT_DIR and qc.ps1 reports ALL CHECKS PASSED. Follow-up: fold the seven inline scrubs into one shared git-command helper.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 803fa32472
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Perf A/B — v1.5.2 (baseline) vs v1.5.32 (this PR)Same corpus (29
No regression. The catch-up is at parity within noise. The cold path (~0.9 s/file) is dominated by per-file embedding + cold model init on a saturated CPU; warm reindex and query are sub-100 ms. Caveat / follow-up: a rigorous A/B needs a quiet host. A first-class |
CodeQL "1 new high alert" — disposition: FALSE POSITIVE on pre-existing upstream code (not introduced here)Alert: Why it is a false positive: the SHA-256 there is not password storage. It builds two fixed-length 32-byte digests so the API-key comparison is constant-time and length-independent (see the function's own doc comment). The secret is a high-entropy API key, never stored as a hash for offline cracking. CodeQL's taint heuristic classified the compared strings as a password. Not introduced by this PR: Not a merge blocker: Recommended hardening (deferred, not done in this lane): replace the hand-rolled SHA-256-digest compare with the idiomatic |
- limits: cancellation-aware memory-admission wait (abort at once, release the slot) - opencode plugin: gate the startup /healthz probe on health.enabled; honour scope.enabled for the scope prelude - serve: constant-time byte-fold API-key compare (no SHA-256; clears rust/weak-sensitive-data-hashing false positive) - tests: limits cancellation test + smoke guards (health probe, scope prelude) Signed-off-by: Test User <test@example.com>
|
Sync catch-up fix-forward — head Cleared the gates blocking this PR:
Supersedes #4 (this branch contains #4 head |
|
Merge routed — blocked on a stale local console release (no bypass used). The gated verb accepts The ceremony is blocked because this cubicle's console runs a pinned release (
Remedy (one desk step): rebuild this cubicle's console onto HEAD, then re-run the ceremony.
No |
|
Merge blocked — ROUTE with a named gate. This PR is green and merge-ready (CI green on The gated master-base mergebot path (
Root cause: Fix (owner: Catch-up verdict: this PR carries 143 upstream commits ( |
|
Merge routed — blocked on a The gated master-base mergebot (
It then refuses at the mesh-effect admission:
Root cause (measured, not inferred)
Rebuild-dist retry does not apply
Fix (owner:
|
⛔ Merge blocked — fleet control-plane contract gap (not a codesearch defect)The gated merge verb ( This PR is otherwise merge-ready: all required checks green ( The gate (named)Repo: Contrast: Origin: SI Owner action
Routed by session |
Summary
Catch our fork up to upstream
flupkede/codesearchdevelop= v1.5.32 (143 commits, v1.5.3 → v1.5.32), then harden the fork's own dev loop.Base branch is
master; head isrelease/v1.5.32(satisfiesprotect-master.yml).Why
The fork was pinned at upstream
masterv1.5.2 (release/v1.5.2, PR #4). Upstream develops ondevelop, which is 30 versions / 143 commits ahead. The fleet installs this fork's pinned binary (nexartis-ozzydev/mcp/upstream-forks.json,pin_version: v1.5.2), so it has been running v1.5.2 while upstream shipped a security refresh and a long list of index-integrity fixes.Ranked catch-up (per-commit SHA evidence in
docs/UPSTREAM-SYNC.md)Tier 0 — security
e61b2cdquinn-proto → 0.11.19 (AikidoAIKIDO-2026-404995, GHSA-53rm-773f-4q8c).Tier 1 — index integrity / data-loss class
f149091stop wiping index caches on every binary swap; harden the transient FTS redrive241e641persist file metadata per index batch, atomically120169bchunk-store records stamped with the builder version, wiped on mismatch3807739retry the transient FTS commit race; keep failed adds registered43d0cc4,6120429symbol pairing / noise / FTS scope / atomic save / rebuild guard85e0a4efile-meta invalidation viawarn_print, notprintlnTier 2 — tool correctness / status honesty / C# helper robustness — 17 fixes incl.
93090a3(find→find_impact position round-trip),07cdddb+abb792c(MCP session negotiation keepsresultType),b4614bd+2cb4976(symbol-index status), the0e87917..7ce51e5status-while-rebuilding group,cc46d3f(Razor FindReferencesAsync),bfcae91(backslash project paths),d2cf10a(kill helper children on shutdown),4574c23(VS-MSBuild restore fallback).Tier 3 — features —
235f593(run C# source generators before symbol collection), the#225restore-gate group.Tier 4 — chore/deps/CI — tree-sitter-php 0.25.1, cargo/actions bumps,
92d8876.Not yet in
develop(follow-up):upstream/perf/csharp-refs-at-index(fa10be7, 5 perf commits) — land when upstream merges it.Hardening (this fork)
fix(git): scrub ambientGIT_*at every repo-discovery git call. The class was already fixed at ONE site (src/symbols/mod.rs); six others never got it. Measured impact:scripts/qc.ps1(the pre-push gate) runscargo testwhilegit pushhasGIT_DIR/GIT_WORK_TREEset for the hook, so the git-shelling tests read the wrong repo — and the tests' owngit commitlanded spuriousinitialcommits on the checkout under test. Sites fixed:db_discovery/repos.rs,watch/mod.rs,db_discovery/repos_tests.rs,tests/helpers/mod.rs,cli/mod.rs,serve/mod.rs.test(db_discovery): macOS-correctregister_leaves_unix_path_untouched—register()canonicalizes and macOS temp dirs live under the/var → /private/varsymlink, so the test failed on every Mac and blocked every push via the QC gate.Measured before/after:
qc.ps1FAILED (7 lib tests red under the hook env) → ALL CHECKS PASSED;cargo test --lib1 pre-existing failure → 870 passed / 0 failed (also green under a deliberately poisonedGIT_DIR).Conflict resolution
Two files, both touched by the fork's two local commits:
src/mcp/tests.rs— keep both tests.helpers/csharp/RestorePolicy.cs— take upstream's evolved policy and re-apply the fork delta (packages.lock.jsonas a restore input).Fork-local deltas preserved
237a73c—group=hits attributed to their owning repo at creation (chunk ids are store-local and collide across repos; upstreama0c00b1keys au32map, which is what this replaces). Reviewer: this is the one intentional 96-line divergence from upstream on a hot file — worth a second look.7b47a9b— structuredproject_unresolvedrefusal (NEE-P-CONSISTENT).Review items
search.rsfork delta vs upstreama0c00b1(above).docs/UPSTREAM-SYNC.mdis a fork-local file upstream lacks — intended as a living sync ledger.GIT_*scrubs into one shared git-command helper.pin_versioninnexartis-ozzydev/mcp/upstream-forks.jsonshould be bumped (and the fork release asset republished) once this lands, so the fleet runs v1.5.32.Verification
cargo check --all-targetsclean;cargo fmt --checkclean;cargo clippy --all-targets -- -D warningsclean.cargo test --lib: 870 passed / 0 failed (13 ignored); integration + doc-tests pass.scripts/qc.ps1 -Fast: ALL CHECKS PASSED.