Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions .impeccable/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@
"detector": {
"ignoreRules": [],
"ignoreFiles": [],
"ignoreValues": [
{
"rule": "side-tab",
"value": "*",
"files": [
"viewer/assets/radsysx-viewer.css"
],
"createdAt": "2026-09-23T02:43:10.069Z",
"reason": "Assistant design review: the pre-existing 2px muted #5c7c91 rule groups nested Jev claim judgments and execution receipts; it is not a thick decorative card accent. Verified in the rendered 280px sidebar and git blame."
}
]
"ignoreValues": []
}
}
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ Last updated: 2026-09-22
- Favor rigorous, beautiful, professional solutions with high signal-to-noise.
- Prefer Linux-native commands and paths.
- Record durable behavior changes in this file or the nearest relevant child `AGENTS.md`.
- `.impeccable/config.json` records reasoned, file-scoped design-detector exceptions. The muted 2 px Jev judgment separator is intentional grouping, not a decorative card accent; its `side-tab` exception is limited to `viewer/assets/radsysx-viewer.css`.
- Keep sidebar information separated into Chat, Research and Jev review views. Use a quiet reading-room palette and progressive disclosure; technical receipts and full abstracts stay collapsed by default. Jev judgment groups use subtle horizontal separators; the old side-accent exception is removed.

## Child DOX Index

Expand Down Expand Up @@ -339,7 +339,7 @@ The standalone [evidence-review runbook](backend/evidence_review/README.md) docu
- See `roadmap/ai-backend/NIM_IMPLEMENTATION.md` for configuration, commands and dated acceptance. Keep provider keys separate and never silently fall back when the chosen model fails.

- The sidebar **Settings → Research models** saves Gemini/NVIDIA NIM provider and exact model per signed account. Environment supplies the default until a saved choice exists. The dropdown includes the entire hosted NVIDIA catalog; catalog inclusion does not verify tool support or entitlement. Saving closes that account's sessions/jobs and requires reconnection; live voice selection and offline evidence CLI model flags remain separate.
- Keep the AI sidebar compact: one header row, inline data confirmation/connect, and media controls visible only during an active connection. Data attestation, transmission disclosure and separate microphone/image consent remain required.
- Keep the AI sidebar compact: show the text/research model near the header and separate Chat, Research and Jev review views. Optional voice setup is collapsed within Chat; data attestation and disclosure live by the composer. Keep media state visible while connected and preserve separate microphone/image consent.

- Sidebar Jev reviews run through backend-owned `/api/ai/sidebar/*/evidence-reviews` contracts in research/pilot only, using backend-only `RADSYSX_TYPESAFE_AI_API_KEY`. They retain original answers, require independent text confirmation, and persist POSIX-private artifacts in `.ai-evidence/` beside the actual database (or absolute `RADSYSX_AI_EVIDENCE_DIR`). Ending voice preserves review; explicit cancel/account changes/logout stop it; source-history deletion cancels jobs and removes their artifacts. Clinical use and the qualified human evidence-quality study remain unapproved/pending.

Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ NVIDIA NIM is available for explicit evidence evaluation and opt-in PubMed resea
Typed **Send** and explicit **Research** work without Gemini Live/OpenAI Realtime. Confirm synthetic/deidentified content and choose the standard model in **Settings → Text & research models**. Only the question, bounded text history (chat only) and neutral viewer metadata are sent; image pixels require separate live sharing. **Connect voice** starts a separate voice conversation. See `roadmap/ai-backend/DESKTOP_AI_ACTIVATION.md`.

ChatGPT/Codex subscription sign-in is available under desktop AI Settings for typed chat and public PubMed research. It uses isolated backend-owned Codex App Server and the OS keyring, not OpenAI API credentials or Realtime entitlement. Read `roadmap/ai-backend/CODEX_SUBSCRIPTION.md`; never copy the user's existing Codex auth.

