Files
ruvnet--RuView/v2/crates/ruview-gamma-clinic/src/main.rs
T
Claude 41d52311bd feat(clinic): ADR-251 clinical dashboard + hash-chained RuVector store
Read-only research/clinical instrumentation over the ADR-250 adaptive-gamma
platform, closing two operational gaps: no durable cohort memory, no
clinician surface.

Store (store.rs): append-only JSONL holding anonymized profiles, witnessed
session summaries, and acceptance verdicts. Every line is hash-chained
(entry_hash = SHA-256(prev_hash || raw record bytes)), so any retroactive
edit, deletion, or reorder breaks the chain — the store fails closed (refuses
to open tampered data) and rebuilds the RuVector kNN/clustering layer on open
so cohort warm-start survives restarts. The chain hashes the exact on-disk
bytes via serde_json RawValue, because serde_json's default float parse is
lossy and re-serialization is not byte-stable (this bit the first cut: a
9-session ingest self-corrupted on reopen).

Dashboard (server.rs + embedded dependency-free dashboard.html): Axum surface
with GET routes for participants, per-participant frequency-response map +
session trend with safety-stop markers, cohort clusters, per-program
acceptance verdicts, and a live chain-integrity badge. Strictly read-only — a
test asserts no route accepts POST. Claim discipline inherited: acceptance
payloads carry AcceptanceReport::released_claim (NO_CLAIM on failure), never a
raw program claim.

gamma-clinic binary; ingest_governor bridges the live ADR-250 loop into the
store (pseudonymous, dedup by witness hash). Pseudonymity asserted: the
person_id never reaches disk.

20 tests (13 store/lib + 7 server) + 1 doctest; live binary smoke-tested.
Workspace gate: 2,935 passed / 0 failed.

https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
2026-06-11 00:32:38 +00:00

34 lines
1.2 KiB
Rust

//! `gamma-clinic` — serve the ADR-251 clinical dashboard over a store file.
//!
//! Usage: `gamma-clinic [STORE_PATH] [BIND_ADDR]`
//! Defaults: `clinic.jsonl`, `127.0.0.1:8090`. Read-only surface.
use std::sync::Arc;
use tokio::sync::RwLock;
use ruview_gamma_clinic::server::router;
use ruview_gamma_clinic::store::ClinicStore;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = std::env::args().skip(1);
let store_path = args.next().unwrap_or_else(|| "clinic.jsonl".to_string());
let bind = args.next().unwrap_or_else(|| "127.0.0.1:8090".to_string());
// Fails closed on a tampered chain — refuses to serve doctored data.
let store = ClinicStore::open(&store_path)?;
let status = store.verify_chain();
println!(
"gamma-clinic: store={store_path} records={} chain={}",
status.records,
if status.valid { "ok" } else { "BROKEN" }
);
let app = router(Arc::new(RwLock::new(store)));
let listener = tokio::net::TcpListener::bind(&bind).await?;
println!("gamma-clinic: dashboard at http://{bind}/ (read-only; research use only)");
axum::serve(listener, app).await?;
Ok(())
}