Skip to content

Commit 46cb25d

Browse files
committed
docs: round-2 freshness pass — spec paths + numbering, RUNBOOK refs, archive pattern
Conservative cleanup following the wider audit. Three changes: docs/roadmap/scribe-iq-lakehouse-spec.md - Section numbering fixed. §17 Roadmap was out of order between §8 and §9 (a pre-existing inconsistency); renumbered to §9 and bumped §9–§16 by one so the spec now runs §1 → §17 cleanly. - 40+ stale `local/` path references fixed to `core/` (relics of the Session 4.5 local/ → core/ rename that this spec predates). Bulk replacements: local/ingest/ → core/ingest/ local/transforms/ → core/transforms/ local/validation/ → core/validation/ local/gold/ → core/gold/ local/platform/ → core/platform/ local.validation. → core.validation. local/pipeline.py → core/surfaces/cli/pipeline.py `python local/pipeline.py` → `python -m core.surfaces.cli.pipeline` `python local/pipeline_lite.py --cohort sample` → `python -m core.surfaces.cli.pipeline --cohort sample` `ruff/black ... local/ tests/` → `... core/ fabric/` factory PLATFORMS strings → real ones (fabric.platform.FabricPlatform, databricks.platform.DatabricksPlatform, etc.; core.platform.local_lite.* stays in core/). - §4 Repository Structure tree: root rename + added fabric/ subtree + tests/ moved under core/tests/ + scripts/ moved under core/scripts/ to match reality. Other entries (mkdocs.yml, docker-compose.yml, REVIEWER_GUIDE.md, PRODUCTION_NOTES.md, STREAMING_DESIGN.md, schemas/*.json) are aspirational from the Session-0 plan and left in place — Conservative scope per user direction; ARCHITECTURE.md is the source of truth for the live tree. docs/RUNBOOK.md - 4 stale `local/` / pre-rename references fixed: `tests/test_dagster_defs.py` → `core/tests/test_dagster_defs.py` `[tool.dagster] module_name = "orchestration.definitions"` → `... = "core.orchestration.dagster.definitions"` (matches pyproject.toml) `python -m scripts.demo_walkthrough` → `python -m core.scripts.demo_walkthrough` (3 instances in §5 + 1 in §6) "portfolio demo video" → "demo video" (one stray narrative residue from the 370f666 personal-narrative pass) docs/_archive/ - New directory + README documenting the archive convention. Empty today; used when planning docs need historical preservation rather than deletion. Decision rules in the README (keep vs archive vs delete) make the policy explicit so future cleanups don't drift into accumulating cruft. Conservative scope per user direction — did NOT trim: - §9 Roadmap aspirational phases (kept; forward-facing planning) - §10 Implementation Sequence (sessions 1–7 plan; mostly stale but kept for historical structure) - §11 README Structure (kept; lives in code fence so doesn't pollute TOC) - §12 Fabric Trial Checklist (overlaps fabric/docs/SCREENSHOTS.md; kept) - §15 Fabric DevOps (442 lines of unbuilt design; kept as forward-facing) - §16 Fabric Demo Plan (overlaps PLAYBOOK.md; kept) Tests still 128 passed + 1 skipped. Zero `local/` references remain in any tracked file.
1 parent b133c53 commit 46cb25d

3 files changed

Lines changed: 101 additions & 62 deletions

File tree

docs/RUNBOOK.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,9 @@ Or run the full one-patient walkthrough for a rendered Bronze → Silver → Gol
197197
(also what's reused by the Dagster asset metadata, see §6):
198198

199199
```bash
200-
python -m scripts.demo_walkthrough # auto-picks a "good demo" patient
201-
python -m scripts.demo_walkthrough --pause 1.5 # 1.5s between sections (screencast pacing)
202-
python -m scripts.demo_walkthrough --patient-id <uuid> # reproducible
200+
python -m core.scripts.demo_walkthrough # auto-picks a "good demo" patient
201+
python -m core.scripts.demo_walkthrough --pause 1.5 # 1.5s between sections (screencast pacing)
202+
python -m core.scripts.demo_walkthrough --patient-id <uuid> # reproducible
203203
```
204204

205205
For **interactive SQL exploration** — corpus headlines, top conditions, full SOAP notes,
@@ -212,7 +212,7 @@ duckdb docs/demo/notebooks/demo.duckdb -ui # opens http://localhost:42
212212

213213
20 SQL cells over the Delta tables; see [`docs/demo/notebooks/README.md`](demo/notebooks/README.md)
214214
for the per-cell guide and how to regenerate the `.duckdb` (gitignored) if missing.
215-
For recording a portfolio demo video around it, see [`docs/demo/PLAYBOOK.md`](demo/PLAYBOOK.md).
215+
For recording a demo video around it, see [`docs/demo/PLAYBOOK.md`](demo/PLAYBOOK.md).
216216

217217
---
218218

@@ -231,8 +231,8 @@ export DAGSTER_HOME="$PWD/dagster_home" && mkdir -p "$DAGSTER_HOME"
231231
dagster dev # opens http://localhost:3000 (asset graph)
232232
```
233233

234-
`dagster dev` reads `[tool.dagster] module_name = "orchestration.definitions"` from
235-
`pyproject.toml`. The asset graph nodes are:
234+
`dagster dev` reads `[tool.dagster] module_name = "core.orchestration.dagster.definitions"`
235+
from `pyproject.toml`. The asset graph nodes are:
236236

237237
```
238238
bronze_fhir [cohort-partitioned]
@@ -275,7 +275,7 @@ Each asset surfaces inline metadata so the graph isn't just lineage — it's the
275275
schema** + one sample encounter rendered as a Markdown card (patient/date/age + SOAP
276276
note text + active conditions / medications / vitals / imaging).
277277

278-
The same renderings are reused by `python -m scripts.demo_walkthrough` for a CLI audience
278+
The same renderings are reused by `python -m core.scripts.demo_walkthrough` for a CLI audience
279279
and by the DuckDB UI notebook for an SQL audience (see §5 above and
280280
[`docs/demo/PLAYBOOK.md`](demo/PLAYBOOK.md) for the demo-video recording guide).
281281

@@ -315,7 +315,7 @@ manually once the cohorts of interest are present).
315315
Assets return `MaterializeResult` (metadata only) — **the `LakehousePlatform` writes the
316316
Delta bytes**, not a Dagster IOManager. Single persistence authority; Dagster owns the DAG
317317
and observability. The `[orchestration]` extra is *optional* by design — CI and the CLI
318-
path don't need it; `tests/test_dagster_defs.py` uses `pytest.importorskip` so the suite
318+
path don't need it; `core/tests/test_dagster_defs.py` uses `pytest.importorskip` so the suite
319319
collects cleanly without it.
320320

321321
---

docs/_archive/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Archive
2+
3+
Historical planning docs that are no longer load-bearing live here.
4+
5+
## When to archive vs delete vs keep
6+
7+
| Doc type | Action |
8+
|---|---|
9+
| Live planning (current/future) | Keep in `docs/roadmap/` |
10+
| Decision record | Keep in `docs/adr/` (never delete; mark "Superseded by ADR-N" instead) |
11+
| Operational doc (current) | Keep in `docs/` |
12+
| Planning doc for **done** work — load-bearing rationale | Move here (`docs/_archive/`) |
13+
| Planning doc for **done** work — replaced by ADRs / CHANGELOG entirely | Delete (git history is the archive) |
14+
| Planning doc for a **different repo** | Delete (belongs in that repo) |
15+
| Speculation / aspirational design — unbuilt | Delete; re-add when work starts |
16+
17+
## Naming
18+
19+
Preserve the original path inside the archive — e.g., if you archive
20+
`docs/roadmap/foo.md`, place it at `docs/_archive/roadmap/foo.md`.
21+
22+
This preserves the "where did this come from" signal without breaking
23+
the original location-based grouping.
24+
25+
## Don't drift
26+
27+
The archive is for genuinely-historical-but-still-referenced docs only.
28+
If a doc isn't referenced from anywhere current, just delete it —
29+
`git log --diff-filter=D --name-only` will find it later if needed.
30+
31+
A growing `_archive/` is a smell. Empty (or near-empty) is the goal.

docs/roadmap/scribe-iq-lakehouse-spec.md

Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ scribe-iq-lakehouse/
187187
│ └── config/
188188
│ └── lakehouse_config.json # OneLake paths, table names, thresholds
189189
190-
├── local/
190+
├── core/
191191
│ ├── ingest/
192192
│ │ ├── __init__.py
193193
│ │ ├── download.py # S3 → local Bronze (no-sign-request)
@@ -215,16 +215,24 @@ scribe-iq-lakehouse/
215215
│ │ ├── schema_registry.py # Expected schemas per Silver table
216216
│ │ └── validate.py # Row counts, null checks, referential integrity
217217
│ │
218-
│ └── pipeline.py # Local end-to-end orchestration
218+
│ ├── surfaces/cli/pipeline.py # Local end-to-end orchestration
219+
│ ├── tests/
220+
│ │ ├── fixtures/
221+
│ │ │ └── sample_bundle.json # 5-patient FHIR bundle for unit tests
222+
│ │ ├── test_fhir_parser.py
223+
│ │ ├── test_silver_soap_notes.py
224+
│ │ ├── test_silver_ecg.py
225+
│ │ ├── test_gold_encounter_summary.py
226+
│ │ └── test_validation.py
227+
│ └── scripts/ # gen_data_dictionary.py, gen_corpus_schema.py, demo_walkthrough.py
219228
220-
├── tests/
221-
│ ├── fixtures/
222-
│ │ └── sample_bundle.json # 5-patient FHIR bundle for unit tests
223-
│ ├── test_fhir_parser.py
224-
│ ├── test_silver_soap_notes.py
225-
│ ├── test_silver_ecg.py
226-
│ ├── test_gold_encounter_summary.py
227-
│ └── test_validation.py
229+
├── fabric/ # Fabric-specific platform + notebooks + deploy (ADR-017)
230+
│ ├── platform.py
231+
│ ├── notebooks/
232+
│ ├── environments/
233+
│ ├── deploy/
234+
│ ├── tests/
235+
│ └── docs/
228236
229237
├── docs/
230238
│ ├── index.md # MkDocs home (mirrors campus-rag pattern)
@@ -278,7 +286,7 @@ scribe-iq-lakehouse/
278286
**Local approach (fallback / delta-rs mirror):**
279287

280288
```python
281-
# local/ingest/download.py
289+
# core/ingest/download.py
282290
# aws s3 sync s3://synthea-open-data/coherent/fhir/ data/bronze/fhir/ --no-sign-request
283291
# Partition output: data/bronze/fhir/cohort=A/, cohort=B/, cohort=C/
284292
# Write partition manifest to data/bronze/_metadata/manifest.json
@@ -312,7 +320,7 @@ df = (spark.readStream
312320
**Local simulation:**
313321

314322
```python
315-
# local/ingest/streaming_sim.py
323+
# core/ingest/streaming_sim.py
316324
# Uses watchdog to monitor data/bronze/fhir/
317325
# Triggers silver transform when new cohort partition lands
318326
# Writes checkpoint to data/bronze/_checkpoints/
@@ -812,8 +820,8 @@ encounter_summary = (
812820
```yaml
813821
jobs:
814822
lint:
815-
- ruff check local/ tests/
816-
- black --check local/ tests/
823+
- ruff check core/ fabric/
824+
- black --check core/ fabric/
817825

818826
test:
819827
- pytest tests/ -v
@@ -822,7 +830,7 @@ jobs:
822830
# SOAP section detection, ECG metadata extraction
823831

824832
validate_schemas:
825-
- python -m local.validation.validate --fixture
833+
- python -m core.validation.validate --fixture
826834
# Runs validation rules against fixture data
827835
# Ensures schema contract is not broken on PR
828836
```
@@ -834,7 +842,7 @@ on:
834842
pull_request:
835843
paths:
836844
- schemas/**
837-
- local/validation/schema_registry.py
845+
- core/validation/schema_registry.py
838846

839847
jobs:
840848
schema_guard:
@@ -862,7 +870,7 @@ jobs:
862870

863871
---
864872

865-
## 17. Roadmap
873+
## 9. Roadmap
866874

867875
Every roadmap item is documented honestly — what it requires,
868876
why it is deferred, and what value it adds when built.
@@ -1090,7 +1098,7 @@ Clear separation maintained.
10901098

10911099
---
10921100

1093-
## 9. Implementation Sequence for Claude Code
1101+
## 10. Implementation Sequence for Claude Code
10941102

10951103
### Session 1 — Repo scaffold + FHIR parser foundation
10961104

@@ -1099,7 +1107,7 @@ Clear separation maintained.
10991107
2. Download 5-patient sample bundle from S3 (no-sign-request)
11001108
aws s3 cp s3://synthea-open-data/coherent/fhir/ tests/fixtures/
11011109
--no-sign-request --recursive --max-keys 5
1102-
3. local/transforms/fhir_parser.py
1110+
3. core/transforms/fhir_parser.py
11031111
- FHIRBundleParser class
11041112
- extract_patient, extract_encounter
11051113
- extract_soap_note (Base64 decode + SOAP section detection)
@@ -1115,26 +1123,26 @@ Goal: parser handles all resource types, tests pass on fixture data
11151123
### Session 2 — Local Bronze + Silver pipeline
11161124

11171125
```
1118-
1. local/ingest/download.py — S3 sync with cohort partitioning
1119-
2. local/ingest/bronze_landing.py — write Delta via delta-rs
1120-
3. local/ingest/streaming_sim.py — watchdog-based Auto Loader sim
1121-
4. local/transforms/silver_patient.py
1122-
5. local/transforms/silver_encounter.py
1123-
6. local/transforms/silver_clinical.py (Condition, Observation, Med, Procedure)
1124-
7. local/transforms/silver_soap_notes.py
1125-
8. local/transforms/silver_ecg.py
1126-
9. local/transforms/silver_imaging.py
1127-
10. local/transforms/silver_genomics.py
1128-
11. local/validation/schema_registry.py + validate.py
1129-
12. local/pipeline.py — end-to-end orchestration
1126+
1. core/ingest/download.py — S3 sync with cohort partitioning
1127+
2. core/ingest/bronze_landing.py — write Delta via delta-rs
1128+
3. core/ingest/streaming_sim.py — watchdog-based Auto Loader sim
1129+
4. core/transforms/silver_patient.py
1130+
5. core/transforms/silver_encounter.py
1131+
6. core/transforms/silver_clinical.py (Condition, Observation, Med, Procedure)
1132+
7. core/transforms/silver_soap_notes.py
1133+
8. core/transforms/silver_ecg.py
1134+
9. core/transforms/silver_imaging.py
1135+
10. core/transforms/silver_genomics.py
1136+
11. core/validation/schema_registry.py + validate.py
1137+
12. core/surfaces/cli/pipeline.py — end-to-end orchestration
11301138
Goal: full pipeline runs locally on 5-patient fixture, all Silver tables written
11311139
```
11321140

11331141
### Session 3 — Gold layer + corpus contract
11341142

11351143
```
1136-
1. local/gold/encounter_summary.py — denormalize Silver → Gold
1137-
2. local/gold/corpus_manifest.py — lineage tracking
1144+
1. core/gold/encounter_summary.py — denormalize Silver → Gold
1145+
2. core/gold/corpus_manifest.py — lineage tracking
11381146
3. schemas/ — JSON Schema files for all Silver + Gold tables
11391147
4. docs/CORPUS_CONTRACT.md — handoff schema for Ollama spec
11401148
5. tests/test_gold_encounter_summary.py
@@ -1156,7 +1164,7 @@ Goal: Gold encounter_summary populated, corpus contract documented
11561164
8. dagster + dagster-webserver in pyproject [dev]; ADR-015/016 written
11571165
Goal: `dagster dev` shows the medallion asset graph; per-cohort backfill works;
11581166
assets reuse the pure transforms — zero duplicate logic (third execution surface
1159-
alongside the CLI and the Fabric notebooks). local/pipeline.py CLI kept for CI.
1167+
alongside the CLI and the Fabric notebooks). core/surfaces/cli/pipeline.py CLI kept for CI.
11601168
```
11611169

11621170
### Session 5 — Fabric notebooks
@@ -1199,7 +1207,7 @@ Goal: Public repo, Fabric screenshots captured before trial expires
11991207

12001208
---
12011209

1202-
## 10. README Structure
1210+
## 11. README Structure
12031211

12041212
```
12051213
# scribe-iq-lakehouse
@@ -1221,7 +1229,7 @@ One-line: Production-pattern healthcare data lakehouse on Synthea Coherent.
12211229
## Streaming simulation (Auto Loader pattern explained briefly)
12221230
12231231
## Quick start
1224-
Local: python local/pipeline.py
1232+
Local: python -m core.surfaces.cli.pipeline
12251233
Fabric: Run notebooks 00 → 10 in sequence
12261234
12271235
## Silver tables (link to DATA_DICTIONARY.md)
@@ -1249,7 +1257,7 @@ One-line: Production-pattern healthcare data lakehouse on Synthea Coherent.
12491257

12501258
---
12511259

1252-
## 11. Fabric Trial — Priority Capture Checklist
1260+
## 12. Fabric Trial — Priority Capture Checklist
12531261

12541262
Before trial expires, ensure these are captured permanently:
12551263

@@ -1270,7 +1278,7 @@ The Delta format is identical — same notebooks, different storage path.
12701278

12711279
---
12721280

1273-
## 12. Downstream Connections
1281+
## 13. Downstream Connections
12741282

12751283
### → scribe-iq
12761284

@@ -1310,7 +1318,7 @@ The Delta format is identical — same notebooks, different storage path.
13101318

13111319
---
13121320

1313-
## 13. Local Spark + Ollama notes
1321+
## 14. Local Spark + Ollama notes
13141322

13151323
Local pipeline work runs on Apple Silicon (MPS). Key configs:
13161324

@@ -1333,7 +1341,7 @@ Ollama on Apple Silicon:
13331341

13341342
---
13351343

1336-
## 14. Fabric DevOps, Observability, and Production Engineering
1344+
## 15. Fabric DevOps, Observability, and Production Engineering
13371345

13381346
This section defines everything required to run the lakehouse pipeline
13391347
as a production-grade system in Fabric — not just notebooks that work once.
@@ -1776,7 +1784,7 @@ Data classification:
17761784

17771785
---
17781786

1779-
## 15. Fabric Demo Plan
1787+
## 16. Fabric Demo Plan
17801788

17811789
### 15.1 What Makes a Successful Demo
17821790

@@ -2030,7 +2038,7 @@ git clone https://github.com/sandeep-jay/scribe-iq-lakehouse
20302038
pip install -r requirements-lite.txt
20312039

20322040
# Download 50-patient sample from Synthea Coherent open data
2033-
python local/pipeline_lite.py --cohort sample
2041+
python -m core.surfaces.cli.pipeline --cohort sample
20342042

20352043
# Inspect Gold output via DuckDB
20362044
python -c "
@@ -2062,7 +2070,7 @@ rich>=13.0
20622070

20632071
---
20642072

2065-
## 16. Platform Abstraction Layer
2073+
## 17. Platform Abstraction Layer
20662074

20672075
Full specification — engine-agnostic design for multi-cloud portability.
20682076

@@ -2080,7 +2088,7 @@ Transform function
20802088
└── FabricPlatform → spark.createDataFrame(arrow) → Delta write
20812089
```
20822090

2083-
### Abstract interface — `local/platform/base.py`
2091+
### Abstract interface — `core/platform/base.py`
20842092

20852093
```python
20862094
from abc import ABC, abstractmethod
@@ -2137,7 +2145,7 @@ class LakehousePlatform(ABC):
21372145
### Platform implementations
21382146

21392147
```
2140-
local/platform/
2148+
core/platform/
21412149
base.py Abstract interface (build now)
21422150
factory.py Env var router (build now)
21432151
local_lite.py Polars + DuckDB + delta-rs (build week 2)
@@ -2148,20 +2156,20 @@ local/platform/
21482156
gcp.py Stub + migration notes (roadmap)
21492157
```
21502158

2151-
### Factory — `local/platform/factory.py`
2159+
### Factory — `core/platform/factory.py`
21522160

21532161
```python
21542162
import os
21552163

21562164
def get_platform() -> LakehousePlatform:
21572165
p = os.getenv("LAKEHOUSE_PLATFORM", "local_lite")
21582166
platforms = {
2159-
"fabric": "local.platform.fabric.FabricPlatform",
2160-
"databricks": "local.platform.databricks.DatabricksPlatform",
2161-
"aws": "local.platform.aws.AWSPlatform",
2162-
"gcp": "local.platform.gcp.GCPPlatform",
2163-
"local_spark": "local.platform.local_spark.LocalSparkPlatform",
2164-
"local_lite": "local.platform.local_lite.LocalLitePlatform",
2167+
"fabric": "fabric.platform.FabricPlatform",
2168+
"databricks": "databricks.platform.DatabricksPlatform",
2169+
"aws": "aws.platform.AWSPlatform",
2170+
"gcp": "gcp.platform.GCPPlatform",
2171+
"local_spark": "core.platform.local_spark.LocalSparkPlatform",
2172+
"local_lite": "core.platform.local_lite.LocalLitePlatform",
21652173
}
21662174
module_path, class_name = platforms[p].rsplit(".", 1)
21672175
module = importlib.import_module(module_path)
@@ -2173,7 +2181,7 @@ One env var. Zero code changes to migrate.
21732181
### Migration stub pattern
21742182

21752183
```python
2176-
# local/platform/databricks.py
2184+
# core/platform/databricks.py
21772185

21782186
class DatabricksPlatform(LakehousePlatform):
21792187
"""
@@ -2188,7 +2196,7 @@ class DatabricksPlatform(LakehousePlatform):
21882196
Delta Lake → identical API, no changes
21892197
MLflow → native, better than Fabric implementation
21902198
2191-
All transforms in local/transforms/ require zero changes.
2199+
All transforms in core/transforms/ require zero changes.
21922200
Estimated migration effort: 2-3 days.
21932201
"""
21942202

0 commit comments

Comments
 (0)