Repository navigation
fix(code-index): a replaced engine no longer drops changes made since the last index run - #36
Merged
Merged
Conversation
…rded; keep a worktree's Zoekt snapshot in its own git dir Co-Authored-By: lemoncrow <302591943+lemoncrow-agent[bot]@users.noreply.github.com> LemonCrow-Session: s1 LemonCrow-Model: claude-opus-5-5
… tree as it is, not a stale baseline Addresses cr-70588 bha_p0_f0: a seeded worktree index the run declines to rebuild kept main's baseline, so autosync re-ran the index subprocess every tick. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-Authored-By: lemoncrow <302591943+lemoncrow-agent[bot]@users.noreply.github.com> LemonCrow-Session: 90d6a214-e1bd-4377-b621-531411b973b6 LemonCrow-Model: claude-opus-5-5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Code search stops seeing changes whenever its engine is replaced
The server's engine cache replaces a repo's
CodeContextEngineevery time the index version moves, and every re-index moves it. That's8ea1eb15, which stops a server from serving an old index version forever.The replacement engine's autosync loop took its starting point from the working tree as it found it. On its first tick it:
bootstrap/seed_signature).So any change made between the old engine's last check and the new engine's first tick was treated as already indexed. That includes a commit, a checkout, or a file written outside LemonCrow's
edit. It stayed out of the index until some later change happened to touch the same files.In a busy session the index version moves on almost every edit, so this happened constantly.
Found in practice. A worktree's index kept
engine.pyfrom Sep 22 through 7 HEAD moves and 3 days.code_searchcould not find constants that were plainly in the file, andcode_coverage_checkreported the file stale.Reproduced with the installed build. In a scratch repo I committed a new function while a loop searched every 2 s, as a working session does. The search went through
mcp_server._code_context_engine. The function never became searchable. The first search after the commit got a new engine. That engine's first tick recorded the post-commit HEAD and tree as its baseline and re-indexed nothing.Server restarts dropped changes the same way.
The fix: the index records what it covers
index_reporun stores the tree signature and HEAD it started from inengine_state, underautosync_baseline:<repo_id>. The key is per repo because several repos can share one database.no_indexed_baseline.Cost. Each index run now walks the source tree once more to compute the signature. That's 1.25 s on a 17.7k-file repo, against a full rebuild of about 19 s. For autosync re-indexes the total is unchanged, because the server no longer walks the tree after each one.
Also: Zoekt snapshot thread crash in linked worktrees
The crash:
ZoektIndexerstores its line-count snapshot at<repo>/.git/lemoncrow/zoekt_snapshot.jsonand reads HEAD from<repo>/.git/HEAD..gitis a file, so loading the snapshot raisedNotADirectoryError, which the loader didn't catch.lemoncrow-zoekt-snapshotthread and printed a traceback every time a worktree engine started.Nonein a worktree, so the saved snapshot could never be reused.The fix:
zoekt/server.py's existing_git_dirs()/_read_git_head(), which already handle linked worktrees..git/worktrees/<name>/, whichgit worktree removedeletes along with the worktree.OSErroras "no snapshot".Tests
New:
test_a_replacement_engine_indexes_a_commit_made_since_the_last_index_runtest_a_replacement_engine_indexes_a_working_tree_change_made_since_the_last_index_runtest_a_change_made_during_an_index_run_is_reindexed_by_the_next_checktest_an_index_without_a_recorded_baseline_is_reindexed_on_the_first_checktest_a_linked_worktree_keeps_its_snapshot_in_its_own_git_admin_directorytest_a_linked_worktree_snapshot_is_rebuilt_once_its_head_movesAll six fail against the old engine and indexer and pass with this change.
The existing autosync test probe now records a baseline the way a real index run does. The existing autosync tests pass unchanged (15 passed).
Other checks:
head_moved), and the commit became searchable.-m 'not slow'): 6972 passed, 9 failed, 2 errors.main: 5 intest_daemon_ownership_races.py,test_mcp_read_batch_budget,test_savings_credit, andtest_index_pool_does_not_fork_live_parent_state.test_edit_mcp_handler::test_workspace_root_edit_reindexes_once_after_the_responsefailed under parallel load and passes on its own.test_retriever_evalsetup errors come fromlemoncrow initin a worktree reading aprepare-commit-msghook that a concurrent test run had just written into the main checkout's shared.githooks. They pass on rerun, and this change doesn't touch that path.