memini-ai v0.7.7 Audit Report¶
Date: 2026-07-10 Auditor: boomerang-architect Scope: Correctness (Area A) + Documentation (Area B)
Executive Summary¶
v0.7.7's core correctness is solid — auto_detect_model, has_dim_mismatch, BM25 guards, multi-model RRF, and model aliases all work as designed with no latent bugs found. The tests (test_manager_dim_checks.py) are comprehensive and correctly exercise the new behavior. However, the documentation has critical gaps: the README's "Enabling Multi-Model" example (lines 73-79) omits MEMINI_EMBEDDING_DIM=1024, which will cause a dim-mismatch degradation to text-only search in v0.7.7's lenient mode — a user following this example verbatim will get a silently degraded server. The .env.example is missing all 5 v0.7.7 env vars. The README architecture tree is missing 20+ source files. The CHANGELOG v0.7.6 entry inaccurately claims enabled_models was reduced to 1 entry when the code has 2. The upgrading-embeddings.md guide references a non-existent pip extra (sentence-transformers[gpu]). The migration script exists but at a different path than documented. These are all doc bugs, not code bugs — the code is correct, but users following the docs will hit avoidable problems.
Severity Legend¶
- CRITICAL — blocks user, breaks correctness, security risk
- HIGH — significant bug, confusing behavior
- MEDIUM — suboptimal, future-proofing
- LOW — nitpick, style
Findings (sorted by severity)¶
[CRITICAL] B1.1: README "Enabling Multi-Model" example omits MEMINI_EMBEDDING_DIM=1024¶
- Location:
README.md:73-79 - Description: The example shows
export MEMINI_MODEL_NAME=BAAI/bge-m3+export MEMINI_ENABLE_RRF=truebut does NOT includeexport MEMINI_EMBEDDING_DIM=1024. BGE-M3 produces 1024-dim vectors. The defaultembedding_dimis 384. In v0.7.7's lenient mode, this mismatch logs a warning and degrades to text-only search — vector search is silently disabled. A user following this example verbatim will get a degraded server with no vector search capability. - Reproduction: Set
MEMINI_MODEL_NAME=BAAI/bge-m3, leaveMEMINI_EMBEDDING_DIMunset (defaults to 384). Start server. Callget_status→embeddingDimMismatch: true. Allquery_memoriescalls fall back to TEXT_ONLY. - Proposed fix: Add
export MEMINI_EMBEDDING_DIM=1024to the example block. Also add a note that the dim must match the model. - v0.7.8 priority: Must-fix
[HIGH] B3.1: .env.example missing all v0.7.7 env vars¶
- Location:
.env.example(72 lines) - Description: The
.env.examplefile documents v0.7.0 dual-model RRF vars (EMBEDDING_MODE,ELEVATE_ENABLED,RRF_K,AUTO_EXTRACT_LOG_DIR,AUTO_EXTRACT_INTERVAL_SECONDS) but is missing all 5 v0.7.7 env vars:MEMINI_STRICT_EMBEDDING_DIM,MEMINI_AUTO_DETECT_MODEL,MEMINI_MODEL_NAME,MEMINI_ENABLE_RRF,RRF_TOP_K_PER_MODEL,MEMINI_ENABLED_MODELS. Users who copy.env.exampleto.envwill not discover these critical configuration options. - Reproduction:
grep -c "MEMINI_STRICT_EMBEDDING_DIM\|MEMINI_AUTO_DETECT_MODEL\|MEMINI_MODEL_NAME\|MEMINI_ENABLE_RRF\|RRF_TOP_K_PER_MODEL\|MEMINI_ENABLED_MODELS" .env.example→ 0 matches. - Proposed fix: Add a "v0.7.7+ Model Selection" section to
.env.exampledocumenting all 6 new env vars with defaults and descriptions. - v0.7.8 priority: Must-fix
[HIGH] B1.2: README env var table missing v0.7.7 vars¶
- Location:
README.md:122-130 - Description: The "Core Settings" env var table lists
MEMINI_EMBEDDING_DIMbut does not listMEMINI_STRICT_EMBEDDING_DIM,MEMINI_AUTO_DETECT_MODEL,MEMINI_MODEL_NAME,MEMINI_ENABLE_RRF,RRF_TOP_K_PER_MODEL, orMEMINI_ENABLED_MODELS. These are all user-facing configuration options introduced in v0.7.5-v0.7.7. - Proposed fix: Add rows for all 6 vars to the Core Settings table.
- v0.7.8 priority: Must-fix
[HIGH] B4.1: upgrading-embeddings.md references non-existent pip extra¶
- Location:
docs/upgrading-embeddings.md:48-51 - Description: Step 2 says
uv pip install sentence-transformers[gpu]/pip install sentence-transformers[gpu]. Thepyproject.tomlhas no[gpu]optional-dependency group. Thesentence-transformerspackage on PyPI does not ship a[gpu]extra either. This command will fail or silently install the base package without GPU acceleration. The correct approach is to ensuretorchwith CUDA support is installed (which is already a core dependency inpyproject.toml). - Reproduction:
pip install sentence-transformers[gpu]→ "WARNING: sentence-transformers does not provide the extra 'gpu'" - Proposed fix: Replace with
pip install torch --index-url https://download.pytorch.org/whl/cu118(or the appropriate CUDA version) and note thattorch>=2.0is already a core dependency. - v0.7.8 priority: Must-fix
[HIGH] B4.2: Migration script path in docs doesn't match actual location¶
- Location:
docs/upgrading-embeddings.md:56andREADME.md:35 - Description: Both docs reference
archives/memini-embedding-migration-2026-07-10/migrate_minilm_to_bge_m3.pyas if it's undermemini-ai-dev/. The actual file is at/home/jcharles/Projects/MCP-Servers/archives/memini-embedding-migration-2026-07-10/migrate_minilm_to_bge_m3.py— one level up in the workspace root. Running the command frommemini-ai-dev/will fail with "No such file or directory." - Reproduction:
cd memini-ai-dev && python archives/memini-embedding-migration-2026-07-10/migrate_minilm_to_bge_m3.py→ FileNotFoundError. - Proposed fix: Either move the archives directory into
memini-ai-dev/or update the docs to use the absolute path or../archives/.... - v0.7.8 priority: Must-fix
[MEDIUM] B1.3: README architecture tree missing 20+ source files¶
- Location:
README.md:322-352 - Description: The architecture tree shows 6 top-level modules (
config.py,server.py,api/,memory/,postgres/,model/,indexer/,utils/) but is missing:llm/(5 files),audit/(2 files),graph.py,rate_limiter.py,thought_chains.py,dialectic.py,multi_peer.py,entity_extractor.py,knowledge_graph.py,decay.py,user_model.py,tiered_loader.py,precompress.py,extractor.py,trust_engine.py,main.py,__init__.py. Also missing from subdirs:memory/rrf.py,memory/merger.py,indexer/snapshot.py,indexer/pause_controller.py,indexer/constants.py,utils/sanitizer.py. - Proposed fix: Regenerate the tree from the actual file listing (53 source files in
src/memini_ai/). - v0.7.8 priority: Should-fix
[MEDIUM] B1.4: README tool count says "35+" but actual count is 52¶
- Location:
README.md:207-208 - Description: The heading says "MCP Tools (35+)" but
server.py::_setup_toolsregisters 52 tools. The "35+" is technically correct (52 ≥ 35) but misleadingly low. The tool listing in the README (lines 212-252) only shows ~28 tools grouped by category, missing ~24 tools. - Proposed fix: Update to "MCP Tools (52)" and add the missing tools to the categorized listing.
- v0.7.8 priority: Should-fix
[MEDIUM] B1.5: README Docker Compose uses pgvector/pgvector:pg16 but user runs timescaledb-ha:pg18¶
- Location:
README.md:287 - Description: The Docker Compose example uses
image: pgvector/pgvector:pg16. The user's actual deployment usesdocker.io/timescale/timescaledb-ha:pg18(per AGENTS.md Session 12/40 review notes). This is misleading for users who want to match the production setup. Thepgvector/pgvector:pg16image works fine for development but doesn't include TimescaleDB. - Proposed fix: Add a note that the example uses a minimal pgvector image for development; for production with TimescaleDB, use
timescale/timescaledb-ha:pg18. - v0.7.8 priority: Should-fix
[MEDIUM] B2.1: CHANGELOG v0.7.6 inaccurately claims enabled_models reduced to 1 entry¶
- Location:
CHANGELOG.md:55 - Description: The v0.7.6 CHANGELOG says: "
enabled_modelsdefault inconfig.pyreduced to['BAAI/bge-m3'](was['BAAI/bge-m3', 'BAAI/bge-large-en-v1.5'])." The actual code inconfig.py:63-69has['all-MiniLM-L6-v2', 'BAAI/bge-m3']— 2 entries, not 1. The CHANGELOG is wrong: it was reduced from 3 to 2 (removing BGE-Large), not from 2 to 1. - Proposed fix: Correct to: "reduced to
['all-MiniLM-L6-v2', 'BAAI/bge-m3'](was['all-MiniLM-L6-v2', 'BAAI/bge-m3', 'BAAI/bge-large-en-v1.5'])." - v0.7.8 priority: Should-fix
[MEDIUM] B5.1: AGENTS.md missing v0.7.7 review note¶
- Location:
AGENTS.md:83-98(Review Notes section) - Description: The latest review note is for Session 40 (v0.7.6). There is no Session 41 or v0.7.7 entry. The env var table (lines 67-82) is also missing v0.7.7 vars (
MEMINI_STRICT_EMBEDDING_DIM,MEMINI_AUTO_DETECT_MODEL,MEMINI_MODEL_NAME,MEMINI_ENABLE_RRF). - Proposed fix: Add a Session 41 review note documenting v0.7.7 changes. Add the 4 new env vars to the table.
- v0.7.8 priority: Should-fix
[MEDIUM] B5.2: HANDOFF.md missing Session 41 entry¶
- Location:
HANDOFF.md(latest entry is Session 40) - Description: No Session 41 handoff entry exists. The file ends at Session 40 (v0.7.6). v0.7.7 was released without a handoff entry documenting the auto-detect, lenient dim-mismatch, and new env vars.
- Proposed fix: Add a Session 41 entry documenting v0.7.7 changes, process state, and quick-resume commands.
- v0.7.8 priority: Should-fix
[LOW] B1.6: README "Multi-Model RRF" section doesn't mention model_name-driven selection¶
- Location:
README.md:26-67 - Description: The Multi-Model RRF section describes
EMBEDDING_MODEdispatch (cpu/auto/gpu) but doesn't mention that model selection is now driven byMEMINI_MODEL_NAME(v0.7.5+). The table at line 30-33 correctly lists model names and aliases, but the mode dispatch table (lines 39-43) doesn't explain howMEMINI_MODEL_NAMEinteracts withEMBEDDING_MODE. - Proposed fix: Add a sentence explaining that
MEMINI_MODEL_NAMEselects which model is loaded, andEMBEDDING_MODEcontrols how writes/queries are dispatched. - v0.7.8 priority: Nice-to-have
[LOW] B4.3: Migration script uses deprecated get_sentence_embedding_dimension¶
- Location:
archives/memini-embedding-migration-2026-07-10/migrate_minilm_to_bge_m3.py:108 - Description: Line 108 calls
model.get_sentence_embedding_dimension()which is deprecated in sentence-transformers 3.x and emits a FutureWarning. The v0.7.7 codebase already migrated toget_embedding_dimension()(seetest_manager_dim_checks.py::TestDeprecationFix). The migration script should use the new method name for consistency. - Proposed fix: Change
get_sentence_embedding_dimension()→get_embedding_dimension(). - v0.7.8 priority: Nice-to-have
Area A: Correctness¶
A1: auto_detect_model (model/manager.py:313-344)¶
Verdict: CORRECT — no bugs found.
- Fires at the right time: Called from
server.py::_init_memory_system(line 210) aftersystem.initialize()succeeds and before any MCP tools are served. This is the correct place — the DB is connected, the memory count is available, and no user operations have run yet. - Correctly detects "new deployment": Checks
memory_count == 0ANDconfig.model_name == DEFAULT_MODEL_NAME("all-MiniLM-L6-v2") ANDconfig.auto_detect_model == True. All three conditions must be true. When they are, setsconfig.model_name = BGE_M3_MODEL_IDandconfig.embedding_dim = BGE_M3_DIM, then returns True. - Correctly does NOT fire for "existing user": When
memory_count > 0, returns False immediately (line 328-330). The user's existing MiniLM setup is preserved. - Correctly does NOT fire when user explicitly set model: When
config.model_name != DEFAULT_MODEL_NAME, returns False (line 325-327). The user's explicit choice is respected. - No race condition:
auto_detect_modelis a@classmethodthat reads config and memory_count as arguments. It's called synchronously within_init_memory_systembefore the server starts accepting MCP requests. There is no concurrent access to the config during this window. TheModelManagersingleton is not yet acquired at this point. - Re-initialization after override: When
auto_detect_modelreturns True,server.py:211-218closes the old MemorySystem, creates a new one, and re-initializes. This ensures the newmodel_nameandembedding_dimare picked up by the freshModelManagersingleton on firstacquire(). - Tests cover all 4 branches:
test_empty_db_selects_bge_m3,test_populated_db_keeps_minilm,test_user_set_model_name_respected,test_auto_detect_disabled_returns_false— all passing.
A2: has_dim_mismatch + add_memory + query_memories dim-mismatch path¶
Verdict: CORRECT — no bugs found.
has_dim_mismatchis set correctly: Inmanager.py::_load_model(lines 224-260), whenactual_dim != self._embedding_dimandstrict_embedding_dim=False(default),self._has_dim_mismatch = Trueis set and a warning is logged. The model is kept loaded (soget_statuscan report metadata).add_memorycatchesEmbeddingDimMismatchError: Insystem.py::add_memory(lines 176-195),generate_embeddingis called in a try/except. WhenEmbeddingDimMismatchErroris raised (fromembeddings.py:74-80), the exception is caught, a warning is logged, andinput.vector = Noneis set. The memory is then stored with a NULL embedding. The text content is fully preserved.- Text is preserved: The
add_memoryflow continues past the except block to line 198 (input.content_hash = hash_content(input.text)) and then to the mode dispatch. The memory is written to the DB withembedding=NULLbuttextintact. query_memoriesforces TEXT_ONLY: Insystem.py::query_memories(lines 402-404),manager.has_dim_mismatchis checked andoptions.strategy = SearchStrategy.TEXT_ONLYis set. This overrides any caller-specified strategy, ensuring vector search (which would fail or return garbage) is never attempted.- Tests cover both paths:
test_lenient_mismatch_does_not_raiseverifies the model loads with_has_dim_mismatch=True.test_strict_mismatch_raises_runtime_errorverifies the opt-in crash behavior.
A3: BM25 guards (memory/search.py)¶
Verdict: CORRECT — no bugs found.
_build_bm25_index(lines 48-83): Filters out empty/whitespace-only text before building the index (line 63). If no valid memories remain, sets_bm25_index = Noneand returns (lines 65-68). Additionally filters out empty token lists (lines 72-74) — handles the edge case of text that is all punctuation with no whitespace splits. If no valid token pairs remain, sets index to None (lines 76-79).text_only_search(lines 265-334): Guards against empty/whitespace query at line 280-281 (returns[]). Guards against unbuilt index at line 285-286 (returns[]). Guards against all-punctuation query tokens at line 289-291 (returns[]). All three guards are correct and prevent theZeroDivisionErrorthat would occur inBM25Okapi.get_scores()with empty input.text_search_collection(lines 439-496): Same three guards: empty query (line 456-457), empty entries (line 462-463), empty-text entries filtered (line 466-467), empty token lists (line 471-473), empty query tokens (line 479-481). All correct.- No edge cases where real results are incorrectly dropped: The guards only filter out degenerate inputs (empty strings, all-whitespace, all-punctuation). Valid text with actual words always passes through. The
_tokenizemethod (line 35-46) usestext.lower().split()which correctly handles mixed content.
A4: Multi-model RRF (memory/rrf.py + system.py)¶
Verdict: CORRECT — no bugs found.
COLUMN_TO_MODEL(rrf.py:123-126): Maps"embedding"→"sentence-transformers/all-MiniLM-L6-v2"and"embedding_bge_m3"→"BAAI/bge-m3". Both are full HuggingFace names that matchModelManager.MODEL_DIMSkeys. This is correct — the v0.7.5 bug (short name'all-MiniLM-L6-v2'not recognized byModelManager) is fixed.- RRF fusion for memories in BOTH columns: In
rrf_search(lines 135-250), each model's column is searched independently. Results are accumulated inall_resultsdict keyed by memory ID. Therrf_scoreis the sum of1/(k+rank)contributions from each column. A memory appearing in both columns gets contributions from both — this is the intended boost behavior. - Memories in only one column: If a memory only has an
embedding(MiniLM) but noembedding_bge_m3, it only gets a contribution from the MiniLM search. The BGE-M3 search won't find it (the SQL filtersWHERE embedding_bge_m3 IS NOT NULL). This is correct — the memory participates with whatever vector spaces it has. - k=60 used consistently:
rrf_searchdefaultk=60(line 139)._query_dual_model_rrfusesself._resolved_rrf_kwhich defaults toget_config().rrf_k= 60._rrf_fusioninsearch.pyalso defaults tok=60. All consistent. MODEL_TO_DIM(rrf.py:129-132): Correctly maps MiniLM → 384, BGE-M3 → 1024. Mirrorsmodel/manager.py::MODEL_DIMS._query_dual_model_rrf(system.py:436-517): Correctly over-fetches (fetch_k = max(options.top_k * 2, options.top_k + 5)) to give RRF enough material. Propagatesthresholdandexact_searchto the 384-side (v0.7.3 fix). Falls back to 384-only if the DB lacks 1024 support. Re-hydrates from 384 entries (preferred) with 1024 fallback.
A5: Model name aliases (model/manager.py)¶
Verdict: CORRECT — no bugs found.
- Alias map location:
_MODEL_ALIASESdict at lines 67-74. 'minilm'is a valid alias: Maps toMINILM_MODEL_ID="sentence-transformers/all-MiniLM-L6-v2". Verified.'bge-m3'is a valid alias: Maps toBGE_M3_MODEL_ID="BAAI/bge-m3". Verified.'all-MiniLM-L6-v2'is the canonical form: The full HF name"sentence-transformers/all-MiniLM-L6-v2"is the canonical form. The short name"all-MiniLM-L6-v2"is also accepted as an alias (line 68). Both resolve to the same canonical ID.- Aliases are case-sensitive:
_normalize_model_name(line 77-86) doeskey = name.strip()but no.lower(). The dict keys are all lowercase. So"BGE-M3"would NOT match"bge-m3"— it would be passed through as an unknown custom model name. This is a potential footgun but not a bug (the behavior is consistent and documented). - Other aliases:
"minilm-l6-v2"→ MiniLM (line 70). The full HF names are also self-aliases (lines 72-73) so passing the canonical name works as a no-op normalization. - Unknown names pass through:
_normalize_model_namereturns the input unchanged if not found in_MODEL_ALIASES(line 86). This allows custom HuggingFace models. The_load_modelmethod will attempt to load it viaSentenceTransformer(model_id).
Area B: Documentation¶
B1: README.md accuracy¶
| Claim | Location | Verdict | Detail |
|---|---|---|---|
'minilm' and 'bge-m3' are valid aliases | Line 32-33 | ✅ CORRECT | Both in _MODEL_ALIASES |
Example config: MEMINI_MODEL_NAME=BAAI/bge-m3 + MEMINI_ENABLE_RRF=true | Lines 73-79 | ❌ CRITICAL BUG | Missing MEMINI_EMBEDDING_DIM=1024 — causes dim mismatch |
| Env var table lists core settings | Lines 122-130 | ❌ INCOMPLETE | Missing 6 v0.7.7 vars |
| "MCP Tools (35+)" | Line 207-208 | ⚠️ OUTDATED | Actual count is 52 |
| Multi-Model RRF section | Lines 26-67 | ⚠️ PARTIAL | Doesn't explain model_name vs embedding_mode interaction |
Docker Compose pgvector/pgvector:pg16 | Line 287 | ⚠️ MISLEADING | User runs timescaledb-ha:pg18 |
| Architecture tree | Lines 322-352 | ❌ INCOMPLETE | Missing 20+ source files |
EMBEDDING_MODE table | Lines 39-43 | ✅ CORRECT | Mode dispatch is accurate |
B2: CHANGELOG.md¶
- v0.7.7 entries: Well-formatted, accurate. The "Changed" and "Added" sections correctly describe auto-detect, lenient dim-mismatch, and new env vars.
- v0.7.6 entry: One inaccuracy — claims
enabled_modelsreduced to['BAAI/bge-m3']but code has['all-MiniLM-L6-v2', 'BAAI/bge-m3'](2 entries, not 1). See finding B2.1. - Format consistency: All entries follow the Keep a Changelog format with
## [version] - dateheaders and### Changed/Added/Removed/Fixedsubsections. Consistent across all versions.
B3: .env.example¶
- Exists: Yes (72 lines).
- Missing v0.7.7 vars:
MEMINI_STRICT_EMBEDDING_DIM,MEMINI_AUTO_DETECT_MODEL,MEMINI_MODEL_NAME,MEMINI_ENABLE_RRF,RRF_TOP_K_PER_MODEL,MEMINI_ENABLED_MODELS. See finding B3.1. - Existing v0.7.0 vars:
EMBEDDING_MODE,ELEVATE_ENABLED,RRF_K,AUTO_EXTRACT_LOG_DIR,AUTO_EXTRACT_INTERVAL_SECONDS— all present and correctly documented.
B4: docs/upgrading-embeddings.md¶
- 4-step recipe accuracy:
- Step 1 (backup):
pg_dumpcommand is correct for the user's PG version (PG16+). Uses-Fc(custom format) which is the recommended format for pg_restore. - Step 2 (install deps):
sentence-transformers[gpu]is NOT a valid extra. See finding B4.1. - Step 3 (run migration): Script path is wrong relative to
memini-ai-dev/. See finding B4.2. The script itself is correct and idempotent (verified by reading the source — it skips rows that already haveembedding_bge_m3set, uses transactions, writes a backup before any modifications). - Step 4 (update env vars): Correctly includes
MEMINI_EMBEDDING_DIM=1024alongsideMEMINI_MODEL_NAME=BAAI/bge-m3. This is the correct config — unlike the README example which omits the dim. - Rollback instructions: Correct. Unsetting
MEMINI_MODEL_NAMEand settingMEMINI_EMBEDDING_DIM=384restores MiniLM. The original 384-dim vectors are preserved. - FAQ: Accurate. The dim-mismatch FAQ correctly describes v0.7.7's lenient behavior.
B5: Other docs¶
- AGENTS.md: Session 40 review note (line 85) reflects v0.7.6, not v0.7.7. Missing v0.7.7 entry. Env var table (lines 67-82) missing v0.7.7 vars. See finding B5.1.
- HANDOFF.md: Latest entry is Session 40 (v0.7.6). No Session 41 entry for v0.7.7. See finding B5.2.
- CONTEXT.md: Not audited (not in the file list provided, but likely needs a v0.7.7 section).
Recommendations for v0.7.8¶
| # | Fix | Priority | Effort | Files |
|---|---|---|---|---|
| 1 | Add MEMINI_EMBEDDING_DIM=1024 to README "Enabling Multi-Model" example | Must-fix | 1 line | README.md:77 |
| 2 | Add all 6 v0.7.7 env vars to .env.example | Must-fix | ~15 lines | .env.example |
| 3 | Add v0.7.7 env vars to README Core Settings table | Must-fix | ~6 rows | README.md:122-130 |
| 4 | Fix sentence-transformers[gpu] reference in upgrading-embeddings.md | Must-fix | 2 lines | docs/upgrading-embeddings.md:48-51 |
| 5 | Fix migration script path in docs (or move archives into memini-ai-dev/) | Must-fix | 2 lines or mv | docs/upgrading-embeddings.md:56, README.md:35 |
| 6 | Regenerate README architecture tree from actual file listing | Should-fix | ~30 lines | README.md:322-352 |
| 7 | Update README tool count to 52 and add missing tools | Should-fix | ~30 lines | README.md:207-252 |
| 8 | Fix CHANGELOG v0.7.6 enabled_models claim (2 entries, not 1) | Should-fix | 1 line | CHANGELOG.md:55 |
| 9 | Add v0.7.7 review note to AGENTS.md + update env var table | Should-fix | ~15 lines | AGENTS.md |
| 10 | Add Session 41 handoff entry for v0.7.7 | Should-fix | ~30 lines | HANDOFF.md |
| 11 | Add note about Docker image difference (pgvector vs timescaledb) | Should-fix | 2 lines | README.md:287 |
| 12 | Fix deprecated get_sentence_embedding_dimension in migration script | Nice-to-have | 1 line | archives/.../migrate_minilm_to_bge_m3.py:108 |
| 13 | Add model_name vs embedding_mode interaction explanation to README | Nice-to-have | ~3 lines | README.md:39-43 |
Total estimated effort: ~2 hours for all Must-fix items, ~4 hours for all items.