Goal: every endpoint and every Streamlit tab must work in a 2-minute
hackathon demo without requiring the demoer to fetch external data.
Code fixes:
- src/api/routes.py + src/agents/tools.py: fix two stale references —
bbb_model.load (not load_model) and bbb_model.predict_with_proba (not
predict_one); also corrects the agent-side default BBB artifact path
from .pkl to .joblib so the auto-resolve in adjust_drug_dose works.
- src/api/routes.py: replace hard-coded _AGENT_DEFAULT_MODEL = google/
gemini-2.0-flash-exp:free (now 404 on OpenRouter) with a fallback
chain probed at orchestrator-build time. Picks the first model that
returns a non-404/429 ping. Override via NEUROBRIDGE_AGENT_MODEL
(single id) or NEUROBRIDGE_AGENT_MODEL_CHAIN (csv).
- src/llm/explainer.py: prepend openai/gpt-oss-20b:free (verified 2026-
05-02) to the explainer fallback chain so /explain/* doesn't fall
back to the deterministic template when free-tier ids churn.
- src/frontend/app.py: drop the en…
Adds the only legitimate BBB <-> MRI bridge in the platform — researcher
lane only. Fusion engine still excludes BBB as a diagnostic modality.
Modules:
- src/models/bbb_permeability_map.py: scalar BBB leakage score in [0,1]
with two modes. heuristic_proxy (default) reuses the 2D resnet18
Alzheimer classifier and computes 1 - P(NonDemented). dce_onnx loads
a real 4D DCE-MRI ONNX model from BBB_PERMEABILITY_DCE_PATH and
averages a normalised Ktrans map; raises a clear FileNotFoundError
with contract documentation when no artifact exists.
- src/research/drug_dose_adjuster.py: pure-function dose revision keyed
on (BBB intact?, drug BBB-permeable?). Permeable drugs see an
aggressive linear cut floored at 30%; non-permeable drugs see a mild
cut floored at 60%; intact BBB returns baseline unchanged. Unknown
drug permeability is treated as permeable (safer). Rationale always
includes the 'research suggestion, not medical advice' disclaimer.
API:
- POST /predict/bbb_permea…
feat(eeg,frontend): EEG fusion-flow test + Streamlit EEG form + real-artifact sanity
- tests/fusion/test_eeg_modality_flow.py: end-to-end EEG -> fusion `eeg`
modality flow (alzheimers feature spike lifts AD score; control profile
doesn't inflate it).
- tests/models/test_eeg_model_real.py: skip-if-absent sanity for the real
EEG joblib; runs automatically once the file lands at the canonical path.
- src/frontend/app.py: doctor MRI tab grows an EEG predict form
(comma-separated features) calling POST /predict/eeg. 503 surfaces as a
human-readable warning instead of a stack trace.
feat(api): add POST /predict/eeg route (stub-able for demo)
All 5 tests pass on existing code — the bare-directory-without-slash case
already works because Path.exists() resolves relative to cwd, which
monkeypatch.chdir() sets correctly in the test. No routing.py change needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
test(mri/model): drop redundant caplog.at_level (direct handler attach is the actual mechanism)
Replace top-level _execute_bbb/eeg/mri functions with closure factories
(_make_bbb/eeg/mri_executor) that (a) accept processed_dir so output paths
are no longer hard-coded relative strings, and (b) catch HTTPException from
route calls and re-raise as ValueError with a clean message.
Add build_default_tools(processed_dir=Path("data/processed")) keyword arg
for backwards-compatible parameterization.
Add 4 new tests: processed_dir threading, retrieve short-circuit with no
index, backwards-compat default, and HTTPException → ValueError translation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TDD implementation: tests/rag/test_embed.py exercises Embedder.encode() with
batch processing, empty lists, dimension validation, and semantic similarity
guarantees. Model lazy-loads on first call (no torch dependency, ~33MB ONNX).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Without this, the regression-detection branch in the live integration
test was silently dead — caplog never received explainer log records
(propagate=False on src.core.logger.get_logger), so every template
fallback hit pytest.fail instead of pytest.skip.
test(llm): tighten live integration test (slow marker, log-gated skip, on-topic assertion)
- Dockerfile.hf: python:3.12-slim base, system deps for RDKit /
nibabel / MNE, pip install requirements.txt, BUILD-TIME train of
the BBB model artifact (RUN python -m src.models.bbb_model) so the
first /predict/bbb call is instant on cold start.
- ENV defaults: DEPLOY_ENV=hf_spaces, NEUROBRIDGE_DISABLE_MLFLOW=1,
NEUROBRIDGE_DISABLE_LLM=1 (jury can opt back into LLM by setting
OPENROUTER_API_KEY in HF Space secrets and unsetting the disable
flag).
- supervisord.conf launches FastAPI on :8000 and Streamlit on :7860
in the same container; Streamlit exposes the HF public URL.
- .dockerignore trims build context (data/processed, mlruns, .venv,
tests/ except fixtures, docs).
- 2 new smoke tests: Dockerfile exists and contains expected stages.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>