@@ -5,8 +5,119 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
55
66## [ Unreleased]
77
8- ### Session 5 (in progress) — Fabric end-to-end + dedup fix + Power BI
9- Plan: [ docs/roadmap/fabric-execution-plan.md] ( docs/roadmap/fabric-execution-plan.md ) . 7 phases; 1–3 complete, 4 in progress.
8+ ### Session 5 (in progress) — Fabric Spark-native rewrite (ADR-022) + dedup fix + Power BI
9+ Plan: [ docs/roadmap/fabric-execution-plan.md] ( docs/roadmap/fabric-execution-plan.md ) .
10+
11+ #### Milestone (2026-05-29 — first green cloud run)
12+ - ** Notebooks 00–10 ran successfully end-to-end on Fabric F4 capacity**
13+ against ` SAMPLE_SIZE=100 ` Coherent bundles. All 10 Silver tables +
14+ ` gold.encounter_summary ` + Bronze/Gold manifests materialized in the
15+ ` scribe_iq_synthea_coherent ` lakehouse.
16+ - Branch ` feat/fabric-spark-native ` pushed to ** both** GitHub (canonical
17+ mirror) and Azure DevOps (Fabric Git Integration source) via
18+ multi-push origin. Single ` git push ` fans out to both.
19+
20+ #### Added (2026-05-29)
21+ - ` fabric/notebooks/01_bronze_ingest.Notebook/ ` — self-contained Bronze
22+ ingest. Pulls Synthea Coherent from ` s3://synthea-open-data/coherent/ `
23+ via anonymous boto3, round-robin partitions into ` cohort=A,B,C ` under
24+ ` Files/bronze/fhir/ ` , writes an ` IngestManifest ` -shaped JSON under
25+ ` Files/bronze/_metadata/ ` . ` SAMPLE_SIZE ` knob for fast demo (` 100 ` ) vs
26+ full corpus (` None ` ).
27+ - ` fabric/environments/public_libraries.yml ` — pip-block file Fabric's
28+ Environment "Import .yml" UI accepts; pins ` boto3==1.35.36 ` +
29+ ` botocore==1.35.36 ` for reproducibility.
30+ - ` FabricPlatform.files_path(subpath) ` — Files/-rooted URI helper for
31+ non-table artifacts (Bronze JSON, Gold manifest). One place owns the
32+ GUID-vs-name path detail.
33+
34+ #### Changed (2026-05-29 — operational fixes from cloud run)
35+ - ` FabricPlatform.ensure_env ` now reads from Spark conf
36+ (` trident.workspace.id ` , ` trident.lakehouse.id ` ) instead of
37+ ` mssparkutils.env.getWorkspaceId() ` — the latter is a Synapse API
38+ not present on Fabric. Returns workspace + lakehouse GUIDs (not name);
39+ display name is best-effort, informational only.
40+ - OneLake paths now use lakehouse GUID throughout (drop ` .Lakehouse `
41+ suffix). Required for tenants with ` FriendlyNameSupportDisabled `
42+ (the trial tenant has this) — ` <name>.Lakehouse ` paths get HTTP 400.
43+ Notebooks 00, 01, 10 updated to use ` platform.files_path() ` instead
44+ of inline path construction.
45+ - ` 00_setup ` Gate 1 reads ` spark.conf.get("trident.workspace.id") `
46+ (drops the broken ` mssparkutils.env.getWorkspaceId ` call).
47+ - ` 01_bronze_ingest ` validation cell uses ` spark.read.text(wholetext=True) `
48+ to read the sample bundle — ` mssparkutils.fs.head ` silently truncates
49+ at ~ 100 KB even when a larger maxBytes is passed, breaking
50+ ` json.loads ` . Sample-histogram wrapped in try/except so a parse
51+ failure prints a one-liner instead of halting the cell (manifest
52+ write below it now always runs).
53+ - ` fabric/environments/lakehouse_env.yml ` — documentation-style spec
54+ updated to match ADR-022; drops ` pyarrow ` /` pydicom ` /` python-dateutil `
55+ (not used by the pure-Spark Fabric tier — Fabric runtime supplies
56+ pyarrow; pydicom is local-only; date parsing is Spark-native).
57+ - ` .github/workflows/fabric-deploy.yml ` renamed
58+ ` fabric-deploy.yml.disabled ` . User removed the ` fabric-prod ` GitHub
59+ Environment; the workflow's ` environment: fabric-prod ` would fail on
60+ trigger. Matches the existing ` aws-deploy.yml.disabled ` /
61+ ` databricks-deploy.yml.disabled ` convention. Active deploy path is
62+ Azure DevOps Git Integration + manual UI wheel upload.
63+
64+ #### Tests (2026-05-29)
65+ - ` test_fabric_platform.py ` updated for GUID-based API:
66+ ` test_storage_path_builds_onelake_uri ` rewritten for the GUID shape
67+ (no ` .Lakehouse ` suffix). New ` test_files_path_builds_onelake_uri `
68+ covers the helper. ` FabricPlatform(lakehouse_id=...) ` constructor
69+ arg replaces ` lakehouse_name=... ` for path-shape tests.
70+ - Full suite: 128 passed + 1 skipped (workspace-only).
71+
72+ #### Added (2026-05-29 — ADR-022 architecture pivot)
73+ - ** ADR-022** (Independent per-platform implementations) — supersedes ADR-002
74+ (LakehousePlatform ABC as universal contract), ADR-004 (pa.Table as
75+ cross-platform interchange), and ADR-020 (applyInPandas bridge — same-day
76+ supersession). Each platform tier now owns its complete Silver + Gold +
77+ validation stack written engine-native; cross-platform compat is by
78+ schema parity + lockstep CONTRACT_VERSION bumps, not code sharing.
79+ - ` fabric/transforms/ ` — Spark-native Silver layer (10 builders + union
80+ BUNDLE_SCHEMA + registry). Parses bundles via ` from_json ` and projects
81+ to Silver via Spark DataFrame ops; no Python bridge.
82+ - ` fabric/gold/ ` — Spark-native ` build_encounter_summary ` + ` corpus_manifest ` .
83+ Output schema matches ` core.gold.encounter_summary ` field-for-field.
84+ Includes a UUIDv5 expression synthesized in Spark (SHA1 + RFC 4122 bit
85+ twiddling) so ` summary_id ` stays deterministic across rebuilds.
86+ - ` fabric/validation/ ` — single ` .agg() ` per Silver table computes every
87+ metric in one pass; ingest_log schema matches core's.
88+ - ` .claude/rules/fabric-transforms.md ` — Fabric-tier transform rules.
89+
90+ #### Changed (2026-05-29)
91+ - ` fabric/platform.py ` slimmed: dropped ` write_silver(pa.Table) ` /
92+ ` read_silver() → pa.Table ` / ` write_gold(pa.Table) ` convenience wrappers,
93+ dropped legacy ` _write_delta(pa.Table) ` , dropped ` LakehousePlatform `
94+ inheritance. Spark DataFrames are the only interchange type. Added
95+ ` read_bronze_bundles_spark() ` as the canonical Bronze entry point.
96+ - ` core/platform/factory.py ` PLATFORMS dict drops ` fabric/databricks/aws/gcp `
97+ — independent tiers don't dispatch through the local factory.
98+ - All Fabric notebooks (00 + 02–10) rewritten: instantiate ` FabricPlatform() `
99+ directly (no factory, no env var), import from ` fabric.transforms ` /
100+ ` fabric.gold ` / ` fabric.validation ` , no ` applyInPandas ` . Notebook 10
101+ rewritten against the actual manifest keys (` gold_table ` ,
102+ ` silver_sources ` , ` row_count ` ) and Gold schema names (` soap_note_text ` ).
103+ - ` CLAUDE.md ` + ` .claude/rules/transforms.md ` + ` .claude/rules/notebooks.md `
104+ updated for the independence model. ADR index README.md flags 002/004/020
105+ as Superseded with links into ` docs/_archive/adr/ ` . ADR-017 amended in place.
106+
107+ #### Removed (2026-05-29)
108+ - ` fabric/spark_helpers.py ` (housed the ` applyInPandas ` bridge factory +
109+ pa→Spark schema converter; both dead under pure-Spark).
110+
111+ #### Tests (2026-05-29)
112+ - ` fabric/tests/test_fabric_platform.py ` — dropped subclass + abstract-method
113+ contract tests; rewrote the workspace round-trip to use Spark DataFrames
114+ against ` fabric.transforms.registry ` . Added ` test_name_attribute ` .
115+ - ` core/tests/test_platform_factory.py ` — added ` test_fabric_not_in_factory ` ;
116+ updated unbuilt-platform test to use ` local_spark ` placeholder.
117+ - Full suite: 128 passed + 1 skipped (workspace-only).
118+
119+ ### Session 5 — earlier phases (Fabric end-to-end + dedup fix + Power BI)
120+ Plan: [ docs/roadmap/fabric-execution-plan.md] ( docs/roadmap/fabric-execution-plan.md ) . Phases 1–3 complete (pre-pivot).
10121
11122#### Added
12123- ** ADR-019** (Silver MERGE idempotency) — pre-merge target-side dedup guard
0 commit comments