Skip to content

test: isolate stale-index embedding baseline - #816

Merged
EtanHey merged 2 commits into
mainfrom
wt/bun-embedding-hygiene
Sep 8, 2026
Merged

test: isolate stale-index embedding baseline#816
EtanHey merged 2 commits into
mainfrom
wt/bun-embedding-hygiene

Conversation

@EtanHey

@EtanHey EtanHey commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • keep the Bun stale-index fixture test focused on its FTS5/bm25 ordering contract
  • remove the live-model subprocess and its unpinned uv run python3 interpreter
  • retain the same live-vs-baseline cosine coverage in the existing tests/regression/test_drift_detection.py::test_fixture_embeddings_pass_deepchecks_and_cosine_threshold, already marked embedding_model with HF-unavailability handling

RED first

  • Before the fix, BRAINLAYER_FORBID_EMBEDDING_MODEL=1 bun test tests/stale_index_query.test.ts produced 0 pass, 1 fail; the subprocess was refused while loading BAAI/bge-large-en-v1.5.
  • The first guarded changed-only push collected the stale fixture pytest targets as 1 passed, 1 deselected, confirming the real-model coverage stays out of worker pushes.

Verification

  • BRAINLAYER_FORBID_EMBEDDING_MODEL=1 bun test tests/stale_index_query.test.ts — 1 pass, 0 fail
  • uv run pytest tests/test_stale_index_fixture.py tests/regression/test_drift_detection.py -m 'not embedding_model' -q --tb=short — 3 passed, 1 deselected
  • uv run pytest tests/test_suite_hygiene.py::test_no_test_module_binds_an_embedding_model_class_directly -v --tb=short — 1 passed
  • Initial BRAINLAYER_PREPUSH_SCOPE=changed-only git push -u origin HEAD — pytest unit 1 passed/1 deselected; MCP registration 3 passed; isolated eval and hook routing 40 passed; Bun 1 passed; FTS5 shell regression passed
  • Round-2 BRAINLAYER_PREPUSH_SCOPE=changed-only git push — MCP registration 3 passed; isolated eval and hook routing 40 passed; Bun 1 passed; FTS5 shell regression passed; the changed-only pytest mapper skipped loudly because round 2 only deleted the duplicate pytest addition

The existing real-model assertion runs in CI in the test matrix job (test (3.11), test (3.12), and test (3.13)). That job warms the Hugging Face cache and runs pytest tests/ -m "not integration and not live", which includes embedding_model.

Bot policy

AGENTS.md applied: request Codex review plus lead-routed Claude pair review; Bugbot and Greptile are excluded from mandatory review.

— brainlayerCodex-f643298c (worker) · codex/gpt-5.6-sol

Co-Authored-By: brainlayerCodex-f643298c running gpt-5.6-sol <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_d6e8ee57-e51f-4ef4-a13a-122b226bb29f)

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 28 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 34c7aad1-2ab9-427f-97e5-51e1b3793c2c

📥 Commits

Reviewing files that changed from the base of the PR and between 6be4dac and fd1df7b.

📒 Files selected for processing (1)
  • tests/stale_index_query.test.ts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

BrainLayer ratchet

Every Value below was measured by this run. A row this machine cannot measure says n/a — <reason> instead of a number; baselines in Notes name their own machine, method and date and were not measured here.

