Repository navigation
feat(search): MSCODEBASE_DENSE_OFF kill-switch + EXP-28 dense-off A/B - #75
Merged
Merged
Conversation
Phase 3 as a measurement, not a deletion. Flag skips the whole dense stage (query embedding + LanceDB vector search); default OFF so the prod path is byte-identical. EXP-28: frozen 33-case panel (sha256 f31e594e, union of three pre-existing frozen sets, frozen before the run), 2 runs per arm, same session and index. A dense ON: hit1 11/33, hit5 15/33, 0 errors, mean 3359/3534ms. B dense OFF: hit1 12/33, hit5 16/33, 0 errors, mean 3163/2492ms. Per case 2 better / 1 worse / 30 same; speedup mean-of-means 18% but per-run spread 5.8-29.5%. Verdict: H1/H2/H6 refuted as expected, H4 confirmed (0 errors), H3 PARTIAL, H5 untested (no symbol/NL labelling in the panel). Harness proven by a _vector_search_async call counter 1 -> 0 with the embedder alive. Key finding: of 52 table-API call sites in 13 src files only 5 are vector search; bm25.py:93 builds BM25 from table.to_pandas(), so LanceDB is the chunk primary store, not a vector index. Dense removal NOT recommended; the flag stays as an operational kill-switch. KNOWN_ISSUES untouched (foreign session edits it) - proposals in experiments/e28_denseoff/PENDING_LEDGER.md. Tests: 3 flag tests + adjacent suites 29/29, ruff clean.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…up claim EXP-28 left H5 untested: no symbol-vs-NL labelling, and it could not be added after the run (freeze-before-look). This experiment freezes the labelling rule first (snake_case | CamelCase | pathy | single token -> symbolic 15 / NL 18, sha256 7639ba1b), then runs both arms twice. A dense ON : NL 3/18 (16.7%), symbolic 8/15 (53.3%), 0 errors, mean 2559/2555ms B dense OFF: NL 5/18 (27.8%), symbolic 7/15 (46.7%), 0 errors, mean 2375/2354ms NL 2 better / 0 worse; symbolic 0 better / 1 worse (TR-P2). Speedup stable at 7.2% / 7.9%. Verdicts: H1 CONFIRMED (symbolic loses exactly 1 of 15, within the declared tolerance), H2 REFUTED as expected (NL is better), H3 REFUTED as expected (7.5%, below 15%), H4 CONFIRMED (0 errors), H5 CONFIRMED against expectation (two NL cases improved). CORRECTED: EXP-28 published an 18.0% speedup; two runs here show 7.2% and 7.9%. The old number was inflated by one noisy run (21% spread vs 0.2% here). Logged as a new entry with the supersede reference, not a silent edit. Harness incident: the first run from the worktree printed hit1=0/33 with rc=0 and 167ms - a silent zero on an empty index (index is per-project-path). Guard added: all-empty exits 2, and the project root is an explicit manifest parameter. That run is not counted. Phase 3 decision unchanged: no observed harm from dense, no proven gain (1-2 of 33 cases is noise), LanceDB stays as chunk primary store, the flag stays a kill-switch.
This was referenced Oct 10, 2026
ManSio
added a commit
that referenced
this pull request
Oct 10, 2026
The workflow listened only to pull_request -> main, so a stacked PR (base = feature branch) produced no CI run at all. That is exactly what happened to phases 2 and 3 of the migration: PR #74 and #75 were merged with a local clean-state run as the only evidence, and their status stayed unverifiable on GitHub. pull_request now also targets feat/**, exp/**, fix/**, chore/**. push stays main-only so one revision is never built twice. Job list unchanged (test, clean-state, manifest-parity, transport-equiv-e2e, docker-build); workflow yaml parses. Co-authored-by: MSCodeBase Agent <mscodebase@intelligence.local>
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.
What
Phase 3 of the migration, as a measurement — not a deletion. Adds
MSCODEBASE_DENSE_OFF(default OFF) which skips the whole dense stage (query embedding + LanceDB vector search), plus the EXP-28 A/B that decides whether removal is ever justified, and EXP-29 which closes the one hypothesis EXP-28 had to leave open.Verdict: dense removal NOT recommended. Quality is unchanged (net +1 of 33 = noise), speed is a stable ~7.5%, and — the real reason — LanceDB is not a vector index here but the chunk primary store.
EXP-28 — dense on vs dense off
Panel
experiments/e28_denseoff/frozen/queries.jsonl, 33 cases, sha256f31e594e…278cc8, union of three pre-existing frozen sets (4A f5, token_reduction, e2e_quality_search::CASES), deduped by gold file. 6 hypotheses frozen, 3 of them written to be expected to fail. 2 runs per arm, same session, same index; only env differs.Per-case: 2 better / 1 worse / 30 same. H1/H2/H6 refuted (as intended), H4 confirmed, H3 PARTIAL, H5 untested — the panel had no symbol/NL labelling, and labelling cannot be added after the run (§17).
Harness proven, not assumed: a
_vector_search_asynccall counter goes 1 → 0 between arms with the embedder alive. Without that check the A/B would have been empty.EXP-29 — the symbol/NL split that closes H5
Labelling rule frozen first (
e29_label.py:symbolic := snake_case | CamelCase | pathy(:: / slash / .method()) | single token), written into the frozen panel (queries_labeled.jsonl, sha2567639ba1b…, symbolic 15 / NL 18), then both arms twice.NL: 2 better / 0 worse. Symbolic: 0 better / 1 worse (
TR-P2). H1 CONFIRMED (symbolic loses exactly 1 of 15 — inside the declared tolerance), H2/H3 refuted as expected, H4 CONFIRMED, H5 CONFIRMED against expectation.Mechanism: both improvements are NL queries where dense pulled top-1 into a document (
docs/adr/0003-verify-on-read.md,src/core/multi_project_searcher.py). The single regression is lexical (docs/zh/SEARCH_PIPELINE.mdinstead ofengine.py). Subset sums reproduce EXP-28 exactly (A 8+3=11, B 7+5=12) — same panel split, not an independent experiment.CORRECTED (no silent edit)
EXP-28 published an 18.0% speedup. EXP-29's two runs give 7.2% and 7.9% — the old figure was inflated by one noisy run (21% spread vs 0.2% here). EXP-28's H3=PARTIAL verdict stands, but the 18% number is retired; the live figure is 7.5%. Logged as a new entry with a supersede reference, per §11/§19.11.
The finding that matters more than the numbers
Of 52 table-API call sites in 13
src/files, only 5 are vector search. The rest is chunk storage:bm25.py:93builds the BM25 index fromtable.to_pandas(),db_writer/indexer/indexer_tablewrite and delete chunks,file_move_manager+index_guarddoversion()/where()scans for meta-patching and repair. Deleting LanceDB would be a store migration, not a cleanup.Harness incident (caught, fixed)
The first EXP-29 run from the worktree printed
hit1=0/33withrc=0in 167 ms — a silent zero on an empty index, because the index is per-project-path and the worktree has none. Guard added: all-empty input exits 2 with an explicit message, and the project root is an explicit manifest parameter. That run is not counted. Separately,test_no_personal_pathscaught a machine-specific absolute path leaking intoEXPERIMENTS_LOG.md— replaced with a placeholder before commit.Safety
engine.py:936).experiments/e28_denseoff/PENDING_LEDGER.md.Verification
Clean state at
3813561:Passed: 2052 / Failed: 0—CLEAN STATE VERIFICATION: PASSED.Notes
CIworkflow (it listens topull_request → mainonly); the clean-state run above is the equivalent evidence.