omnidiag / docs /code_cleanup_report.md
yahyoha's picture
docs: add v2.0 roadmap, API docs, and .env.example
3e4503d
|
Raw
History Blame Contribute Delete
6.85 kB

Code Cleanup Report

Branch: feature/omni-platform-final
Date: 2026-06-28
Scope: Full codebase — frontend (React/JSX) + backend (Python/FastAPI)


Summary

Two analysis agents scanned the frontend and backend in parallel. All confirmed findings were then applied. A total of 19 files were modified across both layers.


Frontend Changes

1. Extracted shared ValueBadge component and SLIDER_CLASS constant

File: frontend/src/components/SchemaFieldFactory.jsx

The live-value badge (blue pill showing the current slider value) and the range <input type="range"> Tailwind class string were each copy-pasted verbatim between SliderField and NumberField.

Fix: Extracted a local ValueBadge({ value }) component and a SLIDER_CLASS string constant at the top of the file. Both field types now reference them.


2. Merged duplicate patient-reset useEffects

File: frontend/src/components/ClinicalEmrMode.jsx

Two useEffects both fired on selectedDisease change:

  • The first reset result/SHAP/error state and set selectedPatient from patients.length.
  • The second also called getPatientsForDisease and set selectedPatient, silently overwriting the first.

Fix: Merged into one useEffect on [selectedDisease] that calls getPatientsForDisease, sets the patient, and clears result state.


3. Removed redundant schema cache from DiseaseContext

File: frontend/src/context/DiseaseContext.jsx

The context maintained its own schemaCache state, a preFetchSchemas function (called eagerly on app load for all diseases), and a getSchemaForDisease method. None of these were consumed anywhere outside the context itself — useDiseaseSchema.js already handles schema fetching and caching independently via its own module-level Map.

Fix: Removed schemaCache state, preFetchSchemas, and getSchemaForDisease (~40 lines). The context now only manages disease selection and the available diseases list.


4. Moved @keyframes animations out of JSX

Files: frontend/src/components/FormSkeleton.jsx, frontend/src/components/VariableScalesModal.jsx
Target: frontend/src/index.css

Both components injected <style> tags with @keyframes blocks directly into the render output, re-injecting them into the document on every mount.

Fix: Moved shimmer and slideInRight animations to index.css. Components reference the class names only.


5. Removed dead exports

All of the following were exported but never imported anywhere in the codebase:

File Removed export
components/ErrorBoundary.jsx PredictionErrorBoundary
utils/schemaToZod.js validateFormData
utils/medicalDictionary.js isKnownMedicalTerm, getFullDictionary
mockPatients.js getAvailablePatientDiseases
hooks/useDiseaseSchema.js clearSchemaCache
components/SchemaFieldFactory.jsx componentIcons (defined, never referenced)

Backend Changes

6. Removed unused imports

File Removed
backend/model_loader.py import sys
backend/ensemble_loader.py import sys, Tuple and Callable from typing
backend/ensemble_loader.py import joblib as _joblib inside a for loop body (top-level joblib already imported)

7. Promoted deferred imports and loggers to module level

File: backend/main.py

Two route handlers (explain_disease, counterfactuals_disease) each executed import traceback as _tb and _log = logging.getLogger(...) on every request, deferring what should be module-level setup.

Fix:

  • Added import traceback at the top of the file.
  • Added _explain_log and _cf_log as module-level loggers alongside the existing log.
  • Removed the per-request imports and local _log assignments from both handlers.

8. Extracted _validate_patient_input helper

File: backend/main.py

The schema-validation block appeared identically in all three clinical route handlers (predict_disease, explain_disease, counterfactuals_disease):

schema = get_schema_for_disease(disease)
if schema:
    validated = schema(**patient)
    patient_data = validated.model_dump()
else:
    patient_data = patient

Fix: Extracted into _validate_patient_input(disease, patient) -> dict placed above the route definitions. All three handlers now call it with one line.


9. Extracted extract_token_from_request utility

File: backend/auth/jwt.py (new function)
Callers updated: backend/rate_limit.py, backend/middleware/audit.py

The cookie-then-header token extraction pattern was duplicated in both files (and had diverged slightly — different variable names, one used str | None, the other Optional[str]):

token = request.cookies.get("access_token")
if not token:
    auth = request.headers.get("Authorization", "")
    if auth.startswith("Bearer "):
        token = auth[7:]

Fix: Added extract_token_from_request(request: Request) -> Optional[str] to auth/jwt.py. Both callers import and use it.


10. Replaced print() with structured logging in router.py

File: backend/router.py

_load_all_configs() and _create_loader() used raw print() with emoji characters for status messages while the rest of the backend uses structured logging. This meant disease registration events were invisible to the configured log handler.

Fix: Added log = logging.getLogger("omnidiag.router") and replaced all 7 print() calls with log.info(), log.warning(), and log.error().


11. Upgraded Pydantic v1 class Config to v2 model_config

File: backend/schemas.py

HeartDiseaseInput and DiabetesInput both used the Pydantic v1 inner-class style:

class Config:
    json_schema_extra = { ... }

The rest of the backend (auth schemas, patient schemas) correctly uses Pydantic v2 style. Added ConfigDict to the import and replaced both with:

model_config = ConfigDict(json_schema_extra={ ... })

What Was Not Changed

The following duplication exists in backend/model_loader.py and backend/ensemble_loader.py and was identified but intentionally left alone:

Duplication Reason deferred
_apply_preprocessors — identical in both loaders Extracting a BaseModelLoader carries regression risk without tests
_get_feature_engineer / _engineer_features — copy-pasted Same as above
preprocessors property directory-scan loop Same as above
XGBoost base_score monkey-patch The two implementations have already diverged in detail; merging requires careful testing

These should be addressed as a dedicated refactor with integration tests in place.