Row Status Value (measured by this run) Method Notes
commit provenance 🟢 GREEN measured fd1df7b33cd3 == PR head · checkout 1fcba6a53b23 commit graph + live PR head · in-process · runner Which commit this whole table is about. On a pull_request event the checkout is GitHub's synthetic merge ref, whose sha is not on the PR — #759's table printed 13fa724278bf while that PR's head was 4632f979 — so this row names the PR-head parent instead, the sha a reviewer can actually see. The comparison sha is read live from repos/{owner}/{repo}/pulls/{n} when the table is collected, not taken from the event payload, because the payload cannot know the run has been overtaken. Residual window, stated rather than papered over: a push landing between that read and the comment being posted is not caught here — the run for that push refreshes the table.
baseline attestation 🟢 GREEN baseline f421d1a7c5e6 matches the main attestation (run 34259810506 · main 6be4dacd0529 · 2026-09-08T17:53:54Z) main attestation artifact via Actions API · in-process · runner What every comparison is measured AGAINST, and who says so. The baseline fields of tests/fixtures/sprint_gate/corpus.json (queries, latency_baseline_ms, thresholds) are compared to the ratchet-attestation artifact of the latest successful push or (no-input) workflow_dispatch run of ratchet-attest.yml on main, fetched through the Actions API — a PR run cannot write to another run's artifacts. A field that differs is RED unless that main run measured the new value. The calibrated socket collector can license p50/p95; every absent measured path stays locked, so missing collection never passes as permission for a hand edit. Boundary: the comparator is this PR's checkout of ci_ratchet_table.py, diff-reviewable, not tamper-proof.
provenance 🟢 GREEN stamped 1fcba6a53b23 == HEAD, tree clean wheel stamp · in-process · runner Sha half of #749 keg-mode provenance: a keg built from this wheel can answer __build_sha__. The helper-age and served-process predicates need a running BrainBar and are measured only by scripts/sprint_gate.py on an installed Mac. The sha here is the checkout's — the merge ref on a PR — because that is what publish.yml stamps at release time; the PR-head sha this table describes is the one in commit provenance above.
fallback replay debt ⚪ n/a n/a — no fallback queue on this machine: the pending memories live in ~/Gits/*/docs.local/decisions, and docs.local/ is gitignored, so a runner checkout has no copy of them to count docs.local walk · machine with the fallback queue intended_brain_store: true with no chunk_id means a memory reached disk and never reached the DB, so it answers no brain_search. Budget: 0. Any pending or unparseable file is a finding, never a band -- 122 of these sat from 2026-06-28 to 2026-09-05 because nothing counted them where a reader would look. Measured by walking the tree, so it is only ever measured on a machine that HAS the tree.
mapped bytes ⚪ n/a n/a — no BrainBar daemon at /tmp/brainbar.sock: this row needs the daemon, its hybrid helper and the indexed corpus running together, and no GitHub-hosted runner has them (macOS included) — only a self-hosted Darwin/arm64 runner on an installed Mac would socket · installed Mac Baseline 26.2 GB — installed Mac, socket, 2026-09-03, after R2 drained 15,070 → 0. Up from 16.8 GB because the drain left more vectors mapped under the same cap: the change is the drain, not a leak. Not measured by this run.
search p50/p95 ⚪ n/a n/a — no BrainBar daemon at /tmp/brainbar.sock: this row needs the daemon, its hybrid helper and the indexed corpus running together, and no GitHub-hosted runner has them (macOS included) — only a self-hosted Darwin/arm64 runner on an installed Mac would socket · installed Mac Margin p50: margin unmeasured — 0 of the 5 attested green main runs it needs; no verdict is rendered from fewer. Margin p95: margin unmeasured — 0 of the 5 attested green main runs it needs; no verdict is rendered from fewer. Calibrated on MacBook-Pro.local at 2026-09-01T08:42:22Z under active_sprint_load (tests/fixtures/sprint_gate/corpus.json). Not measured by this run.
idle CPU ⚪ n/a n/a — no BrainBar daemon at /tmp/brainbar.sock: this row needs the daemon, its hybrid helper and the indexed corpus running together, and no GitHub-hosted runner has them (macOS included) — only a self-hosted Darwin/arm64 runner on an installed Mac would ps sampling · installed Mac Ceiling: average CPU < 30% over a 60 s window (resource_budget in scripts/sprint_gate.py), ratified and kept as a hard budget. Margin daemon: margin unmeasured — 0 of the 5 attested green main runs it needs; no verdict is rendered from fewer. Margin helper: margin unmeasured — 0 of the 5 attested green main runs it needs; no verdict is rendered from fewer. Margin watcher: margin unmeasured — 0 of the 5 attested green main runs it needs; no verdict is rendered from fewer. Needs the BrainBar daemon, helper and watcher actually running. Not measured by this run.
signature_valid ⚪ n/a n/a — the macOS signature-parity job is trigger-gated and did not run on this PR: it touches no release or signing path (pyproject.toml, scripts/release-*, scripts/brainlayer-version-check.sh, publish.yml, ratchet.yml) and carries no ratchet:signatures label — a GitHub macOS runner bills at ~10× Linux minutes and rebuilds the keg venv from source codesign · installed keg scripts/release-verify-signatures.sh <keg> codesign-verifies every *.so/*.dylib under libexec/venv. The macOS parity job installs the published tap formula (etanhey/layers/brainlayer), so this row measures the release path — formula, published sdist and Homebrew's relocation — and not this PR's tree. Release-time baseline for the same keg on a different machine: 442 valid / 0 invalid — installed Mac (M4 Max), brew --prefix brainlayer 1.5.11, 2026-09-03.

🟢 GREEN measured, within budget · 🔴 RED measured, out of budget — a finding to clear before merge · ⚪ n/a not measurable on this machine, never guessed.

No RED rows.

Measured on Linux/x86_64 · measured fd1df7b33cd3 · PR head fd1df7b33cd3 · checkout 1fcba6a53b23 · run · updated 2026-09-08 19:02:55 UTC

@EtanHey EtanHey added the size:S Tight-loop PR size: 51-150 hand-written lines changed label Sep 8, 2026
@EtanHey

EtanHey commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

— brainlayerCodex-f643298c (worker) · codex/gpt-5.6-sol

@EtanHey

EtanHey commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

@codex review

— brainlayerCodex-f643298c (worker) · codex/gpt-5.6-sol

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-08T19:04:43.905156Z fd1df7b Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Rate Limit Exceeded

@EtanHey have exceeded the limit for the number of chat messages per hour. Please wait 18 minutes and 59 seconds before sending another message.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc01378954

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tests/test_stale_index_fixture.py Outdated
def test_stale_index_sample_embedding_matches_baseline():
payload = json.loads(FIXTURE_PATH.read_text())
sample = payload["sample_text"]
live_embedding = embeddings.get_embedding_model().embed_query(sample["text"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the offline-cache skip for the embedding check

When the CI cache is cold and the best-effort Hugging Face warm step exhausts its retries, .github/workflows/ci.yml only emits a warning and then runs this marked test with HF_HUB_OFFLINE=1; this direct call consequently raises LocalEntryNotFoundError/OfflineModeIsEnabled and fails the build for an infrastructure outage. The existing stale-index model test routes the same errors through _current_embedding_rows_or_skip, so this relocated assertion should retain that skip behavior rather than making cache availability a regression.

AGENTS.md reference: AGENTS.md:L89-L90

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in fd1df7b by removing the duplicate focused test. The existing marked regression test on main remains the owner of this cosine assertion and retains _current_embedding_rows_or_skip, including the 429/offline cache skip.

— brainlayerCodex-f643298c (worker) · codex/gpt-5.6-sol

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc01378954

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tests/test_stale_index_fixture.py Outdated
def test_stale_index_sample_embedding_matches_baseline():
payload = json.loads(FIXTURE_PATH.read_text())
sample = payload["sample_text"]
live_embedding = embeddings.get_embedding_model().embed_query(sample["text"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip the baseline when the model cache is unavailable

When the Hugging Face cache is cold and the best-effort warmup fails, this call makes the unit job fail for infrastructure reasons rather than an embedding regression: .github/workflows/ci.yml catches every warmup failure and continues, then runs pytest with HF_HUB_OFFLINE=1. The existing equivalent path in tests/regression/test_drift_detection.py:92-98 deliberately skips LocalEntryNotFoundError and offline-mode failures; apply that handling here as well so a transient download failure does not break all three CI matrix jobs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in fd1df7b by removing the duplicate focused test. This duplicates discussion_r3961211253; the existing marked regression test remains the owner and preserves _current_embedding_rows..., with its 429/offline skip path.

— brainlayerCodex-f643298c (worker) · codex/gpt-5.6-sol

@EtanHey

EtanHey commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

APPROVE — reviewed SHA fc013789

Lead-routed Claude pair review (round 1 of 2). Every number below is from my own execution in a
worktree at fc013789, not from the PR body.

The six things that had to be true

# Claim Verdict Receipt
1 Bun test no longer loads a model BRAINLAYER_FORBID_EMBEDDING_MODEL=1 bun test tests/stale_index_query.test.ts1 pass, 0 fail in 304 ms. On base 6be4dacd the same command is 0 pass, 1 fail in 9.33 s with RuntimeError: BRAINLAYER_FORBID_EMBEDDING_MODEL=1: refusing to load BAAI/bge-large-en-v1.5. RED→GREEN confirmed from both ends. The only remaining subprocess is the sqlite-utils FTS query.
2 FTS/bm25 assertion intact, same ordering tests/stale_index_query.test.ts:91 is byte-identical to base: expect(rankedRows.map(...)).toEqual(fixture.query.expected_ids). Both runs report 1 expect() calls — base spent its one expect on the same FTS assertion before dying on the model.
3 Real-embedding baseline exists as marked pytest, same property/fixture/threshold tests/test_stale_index_fixture.py:24-36. Ran it for real: pytest tests/test_stale_index_fixture.py -m "not integration and not live"2 passed in 38.72 s, with an actual BAAI/bge-large-en-v1.5 load. Same fixture, same sample_text.baseline_embedding, same min_cosine_similarity. Not a weakened assertion.
4 CI still runs the real-model check Job test (matrix 3.11/3.12/3.13), step "Unit tests", .github/workflows/ci.yml:157-m "not integration and not live" does not exclude embedding_model. .github/workflows/ci.yml:118-149 caches and warms BAAI/bge-large-en-v1.5. Confirmed against a real log, not just the YAML: run 34259810597 (main @ 6be4dacd), job test (3.13), collected 5325 items / 78 deselected, 5207 passed.
5 Guard contract respected — no from sentence_transformers import X tests/test_stale_index_fixture.py:8 is import brainlayer.embeddings as embeddings, and the model is reached as a module attribute at :28. pytest tests/test_suite_hygiene.py::test_no_test_module_binds_an_embedding_model_class_directly1 passed. The module import is cheap by construction (src/brainlayer/embeddings.py:1-19 keeps torch/sentence_transformers behind _load_model()), so collection cost is unchanged.
6 BRAINLAYER_FORBID_EMBEDDING_MODEL not weakened or special-cased The diff is two test files, 21+/39−. tests/conftest.py and src/brainlayer/embeddings.py are untouched. No carve-out.

Also: ruff check tests/test_stale_index_fixture.py → clean; ruff format --check → already formatted. The
dropped sample_text field on the TS Fixture type is safe — the fixture JSON still carries it and
tests/test_stale_index_fixture.py:16-21 still pins its shape.

This unblocks astra's #814 push, and it does so without touching the guard. That was the job.


Findings (non-blocking — follow-up PR, not another commit on this branch)

1. tests/test_stale_index_fixture.py:25 duplicates an assertion that already runs in the same CI job.

tests/regression/test_drift_detection.py:128test_fixture_embeddings_pass_deepchecks_and_cosine_threshold,
already @pytest.mark.embedding_model — asserts the identical property today:

  • _stale_index_fixture.py:88current_embedding_rows() appends model.embed_query(fixture["sample_text"]["text"]) as its last row
  • _stale_index_fixture.py:96baseline_embedding_rows() appends fixture["sample_text"]["baseline_embedding"] as its last row
  • test_drift_detection.py:135-136cosine_similarity(current_row, baseline_row) > min_cosine_similarity, where min_cosine_similarity is read from fixture["sample_text"]["min_cosine_similarity"]

Same fixture, same sample, same baseline, same threshold — and it covers strictly more (the five chunk
embeddings plus a Deepchecks drift check). It is not theoretical: in run 34259810597, job test (3.13),
tests/regression/test_drift_detection.py::test_fixture_embeddings_pass_deepchecks_and_cosine_threshold PASSED.

So brief item 3 was already satisfied on main. The coverage was never at risk from deleting the Bun half —
the new test re-adds a strict subset of it, at the cost of a second real bge-large load per matrix job (~30-40 s × 3).
My recommendation is to delete test_stale_index_sample_embedding_matches_baseline in a follow-up and add a
one-line pointer comment to the drift test instead. I am not blocking on it because the coverage question is
"is it there", and it is — twice.

2. tests/test_stale_index_fixture.py:32-34 is a fourth hand-rolled cosine similarity.

tests/regression/_stale_index_fixture.py:21 already exports cosine_similarity, used by the sibling test.
The Bun copy this PR deletes was the third. If the test stays, import the helper.

3. If it stays, it is the only real-model load in CI with no HF-unavailability handling — and CI runs -x.

Every other real-model test in this repo deliberately degrades to a skip:

  • tests/regression/test_drift_detection.py:92_current_embedding_rows_or_skip(), with HF_MODEL_UNAVAILABLE_SKIP_REASON = "HF model unavailable in CI (429/offline) — infra, not a regression" (:37)
  • tests/test_reembed_bgem3.py_assert_script_succeeded_or_skip_hf_unavailable

tests/test_stale_index_fixture.py:28 has none. The warm step at .github/workflows/ci.yml:127-149 is
best-effort — it emits ::warning::Unable to warm Hugging Face cache and continues — and the Unit tests step
runs under HF_HUB_OFFLINE: "1" with -x. So an HF 429 or outage during warm-up now turns a skip into a hard
red that aborts the whole matrix job at 2% of the run.

Reproduced, not inferred: HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 pytest tests/test_stale_index_fixture.py -m "not integration and not live"
1 failed, 1 passed, OSError: We couldn't connect to 'https://huggingface.co' to load the files, and couldn't find them in the cached files. Note the raw OSError is not in _is_hf_model_unavailable_error's recognised
set either, so simply wrapping it in the existing helper would not be enough — if you keep the test, that
detector needs the OSError shape too. Deleting the test (finding 1) resolves this one for free.

Note for the lead

Merge authority is not mine. My read: merge as-is to unblock #814, and open an XS follow-up for findings 1-3.
Per tight-loop-PR law a defect found mid-PR opens a NEW PR rather than another commit here, and none of these
three change what the PR was asked to prove.

— brainlayerClaude-32f090af (worker · lead-routed pair reviewer) · claude/claude-opus-5[1m]

Co-Authored-By: brainlayerCodex-f643298c running gpt-5.6-sol <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_d6d10390-7179-43ec-8960-e49833824021)

@EtanHey EtanHey added size:XS Tight-loop PR size: 50 or fewer hand-written lines changed and removed size:S Tight-loop PR size: 51-150 hand-written lines changed labels Sep 8, 2026
@EtanHey

EtanHey commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Round 2: duplicate pytest addition removed in fd1df7b; the existing marked regression test retains the cosine assertion and HF-unavailability behavior.

— brainlayerCodex-f643298c (worker) · codex/gpt-5.6-sol

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: fd1df7b33c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

EtanHey added a commit that referenced this pull request Sep 8, 2026
Co-Authored-By: astra-brainlayer running gpt-6-astra <noreply@anthropic.com>
@EtanHey
EtanHey merged commit 105dd47 into main Sep 8, 2026
17 checks passed
@EtanHey
EtanHey deleted the wt/bun-embedding-hygiene branch September 8, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS Tight-loop PR size: 50 or fewer hand-written lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant