Skip to content

Commit c055849

Browse files
authored
docs: stack-forward homepage, architecture diagrams, provenance, and repo metadata (#5)
* docs: stack-forward homepage + README lead, provenance, reconciled numbers Lead with the engineering (Polars/Spark/Dagster/Delta/Fabric/streaming) above the comparison table; add a 'Built with' band and a 'Why this exists' provenance section (scribe-iq's heuristic corpus from Synthea CSV + ACI-Bench/MTSamples/MedSynth → this principled rebuild → roadmap Ollama loop), led by ADR-022. Reorder 'What this shows' engineering-first + add the streaming-sim row. Reconcile 1,278 patients / 1,280 bundles and keep the 129-test badge (confirmed via pytest --collect-only). Mark the Ollama loop roadmap. * docs: architecture/parity/portfolio diagrams; Ollama loop marked roadmap ARCHITECTURE: system-context (D1) + medallion-with-engines (D2) + Dagster asset graph (D5). parity: dual-engine convergence with the rejected shared-abstraction / applyInPandas bridge-tax note (D3). portfolio: the Gold→Ollama→scribe-iq loop (D4), with prose corrected so it no longer implies scribe-iq's CURRENT corpus came from this lakehouse. * docs: plain-language lead (layered disclosure) on homepage, README, reviewer guide ADD-1: a jargon-free 2-sentence lead now precedes the technical hero on docs/index.md (hero moved into a 'For technical reviewers' abstract) and README.md; reviewer-guide gains a 'Not technical?' tier above '90 seconds'. Both audiences served by sequence — the technical depth is unchanged. * docs(site): tighten ADR-022 framing, roadmap honesty, and number consistency Review-driven fixes to the docs revamp (PR #5), from a 3-lens "how it lands" read (recruiter / senior-DE / honesty audit): - ADR-022 accuracy: drop "the same transforms run three ways." The two LocalLite surfaces (CLI + Dagster) share one transform set; the Fabric tier reimplements its own engine-native transforms. Fixed index.md and the README ASCII flow; amended ADR-015 (it cited the superseded ADR-002/004) and ADR-009. - Roadmap honesty: CORPUS_CONTRACT intro no longer presents the Ollama -> scribe-iq loop as live (clinical-bert is the current consumer; the loop is roadmap and does not produce scribe-iq's current corpus). Added the Ollama row to the reviewer-guide "what's real vs in-progress" table; standardized roadmap wording to "not built" (dropped "in progress"). - Numbers: standardized Bronze->Silver on the measured 2m19s (removed the contradictory 2m30s); fixed "1,278-bundle" (a patient count) -> "1,280-bundle" across 5 files. - Tone/scope: softened "proven on real enterprise infrastructure" -> "validated end-to-end on Fabric (F4) at sample scale"; dropped the dead local_spark column and the non-ADR-backed GCP column from the engine matrix; added a "New here?" cue to the homepage 90-second-tour card. mkdocs build --strict green; gen_data_dictionary/gen_corpus_schema --check pass.
1 parent 018c37c commit c055849

12 files changed

Lines changed: 352 additions & 146 deletions

README.md

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,42 @@
11
# scribe-iq-lakehouse
22

3+
This project takes raw, messy, hospital-style patient data and turns it into one clean, reliable,
4+
well-documented dataset that AI systems can safely build on. It's built to run the same way on a
5+
laptop or in the cloud, on synthetic (non-real) patient data only.
6+
37
Production-pattern healthcare data lakehouse on [Synthea Coherent](https://registry.opendata.aws/synthea-coherent-data/)
4-
(1,278 synthetic patients, FHIR R4). **Medallion** architecture — Bronze → Silver → Gold —
5-
implemented as **two independent, engine-native tiers** that emit the same Gold contract: a
6-
LocalLite tier (`core/` — Polars + delta-rs, runs on a laptop) and a Fabric tier (`fabric/`
7-
Spark + OneLake). The Gold corpus (`gold.encounter_summary`) feeds
8-
[`scribe-iq`](https://sandeep-jay.github.io/scribe-iq/) (clinical RAG),
9-
`clinical-bert-pipeline` (NLP), and an Ollama dialogue-generation pipeline.
8+
(1,278 patients → 1,280 FHIR R4 bundles): a **Bronze → Silver → Gold medallion** that turns raw
9+
multimodal clinical bundles into one governed, **versioned, test-gated** Gold data contract.
10+
11+
**Built twice, on purpose****Polars + delta-rs + DuckDB** on a laptop and **Spark + Delta +
12+
OneLake** on **Microsoft Fabric** — orchestrated as a **Dagster** asset graph with a
13+
**streaming-ingest simulation** of Fabric's Auto Loader. Two independent, engine-native
14+
implementations converge on the *same* contract by schema parity and a lockstep version, not
15+
shared code ([ADR-022](docs/adr/022-platform-independent-implementations.md)).
16+
17+
**Built with:** Polars · Apache Spark · Delta Lake (delta-rs / OneLake) · DuckDB · Dagster ·
18+
Microsoft Fabric · FHIR R4 · DICOM · AWS Open Data S3 — Python 3.11 · synthetic data, no PHI.
19+
20+
**Why it exists.** `scribe-iq` proved the clinical-documentation product on a corpus assembled
21+
heuristically (Synthea CSV + public note sets — ACI-Bench, MTSamples, MedSynth). This repo
22+
industrializes that foundation the rigorous way; next, a **roadmap** Ollama loop will generate
23+
`scribe-iq`'s next corpus from the Gold contract. Full story in the
24+
[docs](https://sandeep-jay.github.io/scribe-iq-lakehouse/portfolio/).
1025

1126
**Status:** Bronze → Silver → **Gold** fully built and run end-to-end on the complete
1227
1,278-patient dataset on the LocalLite tier (143,946 encounter summaries). DICOM imaging
1328
headers ingested. **Dagster** local orchestration renders the medallion as a software-defined
1429
asset graph (a third local execution surface alongside the CLI). The **Fabric tier** ran green
15-
end-to-end on F4 capacity against a 100-patient sample (notebooks 00–10); the full 1,278-bundle
30+
end-to-end on F4 capacity against a 100-patient sample (notebooks 00–10); the full 1,280-bundle
1631
re-run is pending. Synthetic data only — **no PHI**.
1732

1833
```
19-
AWS Open Data S3 Bronze (raw) Silver (10 Delta tables) Gold
20-
coherent/unzipped/ ──► fhir/ · dicom/ · csv/ ──► patient · encounter · … ──► encounter_summary
21-
(no credentials) + manifests condition · observation … (1 row / encounter)
22-
CDC enabled, validated + corpus_manifest.json
23-
└─► scribe-iq · BERT · Ollama
34+
AWS Open Data S3 Bronze (raw, append-only) Silver (10 typed Delta tables) Gold
35+
coherent/ ─► streaming_sim ─► fhir· dicom· csv ─► Polars + delta-rs (local) ─► gold.encounter_summary
36+
(no creds) (Auto Loader sim) + manifests / Spark from_json (Fabric) 1 row/encounter · contract v1.1.0
37+
CDC · validated (Dagster checks) └─► clinical-bert · scribe-iq via Ollama (roadmap)
2438
25-
execution surfaces (same pure transforms): CLI · Dagster (core/orchestration/dagster/) · Fabric notebooks
39+
local surfaces share one transform set: CLI · Dagster asset graph (core/orchestration/dagster/) | Fabric tier reimplements its own (ADR-022)
2640
```
2741

2842
---

docs/ARCHITECTURE.md

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,29 @@ CLI or a **Dagster** software-defined asset graph (ADR-015/016); on Fabric it ra
1818
green end-to-end on F4 capacity against a 100-patient demo sample via notebooks 00–10.
1919

2020
```mermaid
21-
flowchart TD
22-
S3["AWS Open Data<br/>s3://synthea-open-data/coherent<br/>(1,280 FHIR bundles, 4.6 GB)"]
23-
24-
subgraph BRONZE["BRONZE — raw, append-only"]
25-
B["data/bronze/fhir/cohort=A|B|C/*.json<br/>+ dicom/*.dcm (headers) + csv/ (reference)<br/>+ _metadata/manifest.json"]
26-
end
27-
28-
subgraph SILVER["SILVER — Delta, CDC enabled ✅ built"]
29-
ST["10 tables: patient · encounter · condition · observation<br/>medication_request · procedure · soap_note · ecg_metadata<br/>imaging_study · genomic_report (+ ingest_log audit)"]
21+
flowchart LR
22+
SRC["AWS Open Data S3<br/>Synthea Coherent · FHIR R4<br/>1,278 patients · ~4.6 GiB"]
23+
subgraph LH["scribe-iq-lakehouse — the data platform"]
24+
direction TB
25+
BR["Bronze<br/>raw · append-only"]
26+
SV["Silver<br/>10 typed Delta tables · CDC · validated"]
27+
GD["Gold<br/>gold.encounter_summary<br/>143,946 rows · 1 / encounter"]
28+
BR --> SV --> GD
3029
end
31-
32-
subgraph GOLD["GOLD — denormalized corpus ✅ built"]
33-
G["gold.encounter_summary (143,946 rows, 1/encounter)<br/>+ _metadata/corpus_manifest.json"]
30+
SRC --> BR
31+
GD == "corpus contract v1.1.0<br/>versioned · test-gated" ==> CON
32+
subgraph CON["Downstream AI consumers"]
33+
direction TB
34+
SIQ["scribe-iq<br/>clinical RAG / docs"]
35+
BERT["clinical-bert-pipeline<br/>NLP"]
36+
OLL["Ollama pipeline (roadmap)<br/>note + dialogue generation"]
3437
end
35-
36-
S3 -->|"download.py · aws s3 sync"| B
37-
B -->|"pipeline.py · per-cohort micro-batch<br/>parse → build → MERGE"| ST
38-
ST -->|"build_gold · Polars denormalize → overwrite"| G
39-
G -.->|"corpus contract v1.1.0"| DS["scribe-iq (RAG)<br/>clinical-bert-pipeline (NLP)<br/>Ollama generation"]
40-
41-
classDef done fill:#d4edda,stroke:#28a745;
42-
classDef planned fill:#fff3cd,stroke:#ffc107,stroke-dasharray:4 3;
43-
class B,ST,G done;
38+
classDef plat fill:#eef2ff,stroke:#6366f1;
39+
classDef cons fill:#f0fdf4,stroke:#22c55e;
40+
classDef road fill:#fff7ed,stroke:#f59e0b,stroke-dasharray:4 3;
41+
class LH plat
42+
class CON cons
43+
class OLL road
4444
```
4545

4646
The LocalLite tier runs under **two local execution surfaces** (ADR-015/016): the
@@ -59,6 +59,67 @@ both render via [`core/preview.py`](https://github.com/sandeep-jay/scribe-iq-lak
5959
shape appears in the UI, the terminal, and the SQL notebook — one set of
6060
renderers, three audiences. Recording guide: [`docs/demo/PLAYBOOK.md`](demo/PLAYBOOK.md).
6161

62+
## Medallion, with the engine at every hop
63+
64+
Bronze ingest (S3 → append-only; `streaming_sim.py` replays cohorts as an Auto Loader analogue)
65+
→ Silver (one pure-Python FHIR parse fans out to both tiers — Polars + delta-rs locally, Spark
66+
`from_json(BUNDLE_SCHEMA)` on Fabric — into 10 typed, CDC-enabled Delta tables, validated by
67+
`validate_table`) → Gold (Polars join/agg → one `gold.encounter_summary` under the versioned
68+
contract).
69+
70+
```mermaid
71+
flowchart TB
72+
S3["AWS Open Data S3<br/>FHIR bundles"]
73+
STREAM["streaming_sim.py<br/>cohort replay · Auto Loader pattern"]
74+
S3 --> STREAM --> BRONZE
75+
76+
subgraph BRONZE["Bronze — raw, append-only"]
77+
B1["fhir/ · dicom/ · csv/ + manifests"]
78+
end
79+
80+
subgraph SILVER["Silver — 10 typed Delta tables · CDC · validated"]
81+
direction LR
82+
PARSE["pure-Python FHIRBundleParser<br/>(engine-agnostic dicts)"]
83+
LOCALS["LocalLite: Polars + delta-rs"]
84+
FABS["Fabric: Spark from_json(BUNDLE_SCHEMA)<br/>distributed"]
85+
PARSE --> LOCALS
86+
PARSE --> FABS
87+
end
88+
89+
subgraph GOLD["Gold — one governed contract"]
90+
G1["gold.encounter_summary<br/>Polars join/agg · 1 row / encounter<br/>contract v1.1.0"]
91+
end
92+
93+
BRONZE --> SILVER --> GOLD
94+
VAL["validate_table → Dagster asset checks"] -.-> SILVER
95+
96+
classDef gold fill:#fff7ed,stroke:#f59e0b;
97+
class GOLD gold
98+
```
99+
100+
## Dagster asset graph (ADR-015/016)
101+
102+
The LocalLite tier also renders the medallion as a **software-defined asset graph** — cohorts
103+
become partitions, one parse-once `@multi_asset` fans out to 10 Silver nodes, and `validate_table`
104+
is surfaced as an `@asset_check` (rule-by-rule pass/fail in the UI).
105+
106+
```mermaid
107+
flowchart LR
108+
subgraph BRONZE_G["bronze (cohort-partitioned)"]
109+
BF["bronze_fhir<br/>inventory per cohort"]
110+
end
111+
subgraph SILVER_G["silver (multi-asset: parse-once → 10 nodes)"]
112+
S1["patient"]; S2["encounter"]; S3["condition"]; S4["observation"]; S5["… 6 more"]
113+
end
114+
subgraph GOLD_G["gold"]
115+
GA["gold_encounter_summary<br/>+ corpus_manifest.json"]
116+
end
117+
BF --> S1 & S2 & S3 & S4 & S5
118+
S1 & S2 & S3 & S4 & S5 --> GA
119+
AC["@asset_check: validate_table"] -.-> S1
120+
AC -.-> S2
121+
```
122+
62123
## Layers (as-built)
63124

64125
| Layer | State | Storage | Notes |
@@ -67,7 +128,7 @@ renderers, three audiences. Recording guide: [`docs/demo/PLAYBOOK.md`](demo/PLAY
67128
| Silver | ✅ built (local) | 10 Delta tables + `ingest_log` | CDC enabled; validated; MERGE-upsert per cohort |
68129
| Gold | ✅ built (local) | `encounter_summary` Delta + manifest | 1 row/encounter; CDC; as-of-date problem list; corpus contract v1.1.0 (ADR-012/014) |
69130
| Dagster orchestration | ✅ built (local) | `core/orchestration/dagster/` package | medallion as asset graph; cohort partitions; `validate_table` as asset checks (ADR-015/016) |
70-
| Fabric execution | ✅ green end-to-end (F4, SAMPLE_SIZE=100) | OneLake | independent Spark-native impl (ADR-022); notebooks 00–10; anonymous S3 ingest in 01; full 1,278-bundle re-run pending |
131+
| Fabric execution | ✅ green end-to-end (F4, SAMPLE_SIZE=100) | OneLake | independent Spark-native impl (ADR-022); notebooks 00–10; anonymous S3 ingest in 01; full 1,280-bundle re-run pending |
71132

72133
## Module map
73134

@@ -129,7 +190,7 @@ docs/demo/
129190

130191
## Current scale (full local run)
131192

132-
1,280 bundles (1,278 patients) → 10 Silver Delta tables in **~2m30s**, then →
193+
1,280 bundles (1,278 patients) → 10 Silver Delta tables in **2m19s**, then →
133194
**143,946** `gold.encounter_summary` rows in **~6.5s** on a single laptop, all validations passing.
134195
Per-table counts, corpus coverage, and methodology: [BENCHMARKS.md](BENCHMARKS.md). Operational
135196
procedures: [RUNBOOK.md](RUNBOOK.md). The Gold corpus contract is documented in

docs/BENCHMARKS.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,13 @@ Delta table (overwrite + CDC) plus the corpus manifest.
9090
Independent engine-native tiers emitting the same Gold contract (ADR-022). LocalLite is measured
9191
on the full dataset; the Fabric tier ran green on F4 capacity against a 100-patient sample.
9292

93-
| Capability | local_lite | local_spark | Fabric | Databricks | AWS | GCP |
94-
|------------|-----------|-------------|--------|------------|-----|-----|
95-
| Bronze→Silver (full) |2m30s | | ✅ F4 (100-sample) | roadmap | roadmap | roadmap |
96-
| Silver→Gold (full) |~6.5s | | ✅ F4 (100-sample) | roadmap | roadmap | roadmap |
97-
| CDC || || roadmap | roadmap | roadmap |
98-
| Streaming | sim only | | 🔜 Auto Loader | roadmap | roadmap | roadmap |
99-
| Cost (1.3k pts) | $0 | $0 | trial | |||
93+
| Capability | local_lite | Fabric | Databricks | AWS |
94+
|------------|-----------|--------|------------|-----|
95+
| Bronze→Silver (full) |2m19s | ✅ F4 (100-sample) | roadmap | roadmap |
96+
| Silver→Gold (full) |~6.5s | ✅ F4 (100-sample) | roadmap | roadmap |
97+
| CDC || | roadmap | roadmap |
98+
| Streaming | sim only | 🔜 Auto Loader | roadmap | roadmap |
99+
| Cost (1.3k pts) | $0 | trial |||
100100

101101
## Execution surfaces
102102

@@ -147,5 +147,5 @@ python -m core.surfaces.cli.pipeline --gold-only # rebuil
147147
- `local_lite` holds one cohort's records in memory at a time (~1/3 of the data); peak
148148
RSS stayed well under what a typical dev laptop offers. Full-dataset-in-memory was
149149
deliberately avoided.
150-
- Fabric/Spark full-run figures will be filled in after the full 1,278-bundle re-run; the
150+
- Fabric/Spark full-run figures will be filled in after the full 1,280-bundle re-run; the
151151
100-patient F4 run is green end-to-end (notebooks 00–10).

docs/CORPUS_CONTRACT.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
This is the handoff interface between the lakehouse and its downstream AI consumers:
66

7-
- **Ollama generation pipeline** — grounds synthetic clinical dialogue on each summary.
8-
- **scribe-iq** (RAG) — replaces the 19-patient dev corpus with this 1,278-patient corpus.
9-
- **clinical-bert-pipeline** (NLP) — consumes `soap_note_text` + structured labels.
7+
- **clinical-bert-pipeline** (NLP) — consumes `soap_note_text` + structured labels from the contract.
8+
- **Ollama generation pipeline** *(roadmap)* — will derive synthetic notes/dialogue from each summary.
9+
- **scribe-iq** (RAG) *(roadmap loop)* — its next corpus will be that Ollama-generated text, superseding
10+
its current heuristic 19-patient dev corpus (which this lakehouse does not yet produce).
1011

1112
One row = one clinical encounter. The machine-readable schema is
1213
[`schemas/gold_encounter_summary.json`](https://github.com/sandeep-jay/scribe-iq-lakehouse/blob/main/schemas/gold_encounter_summary.json) (JSON

docs/RUNBOOK.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ python -m core.ingest.download --bronze-root data/bronze
6262
# 3. (Optional) Land DICOM + CSV assets (~10 GB; enables imaging header extraction)
6363
python -m core.ingest.download --assets-only --with-dicom --with-csv
6464

65-
# 4. Build Bronze → Silver → Gold (~2.5 min Silver + ~6.5 s Gold)
65+
# 4. Build Bronze → Silver → Gold (~2m19s Silver + ~6.5 s Gold)
6666
python -m core.surfaces.cli.pipeline --with-gold
6767

6868
# 5. Verify (see §5)

docs/adr/009-local-silver-materialization.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ real Coherent data forced:
4949
## Consequences
5050

5151
**Positive:**
52-
- Full local pipeline runs with `pip install` only; same transforms target Fabric later.
52+
- Full local pipeline runs with `pip install` only; the Fabric tier later targets the same
53+
*contract* (its own engine-native transforms, per ADR-022).
5354
- CDC enabled from creation — downstream change-feed consumers work on day one.
5455
- Flat, portable Silver schemas; Gold can still recover BP via `components_json`.
5556

docs/adr/015-dagster-local-orchestration.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ the persistence pattern are specified separately in [ADR-016](016-dagster-asset-
4747
- Per-cohort **partitioned materialization + backfill** replaces the `rm -rf` full rebuild:
4848
each cohort is the incremental MERGE path that actually works (ADR-016).
4949
- Validation surfaces as first-class **asset checks**; run history/metadata live in the UI.
50-
- The same pure transforms now demonstrably run under **three orchestrators** (CLI, Dagster,
51-
Fabric Data Factory) — the concrete payoff of ADR-002 (platform isolation) and ADR-004 (Arrow).
50+
- The LocalLite pure transforms run under **two local orchestrators** (CLI, Dagster) with zero
51+
duplicated logic — the concrete payoff of platform isolation and the Arrow interchange type.
52+
*Amended per [ADR-022](022-platform-independent-implementations.md): the Fabric tier is a separate
53+
engine-native implementation, not a third orchestrator over the same transforms; the originally
54+
cited ADR-002/004 are superseded by ADR-022.*
5255

5356
**Negative:**
5457
- New dev dependency (`dagster` + `dagster-webserver`) and a UI process to run.

0 commit comments

Comments
 (0)