Repository navigation
fix(core): indexing and vector sync fixes from contributor reports - #1759
Merged
Merged
Conversation
…ports - #1743: bm reindex on a keyword-only host printed None through Rich escape() and crashed; it now reports embeddings as skipped. - #1742: an unreadable created/modified frontmatter value fell the whole note out of the index; it now falls back to the file timestamp with a warning. reindex also counts and lists files that failed to index and exits 1. - #1741: a full reindex republishes unchanged notes under the same relation generation, so cleanup never removed a relation the current parser no longer produces. Cleanup now deletes same-generation rows the publication did not write. - #1734: SQLite applied a prepare plan read before a newer sync finished, publishing an obsolete chunk as ready. It now re-plans under its prepare write lock, as external indexes already do. - #1733: an older completed vector sync cleared a newer pass's deferred-shard marker. The clear now applies only to markers set before the pass started. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EQPZkbnuxxtTEJoNJCkt45 Signed-off-by: phernandez <paul@basicmachines.co>
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. |
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.
Summary
Fixes five bugs reported by @beru-ant-king against current
main, for v0.24.0. Each report came with a deterministic reproducer, and each fix has a regression test.Closes #1733, closes #1734, closes #1741, closes #1742, closes #1743.
#1743:
bm reindexcrashes on a keyword-only hostA regression from this cycle (f756dc5). When sqlite-vec cannot load, the vector rebuild returns
vector_index=None, and the reindex summary passed it to Rich'sescape(). That raisedTypeErrorfrombm reindex,bm project indexandbm project add. The summary now printsEmbeddings skipped: semantic search is unavailable on this host, so search is keyword-only.#1742: one bad frontmatter timestamp keeps a note out of the index
created/modifiedvalue, such as{{date}}, freeform text or an import's date format, raised and failed the whole file. The timestamp is metadata about the note, so the parser now uses the file-time fallback and logs a warning with the path. Missing andnullvalues already fell back the same way.bm reindexprinted the number of files queued as "indexed" and exited 0 even when files failed. It now printsN indexed, M failedand lists up to 10 failed files with their reason. The project line readsincomplete, and the command exits 1 so scripts notice.#1741: a full reindex keeps relations the parser no longer produces
A full reindex of unchanged files republishes relations under the same generation (
db_version). Cleanup deleted only rows from older generations, and the upsert skips rows at the same generation. A relation the current parser drops therefore survived everybm reindex --fulluntil the note was edited.v0.24.0's inline-code wikilink fix (#1332) drops exactly this kind of relation, so upgraders would keep false edges and relation search rows.
Cleanup now gets the
(relation_type, to_name)set the publication wrote. It also deletes this entity's rows at the current generation that are not in that set, in id batches under the existing generation fence.#1734: a stale SQLite prepare publishes an obsolete chunk
Vector prepare reads the source and manifest in a shared session, then applies the plan in a write transaction. Only external indexes re-read and re-planned after taking their lock. On SQLite, a plan read before a newer sync of the same note finished could still be applied, which added an obsolete chunk as a ready vector.
SQLite already serializes prepare writes behind
_sqlite_prepare_write_lock. It now re-reads and re-plans under that lock too, through a new_replans_prepare_under_write_lock()hook. Built-in Postgres takes no lock at that point, so a re-read there would only add round trips; it keeps its current behavior.#1733: an older vector sync clears a newer deferred-shard marker
record_entity_vector_deferralsclearedvector_sync_deferred_atfor completed entities without any condition. An older pass that finished after a newer pass deferred the same entity erased the only signal that the newer source still had shards to embed.Each pass now records when it started, and the clear applies only to markers that are null or older than that time. Marking an entity unfinished is unchanged, because over-marking is safe: the next pass clears it. The clear binds
NULLin place of:deferred_at, so every marker statement stays within the existing bind-parameter bound.Verification
Each reporter's reproducer was run against
mainand against this branch:main--assert-cleanup)Hiddenedge survivesVisibleremainsRegression tests:
test_reindex_on_keyword_only_host_reports_skipped_embeddingstest_reindex_reports_failed_files_and_exits_onetest_parse_invalid_canonical_timestamp_falls_back_to_file_time(replaces the test that required a raise)test_same_generation_republish_removes_relations_it_no_longer_writestest_sqlite_stale_prefetched_prepare_does_not_publish_an_obsolete_chunk, which fails onmainwith 2 manifest rowstest_an_older_pass_does_not_clear_a_newer_deferral_markerTest plan
just fast-checkjust test-unit-sqlite: 8316 passed, 59 skippedjust test-int-sqlite: 712 passed, 15 skipped🤖 Generated with Claude Code
https://claude.ai/code/session_01EQPZkbnuxxtTEJoNJCkt45