The AI sidebar separates Chat, Research and Jev review. Optional voice setup stays in Chat; the review workspace hides the composer and collapses abstracts/technical receipts. Sidebar evidence uses versioned intact cited passages and explicitly reports empty previews as unavailable. See `roadmap/ai-backend/JEV_SIDEBAR_IMPLEMENTATION.md` for the corrected workflow and live acceptance.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,15 +285,15 @@ The OHIF sidebar offers `gemini-3.8-live-extended-thinking` and `gpt-realtime-2.

1. Run `npm run desktop` and open **Settings → API keys** in the **RadSysX AI** panel. Enter and save your own Gemini key, OpenAI key, or both. Saving refreshes provider availability without restarting; the first connection verifies provider access. Keys are sent only to the local backend for encrypted storage, and are never displayed again or saved in browser storage/history. Replacing or removing a key ends your active assistant sessions and tasks.
2. Open a synthetic/deidentified study. The key settings distinguish **your saved key**, an **app-configured key**, and **not configured**. Removing a saved key explicitly returns that provider to an app-configured key when one exists.
3. Select the provider, confirm the displayed content is synthetic or deidentified, then connect. If the initial catalog loaded before local sign-in, use **Retry assistant setup** first. This records your declaration, not an automated deidentification result. Changing provider ends the old session and requires fresh confirmation.
3. In **Chat → Voice**, select the provider, confirm the displayed content is synthetic or deidentified, then connect. If the initial catalog loaded before local sign-in, use **Retry setup** first. This records your declaration, not an automated deidentification result. Changing provider ends the old session and requires fresh confirmation.
4. After **Connected**, enable the microphone or send text to the voice provider. Independent text chat and research are described below. To discuss what is visible, click **Share active image** and wait for **image sharing on · image sent**. The panel names the active image; capture covers that selected viewport, at up to one JPEG frame per second. The whole app, sidebar and other windows are outside this capture.
5. Ask for a viewer action, image explanation, or public research. Review a proposed durable report save or deletion before applying it. Local-only DICOM must be imported/associated through the worklist before saving a report.

**Text without voice:** confirm synthetic/deidentified data, type your question, then choose **Send** for a discussion or **Research** for an explicit literature search. No Gemini Live or OpenAI Realtime connection is required. **Settings → Text & research models** selects the standard Gemini/NVIDIA or signed-in ChatGPT/Codex model. The request includes your question and neutral case/series metadata, not image pixels or patient records. Describe relevant findings in your question; this path does not inspect scans. **Connect voice** separately starts a new voice conversation. Jobs show progress, cancellation and saved results.

**ChatGPT subscription:** in **Settings**, choose **Sign in with ChatGPT**, continue in the official browser flow, then select **ChatGPT / Codex subscription** and an account-available model under Text & research models. Sign-in preserves your existing model until you save. Uses your plan’s Codex allowance for text/public PubMed research; Realtime voice remains separately API-key billed. Credentials stay in an isolated OS-keyring account. See the [subscription runbook](roadmap/ai-backend/CODEX_SUBSCRIPTION.md) for setup, limits and validation.

**Jev evidence review** is visible above the conversation: use **Review latest evidence with Jev** for the latest completed PubMed result, or **Saved research** to reopen a conversation. Preview the exact claims and abstracts, select claims, confirm public/synthetic text, then explicitly start the review. Jev shows abstract-support judgments and saved execution receipts; the original answer stays unchanged. It does not analyze image pixels.
The sidebar separates **Chat**, **Research**, and **Jev review**. Chat discusses the case; Research shows literature answers and collapsed source lists. Optional voice setup is inside Chat. From a completed PubMed result, choose **Review evidence with Jev** to enter a dedicated review view. Select the unchanged cited passages, inspect their abstracts, confirm public/synthetic text, then explicitly start Jev. Results show abstract-support judgments with execution receipts under details. Empty previews explain why Jev has not run and offer **Prepare review again**. It does not analyze image pixels.

**Literature research** cards show the recorded provider/model and worker steps, including waiting for the model, searching PubMed and preparing the answer. Completed, timed-out and cancelled jobs stay visible in history. Model configuration alone does not mean a job is running. [Desktop activation evidence](roadmap/ai-backend/DESKTOP_AI_ACTIVATION.md) separates local checks from hosted-provider results.

Expand Down
2 changes: 2 additions & 0 deletions WARP.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,5 @@ NVIDIA NIM is available for explicit evidence evaluation and opt-in PubMed resea
Typed **Send** and explicit **Research** work without Gemini Live/OpenAI Realtime. Confirm synthetic/deidentified content and choose the standard model in **Settings → Text & research models**. Only the question, bounded text history (chat only) and neutral viewer metadata are sent; image pixels require separate live sharing. **Connect voice** starts a separate voice conversation. See `roadmap/ai-backend/DESKTOP_AI_ACTIVATION.md`.

ChatGPT/Codex subscription sign-in is available under desktop AI Settings for typed chat and public PubMed research through isolated, pinned Codex App Server. Subscription credentials stay in the OS keyring; Realtime remains API-key billed. Read `roadmap/ai-backend/CODEX_SUBSCRIPTION.md`.

The AI sidebar separates Chat, Research and Jev review. Optional voice setup stays in Chat; the review workspace hides the composer and collapses abstracts/technical receipts. Sidebar evidence uses versioned intact cited passages and explicitly reports empty previews as unavailable. See `roadmap/ai-backend/JEV_SIDEBAR_IMPLEMENTATION.md` for the corrected workflow and live acceptance.
2 changes: 2 additions & 0 deletions backend/clinical/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@

## Explicit Jev evidence reviews

- New sidebar preparations use the versioned intact-passage extractor (`cited-passages-v2`) for trailing paragraph citations and comma-grouped source IDs. Preserve original offsets/text and rebuild the declared plan during evaluation. A preview with no executable pairs is unavailable with `no_reviewable_claims`; legacy ready/zero-pair summaries are projected the same way without rewriting artifacts. Explicit Prepare review again creates a fresh preview and requires renewed confirmation.

- Own `ai_evidence_contracts.py`, `ai_evidence_repository.py`, `ai_evidence_artifacts.py`, `ai_evidence_review.py` and their additive `ai_jev_reviews`/`ai_jev_operations` persistence. These focused contracts stay separate from live conversation messages and primary-model tool results.
- Only signed unexpired `ai.run` actors in enabled research/pilot may prepare an owned completed PubMed research result. Freeze its original answer/source/context identity and recorded generation, retrieve original abstracts by fixed PMID endpoints, then require exact-preview public/synthetic confirmation and backend-issued claim selection before pinned `jev-1.13.0` inference. Saved-history review does not require a live connection. The preview is not patient-text approval.
- One active review per actor, two globally; preparation is bounded to 20 seconds, evaluation/cleanup to 70 (the runner itself remains 60 plus five). Recheck authority/source identity before every external call. Account stop invalidates queued starts, even if they were waiting for the owner lock. Operation identity and starting state commit together; duplicate requests never schedule duplicate inference.
Expand Down
10 changes: 6 additions & 4 deletions backend/clinical/ai_evidence_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ def artifacts(self,row):
def _summary(self,row):
values={k:v for k,v in row.progress_json.items() if k in {
'generation','totalPairs','completedPairs','settledPairs','submittedAttempts','unknownUsageAttempts'}}
empty = row.status == 'ready' and not values.get('totalPairs')
return EvidenceReviewSummary(review_id=row.id,session_id=row.session_id,tool_call_id=row.tool_id,
source_context_version=row.context_version,status=row.status,created_at=row.created_at,
updated_at=row.updated_at,reason=row.reason,**values)
source_context_version=row.context_version,status='unavailable' if empty else row.status,created_at=row.created_at,
updated_at=row.updated_at,reason='no_reviewable_claims' if empty else row.reason,**values)

def list(self,actor,session_id):
self.require(actor)
Expand Down Expand Up @@ -247,11 +248,12 @@ async def _work(self,job):
'data_class':'public_literature','generation':job.row.progress_json['generation'],
'result':result.model_dump(mode='json'),'evidence':[e.model_dump(mode='json') for e in evidence],
'capture_exclusions':[e.model_dump(mode='json') for e in exclusions]},limits=self.limits)
plan=build_review_plan(snapshot,limits=self.limits)
plan=build_review_plan(snapshot,limits=self.limits,builder_version='cited-passages-v2')
ref,digest=self.artifacts(job.row).create_preview(snapshot,plan,job.row.progress_json['generation'])
self.repository.update_if_current(job.row.id,job.row.generation,preview_ref=ref,preview_hash=digest,
progress_json={**job.row.progress_json,'totalPairs':len(plan.pairs)})
status='ready'
status='ready' if plan.pairs else 'unavailable'
reason=None if plan.pairs else 'no_reviewable_claims'
else:
with self.artifacts(job.row).open_run() as store:
job.store=store
Expand Down
1 change: 1 addition & 0 deletions backend/evidence_review/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ None.
## Evaluation inputs and providers

- `sentence-citations-v1` keeps exact Unicode spans, compound sentences and separate cited abstracts. Ambiguous paragraph citation attachment is excluded; curated annotations must validate against original spans and sources.
- Sidebar preparation explicitly uses `cited-passages-v2`: retain a whole paragraph/list item when only its final sentence is cited, rather than guessing individual sentence attribution. Recognize exact single and comma-grouped `[s1, s2]` citation spans; each cited abstract still receives an independent judgment. The runner validates the declared supported builder and reconstructs the full immutable plan. Legacy CLI/default and saved v1 plans retain their original sentence rules; never silently reinterpret an existing preview.
- `settings.py` reads only explicitly requested deployment settings. Clinical/unknown modes reject network evaluation; Jev does not require Gemini credentials. The normal application provider catalog is unchanged.
- `typesafe.py` pins Jev 1.13.0 and validates all five-way probabilities, model identity and usage. Adapters issue one attempt; the runner owns retries/deadlines. Transport discards error bodies, rejects compression and bounds success bodies.

Expand Down
6 changes: 5 additions & 1 deletion backend/evidence_review/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ async def evaluate_snapshot(snapshot: Snapshot, plan: ReviewPlan, *, adapter: Ev
snapshot = load_snapshot(canonical_json(snapshot.model_dump(mode="json")), limits=limits)
annotations = tuple(SpanAnnotation(start=u.start,end=u.end,citation_spans=u.citation_spans)
for u in plan.units if u.origin == "curated")
expected = build_review_plan(snapshot,limits=limits,annotations=annotations)
versions = {u.builder_version for u in plan.units}
if len(versions) > 1:
raise ValueError("evaluation_input_mismatch")
expected = build_review_plan(snapshot,limits=limits,annotations=annotations,
**({'builder_version':next(iter(versions))} if versions else {}))
expected = select_review_plan(expected, selected_unit_ids=selected_unit_ids)
selection = ([u.unit_id for u in expected.units if u.unit_id in selected_unit_ids]
if selected_unit_ids is not None else None)
Expand Down
Loading
Loading