Spaces:
Sleeping
Sleeping
docs: add CLAUDE.md with architecture and workflow notes
Browse filesCovers what needs several files to piece together: the two parallel Gradio
apps over one core, the message-flow state machine, the agent-name keys that
must stay in sync across four files, the three-tier prompt resolution, the two
separate verification subsystems, and the Gradio 6 arity/Radio traps this repo
has already hit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CLAUDE.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CLAUDE.md
|
| 2 |
+
|
| 3 |
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
| 4 |
+
|
| 5 |
+
## What this is
|
| 6 |
+
|
| 7 |
+
A Gradio web app: a **Medical Assistant** chat that runs a **background spiritual-distress classifier** on every patient message, plus a **verification/review workflow** so clinicians and chaplains can grade the classifier's output and export the results. Python 3.14, Gradio 6.1.0, LLM calls to Google Gemini and Anthropic Claude.
|
| 8 |
+
|
| 9 |
+
## Commands
|
| 10 |
+
|
| 11 |
+
```bash
|
| 12 |
+
# Setup
|
| 13 |
+
python3 -m venv .venv && source .venv/bin/activate
|
| 14 |
+
pip install -r requirements.txt
|
| 15 |
+
# .env must contain GEMINI_API_KEY and/or ANTHROPIC_API_KEY
|
| 16 |
+
|
| 17 |
+
# Run β full interface (Chat, Verification, Model Settings, Edit Prompts, Profiles, Help)
|
| 18 |
+
./run.sh # port 7861, activates .venv and sets PYTHONPATH
|
| 19 |
+
python app.py # port 7860
|
| 20 |
+
|
| 21 |
+
# Run β simplified interface (Chat, Conversation Verification, Help only)
|
| 22 |
+
python run_simplified_interface.py
|
| 23 |
+
|
| 24 |
+
# Tests
|
| 25 |
+
python run_tests.py # all suites, one pytest subprocess per directory
|
| 26 |
+
python -m pytest tests/unit -q # one suite
|
| 27 |
+
python -m pytest tests/unit/test_consent_manager.py::test_name -q # one test
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
Tests import as `src.*`; pytest's rootdir insertion makes this work when run from the repo root. Run from anywhere else and you need `PYTHONPATH=.`. `direnv` (`.envrc`) does venv activation + `PYTHONPATH` + dotenv automatically.
|
| 31 |
+
|
| 32 |
+
Baseline as of this writing: `tests/unit` is **5 failed, 170 passed** β the 5 failures in `test_enhanced_results_display.py` are pre-existing, not caused by your change. Verify against a clean checkout before assuming you broke something. Several older files under `tests/unit` and `tests/integration` are script-style (`test_*()` returning `bool`), so they pass in pytest regardless of what they print β don't trust them as regression gates.
|
| 33 |
+
|
| 34 |
+
Env vars that change behavior: `LOG_PROMPTS=true` (dump every system/user prompt and response to `ai_interactions.log`), `PERF_TIMING` (per-stage `[PERF]` timing in the message path, on by default), `GRADIO_SERVER_PORT` / `GRADIO_SERVER_NAME` / `GRADIO_SHARE`, `GCP_SERVICE_ACCOUNT_B64` (base64 service-account JSON β enables Vertex AI instead of the Gemini API key).
|
| 35 |
+
|
| 36 |
+
## Two interfaces, one core
|
| 37 |
+
|
| 38 |
+
`src/interface/gradio_app.py` (full) and `src/interface/simplified_gradio_app.py` (simplified, built for the testing team) are **separate, largely parallel UI builders over the same `SimplifiedMedicalApp` core**. A change to shared chat/verification behavior usually has to be made or checked in both. The full app delegates to the `*_handlers.py` modules; the simplified app uses `simplified_chat_handlers.py` and its own inline wiring.
|
| 39 |
+
|
| 40 |
+
Entry points disagree on purpose: `app.py` β `gradio_app.main`, `run_simplified_interface.py` β `simplified_gradio_app.main`, and the README front-matter (`app_file:`) points Hugging Face Spaces at `simplified_gradio_app.py`. If you change what the deployed Space runs, update the README front-matter too.
|
| 41 |
+
|
| 42 |
+
## Message flow
|
| 43 |
+
|
| 44 |
+
`SimplifiedMedicalApp.process_message` (`src/core/simplified_medical_app.py`) is the single entry point for every patient turn. It is a state machine over `SessionSpiritualState` (`spiritual_state.py`), *not* a straight classify-then-answer:
|
| 45 |
+
|
| 46 |
+
1. **Awaiting consent** β `_handle_consent_response` (patient is deciding on a chaplain referral).
|
| 47 |
+
2. **In triage** β `_handle_triage_response` β continues the existing YELLOW triage; the classifier is **not** re-run mid-triage.
|
| 48 |
+
3. **Otherwise** β `SpiritualMonitor.classify` returns GREEN / YELLOW / RED:
|
| 49 |
+
- GREEN β normal medical reply.
|
| 50 |
+
- YELLOW β `SoftTriageManager` asks up to 2β3 gentle clarifying questions, then resolves to GREEN or escalates to RED (`_resolve_to_green` / `_escalate_to_red`; forced decision at the question limit).
|
| 51 |
+
- RED β crisis response + consent request + `ProviderSummaryGenerator` handoff summary.
|
| 52 |
+
|
| 53 |
+
The response returned to Gradio is prefixed with a classification badge, and every exchange is written by `ConversationLogger` to `conversation_logs/session_*.json`. `spiritual_state.last_assessment` is the shared slot the display, the logger, and the verification tab all read β the triage/escalation helpers update it as a side effect.
|
| 54 |
+
|
| 55 |
+
## Agent name keys
|
| 56 |
+
|
| 57 |
+
A small set of string keys threads through config, model overrides, prompt overrides, and the UI. They must stay in sync across four places:
|
| 58 |
+
|
| 59 |
+
- `AGENT_CONFIGURATIONS` in `src/config/ai_providers_config.py` β provider + model + temperature per agent.
|
| 60 |
+
- `apply_model_settings` in `src/interface/model_handlers.py` β the Model Settings tab writes `session.custom_models` under these keys.
|
| 61 |
+
- `_prompt_name_to_agent` in `src/interface/prompt_handlers.py` β maps emoji UI labels ("π Spiritual Monitor (Classifier)") to agent keys.
|
| 62 |
+
- `SimplifiedMedicalApp.set_model_overrides` / `set_prompt_overrides`, which propagate onto `AIClientManager`.
|
| 63 |
+
|
| 64 |
+
`get_agent_config` **silently falls back to Gemini 2.5 Flash for an unknown agent name** οΏ½οΏ½ a typo'd key produces a working app that quietly uses the wrong model. Note that `SoftSpiritualTriage` and `TriageResponseEvaluator` are used by the UI but are not in `AGENT_CONFIGURATIONS`, so they currently hit that fallback.
|
| 65 |
+
|
| 66 |
+
## Prompt system
|
| 67 |
+
|
| 68 |
+
Prompts are text files in `src/config/prompts/`, but resolution goes through `PromptController` (`src/config/prompt_management/prompt_controller.py`) with three tiers, highest first:
|
| 69 |
+
|
| 70 |
+
1. **Session override** β set from the Edit Prompts tab, scoped to one `session_id`, never touches disk.
|
| 71 |
+
2. **Centralized file** β `src/config/prompts/*.txt`, with shared components (indicators / rules / templates / categories from `prompt_management/data/*.json`) spliced into placeholders.
|
| 72 |
+
3. **Hardcoded default** β module-level `SYSTEM_PROMPT_*` constants in `spiritual_monitor.py`, `soft_triage_manager.py`, `src/config/prompts.py`.
|
| 73 |
+
|
| 74 |
+
"Promote to File" writes a session override to the real `.txt` and leaves a `*.backup.<timestamp>.txt` beside it (that's what the existing backup files in `src/config/prompts/` are). `PromptController` caches per `agent_type + session_id`; if you edit a prompt file on disk while the app is running, the cache can serve the stale copy.
|
| 75 |
+
|
| 76 |
+
## Verification subsystems
|
| 77 |
+
|
| 78 |
+
Two distinct workflows that share vocabulary but not code paths:
|
| 79 |
+
|
| 80 |
+
- **Conversation Verification** β replays the *current chat session*, exchange by exchange, for reviewer grading. Handlers in `src/interface/verification_handlers.py` (`_generate_conv_verification*`, `_mark_conv_correct/_incorrect`, `_export_conv_records_to_{json,csv}`). State lives in Gradio component state, not in a store. The Provider Summary is appended as the **final exchange**, and on that step the classification flag is hidden (see Gradio notes below).
|
| 81 |
+
- **Enhanced Verification** β batch testing via manual entry or CSV/XLSX upload (`enhanced_verification_interface.py`, `manual_input_interface.py`, `file_upload_interface.py`), persisted through `JSONVerificationStore` (`src/core/verification_store.py`) into `verification_sessions/`, exported to `verification_exports/`.
|
| 82 |
+
|
| 83 |
+
Feature toggles for both live in `app_config.py` (`FEATURE_FLAGS`, `ENHANCED_VERIFICATION_CONFIG`). Standard Verification is deliberately disabled there β its functionality was folded into Enhanced Verification; leave it off unless asked.
|
| 84 |
+
|
| 85 |
+
## Gradio 6 gotchas this codebase has already been bitten by
|
| 86 |
+
|
| 87 |
+
- A `gr.Radio` handed `""` raises (value not in choices) and fails the **entire** event response, painting "Error" across unrelated components. Normalize unselected radios to `None`.
|
| 88 |
+
- Handler return arity must match the `outputs=` list on **every** branch, including early returns and empty-session paths. Mismatches surface as unrelated UI breakage, not a clear traceback.
|
| 89 |
+
|
| 90 |
+
## Conventions
|
| 91 |
+
|
| 92 |
+
- Everything imports absolute from the repo root (`from src.core... import`); scripts that may be run directly re-insert the project root into `sys.path` at the top.
|
| 93 |
+
- Property-based tests use Hypothesis and live in `tests/verification_mode/test_properties_*.py` and `tests/chaplain_feedback/test_properties_*.py` β these are the meaningful correctness gates. `manual_tests/` holds scripts that hit real APIs and are run by hand, never in CI.
|
| 94 |
+
- Ignore `src/interface/enhanced_verification_ui_backup.py` β dead 1700-line copy kept around; don't edit it or use it as a reference.
|
| 95 |
+
- `.gitignore` excludes `docs/`, `conversation_logs/`, `exports/`, `review/`, `verification_*/`, and (oddly) `src/core/verification_store.py` β that last one is already tracked so edits commit normally, but `git status` will not surface new files in those paths.
|
| 96 |
+
- No PHI is persisted; API keys stay in `.env`.
|