Skip to content

[BUG] No local counterpart to bm cloud prune: entities for newly-.bmignore'd files persist, and reindex --full re-creates them #1254

Description

@EricXu-0805

Summary

bm cloud prune (#1061, closing #1032) gave cloud tenants a way to remove content that was
added to .bmignore after it had already synced. Local projects have no equivalent. Adding a
pattern to .bmignore stops future indexing, but entities already in the database stay, remain
searchable, and basic-memory reindex --full re-creates any that were removed by hand.

The remediation story is now asymmetric: the cloud gap described in #1032 is closed, the same gap
on local is not, and the local case is the one a user hits first.

Where

src/basic_memory/ignore_utils.py exposes should_ignore_path() / filter_files(), and these
are applied when scanning for files. src/basic_memory/indexing/batch_indexer.py on main
(401ed6bf) contains no reference to ignore rules at all — nothing checks the current patterns
against entities that are already known, so a reindex has no reason to drop them.

Reproduce

# with a local project that has been synced at least once
echo 'notes/scratch.md' >> ~/.basic-memory/.bmignore
basic-memory reindex --full -p <project>
basic-memory search "<a phrase unique to scratch.md>" -p <project>   # still returns it

Deleting the row by hand and reindexing brings it back.

Why manual cleanup is not a reasonable workaround

Removing an entity fully means touching three places — entity (which cascades to relation),
search_index, and the sqlite-vec vector tables. search_vector_embeddings is a vec0 virtual
table, so the stock sqlite3 CLI cannot open the database at all; it needs the sqlite_vec
extension loaded from the app's own Python. The join key is
search_vector_embeddings.rowid == search_vector_chunks.id, which is not evident from the schema.
If hand-cleanup is meant to be the supported path, that alone is worth documenting.

Suggested fix

Either have the local reindex apply current ignore rules to existing entities and delete the ones
that now match, or add a local bm prune mirroring bm cloud prune so both backends have the
same remediation. The cloud implementation notes in #1061 flag this as a destructive behavior
change — the same caution would apply locally, which argues for the explicit command over silent
deletion during reindex.

Verification

Reproduced on 0.22.1 (current PyPI release, macOS 15, Python 3.14, local file backend). The
main claims above come from reading ignore_utils.py, batch_indexer.py, and the CLI command
tree at 401ed6bf — there is no prune outside cli/commands/cloud/. I have not run main, so
treat the local-gap claim as "not fixed as far as the source shows" rather than a live test.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions