medallantic 0.27.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ .eggs/
7
+ dist/
8
+ build/
9
+ site/
10
+ .venv/
11
+ venv/
12
+ .env
13
+
14
+ # Tools
15
+ .pytest_cache/
16
+ .ruff_cache/
17
+ .mypy_cache/
18
+ .coverage
19
+ htmlcov/
20
+ # macOS
21
+ .DS_Store
22
+ **/.DS_Store
23
+ ._*
24
+ **/._*
25
+
26
+ examples/_file_storage_out/
27
+ examples/_generated_*.py
28
+ tmp_cli_contracts/
29
+ tmp_/
30
+
31
+ # Local durable workspace (reports, artifacts, schema history)
32
+ .etlantic/
33
+
34
+ # Local authoring artifacts (not part of the repo)
35
+ pipeline.definition.json
@@ -0,0 +1,133 @@
1
+ Metadata-Version: 2.4
2
+ Name: medallantic
3
+ Version: 0.27.0
4
+ Summary: Engine-agnostic medallion pipelines built on ETLantic.
5
+ Project-URL: Homepage, https://github.com/eddiethedean/etlantic
6
+ Project-URL: Documentation, https://github.com/eddiethedean/etlantic/tree/main/docs
7
+ Project-URL: Repository, https://github.com/eddiethedean/etlantic
8
+ Project-URL: Issues, https://github.com/eddiethedean/etlantic/issues
9
+ Project-URL: Changelog, https://github.com/eddiethedean/etlantic/blob/main/CHANGELOG.md
10
+ Author-email: Odo Matthews <odosmatthews@gmail.com>
11
+ License-Expression: MIT
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: etlantic<0.28,>=0.27.0
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Medallantic
25
+
26
+ Engine-agnostic medallion pipelines built on ETLantic.
27
+
28
+ Medallantic owns bronze/silver/gold authoring and conventions. ETLantic owns
29
+ the portable contracts, graph, validation, planning, execution lifecycle, and
30
+ plugin coordination underneath it. **ETLantic core never gains medallion
31
+ types.**
32
+
33
+ The current release is the renamed SparkForge migration adapter. It maps
34
+ SparkForge IR onto ordinary ETLantic `Extract` / `Step` / `Load`, `Profile`,
35
+ `RunSelection` / `RunIntent`, and `PipelineRunReport` surfaces. A native
36
+ engine-agnostic builder and live Spark/SQL parity are planned; see the
37
+ [roadmap](ROADMAP.md).
38
+
39
+ Documentation:
40
+
41
+ - [Documentation index](docs/README.md)
42
+ - [Getting started](docs/getting-started.md)
43
+ - [SparkForge migration](docs/sparkforge-migration.md)
44
+ - [Compatibility](docs/compatibility.md)
45
+ - [Architecture](docs/architecture.md)
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pip install 'etlantic==0.27.0' 'medallantic==0.27.0'
51
+ # or
52
+ pip install 'etlantic[medallantic]'
53
+ ```
54
+
55
+ The shipped adapter is **IR-only**: feed `SparkForgePipelineSpec` (JSON/YAML
56
+ fixtures or hand-built dataclasses). There is **no** live
57
+ `pipeline_builder` / SparkForge Python API bridge in this release.
58
+
59
+ The adapter is registered explicitly by importing `medallantic` and
60
+ calling its conversion helpers. The adapted result supplies an ordinary
61
+ ETLantic pipeline and profile; select execution plugins such as
62
+ `Profile.spark_engine="pyspark"` separately. Production profiles must
63
+ allowlist every trusted execution plugin.
64
+
65
+ ## Quick start (IR → Pipeline)
66
+
67
+ ```python
68
+ from medallantic import (
69
+ SparkForgePipelineSpec,
70
+ SparkForgeStepSpec,
71
+ StepKind,
72
+ LayerKind,
73
+ adapt_pipeline,
74
+ debug_request_from_sparkforge,
75
+ enrich_plan,
76
+ )
77
+ from etlantic.plan import plan_pipeline
78
+
79
+ spec = SparkForgePipelineSpec(
80
+ name="ecommerce",
81
+ schema="demo",
82
+ steps=(
83
+ SparkForgeStepSpec(
84
+ name="orders",
85
+ kind=StepKind.BRONZE_RULES,
86
+ layer=LayerKind.BRONZE,
87
+ table_name="bronze_orders",
88
+ ),
89
+ SparkForgeStepSpec(
90
+ name="clean_orders",
91
+ kind=StepKind.SILVER_TRANSFORM,
92
+ layer=LayerKind.SILVER,
93
+ source="orders",
94
+ table_name="silver_orders",
95
+ write_mode="overwrite",
96
+ ),
97
+ ),
98
+ )
99
+ adapted = adapt_pipeline(spec)
100
+ adapted.pipeline_cls.validate(profile=adapted.profile)
101
+ plan = enrich_plan(
102
+ plan_pipeline(adapted.pipeline_cls, profile=adapted.profile),
103
+ adapted,
104
+ )
105
+ request = debug_request_from_sparkforge(mode="incremental", skip_writes=True)
106
+ ```
107
+
108
+ ## Delivery direction
109
+
110
+ 1. **Plan-only** — generate/inspect ETLantic plans from SparkForge IR
111
+ (`strict_delta=False` to warn instead of fail when Delta caps are unknown)
112
+ 2. **Dual reporting** — `adapt_run_result` → `PipelineRunReport`
113
+ 3. **ETLantic planning** — selections/intents via `debug_request_from_sparkforge`
114
+ 4. **Plugin execution** — `Profile.spark_engine="pyspark"` / SQL plugins
115
+ 5. **Native facade** — Medallantic owns medallion authoring and retires the
116
+ duplicated legacy engine-specific builders
117
+
118
+ `transform_ref` / bronze `rules` emit `PMSF411` warnings: the adapter builds
119
+ passthrough transforms for planning parity; it does not execute SparkForge
120
+ callables. Write intents (including MERGE) are attached via `enrich_plan` for
121
+ orchestration; the local runtime still gates materialization with
122
+ `RunRequest.no_write`.
123
+
124
+ See `docs/11_DEVELOPMENT/MIGRATION_0_9_TO_0_10.md`.
125
+
126
+ ## Boundary
127
+
128
+ | Concern | Owner |
129
+ |---|---|
130
+ | bronze / silver / gold APIs | Medallantic |
131
+ | portable graph, plan, reports | ETLantic |
132
+ | legacy mapping + parity fixtures | Medallantic migration layer |
133
+ | physical execution | ETLantic engine and storage plugins |
@@ -0,0 +1,110 @@
1
+ # Medallantic
2
+
3
+ Engine-agnostic medallion pipelines built on ETLantic.
4
+
5
+ Medallantic owns bronze/silver/gold authoring and conventions. ETLantic owns
6
+ the portable contracts, graph, validation, planning, execution lifecycle, and
7
+ plugin coordination underneath it. **ETLantic core never gains medallion
8
+ types.**
9
+
10
+ The current release is the renamed SparkForge migration adapter. It maps
11
+ SparkForge IR onto ordinary ETLantic `Extract` / `Step` / `Load`, `Profile`,
12
+ `RunSelection` / `RunIntent`, and `PipelineRunReport` surfaces. A native
13
+ engine-agnostic builder and live Spark/SQL parity are planned; see the
14
+ [roadmap](ROADMAP.md).
15
+
16
+ Documentation:
17
+
18
+ - [Documentation index](docs/README.md)
19
+ - [Getting started](docs/getting-started.md)
20
+ - [SparkForge migration](docs/sparkforge-migration.md)
21
+ - [Compatibility](docs/compatibility.md)
22
+ - [Architecture](docs/architecture.md)
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install 'etlantic==0.27.0' 'medallantic==0.27.0'
28
+ # or
29
+ pip install 'etlantic[medallantic]'
30
+ ```
31
+
32
+ The shipped adapter is **IR-only**: feed `SparkForgePipelineSpec` (JSON/YAML
33
+ fixtures or hand-built dataclasses). There is **no** live
34
+ `pipeline_builder` / SparkForge Python API bridge in this release.
35
+
36
+ The adapter is registered explicitly by importing `medallantic` and
37
+ calling its conversion helpers. The adapted result supplies an ordinary
38
+ ETLantic pipeline and profile; select execution plugins such as
39
+ `Profile.spark_engine="pyspark"` separately. Production profiles must
40
+ allowlist every trusted execution plugin.
41
+
42
+ ## Quick start (IR → Pipeline)
43
+
44
+ ```python
45
+ from medallantic import (
46
+ SparkForgePipelineSpec,
47
+ SparkForgeStepSpec,
48
+ StepKind,
49
+ LayerKind,
50
+ adapt_pipeline,
51
+ debug_request_from_sparkforge,
52
+ enrich_plan,
53
+ )
54
+ from etlantic.plan import plan_pipeline
55
+
56
+ spec = SparkForgePipelineSpec(
57
+ name="ecommerce",
58
+ schema="demo",
59
+ steps=(
60
+ SparkForgeStepSpec(
61
+ name="orders",
62
+ kind=StepKind.BRONZE_RULES,
63
+ layer=LayerKind.BRONZE,
64
+ table_name="bronze_orders",
65
+ ),
66
+ SparkForgeStepSpec(
67
+ name="clean_orders",
68
+ kind=StepKind.SILVER_TRANSFORM,
69
+ layer=LayerKind.SILVER,
70
+ source="orders",
71
+ table_name="silver_orders",
72
+ write_mode="overwrite",
73
+ ),
74
+ ),
75
+ )
76
+ adapted = adapt_pipeline(spec)
77
+ adapted.pipeline_cls.validate(profile=adapted.profile)
78
+ plan = enrich_plan(
79
+ plan_pipeline(adapted.pipeline_cls, profile=adapted.profile),
80
+ adapted,
81
+ )
82
+ request = debug_request_from_sparkforge(mode="incremental", skip_writes=True)
83
+ ```
84
+
85
+ ## Delivery direction
86
+
87
+ 1. **Plan-only** — generate/inspect ETLantic plans from SparkForge IR
88
+ (`strict_delta=False` to warn instead of fail when Delta caps are unknown)
89
+ 2. **Dual reporting** — `adapt_run_result` → `PipelineRunReport`
90
+ 3. **ETLantic planning** — selections/intents via `debug_request_from_sparkforge`
91
+ 4. **Plugin execution** — `Profile.spark_engine="pyspark"` / SQL plugins
92
+ 5. **Native facade** — Medallantic owns medallion authoring and retires the
93
+ duplicated legacy engine-specific builders
94
+
95
+ `transform_ref` / bronze `rules` emit `PMSF411` warnings: the adapter builds
96
+ passthrough transforms for planning parity; it does not execute SparkForge
97
+ callables. Write intents (including MERGE) are attached via `enrich_plan` for
98
+ orchestration; the local runtime still gates materialization with
99
+ `RunRequest.no_write`.
100
+
101
+ See `docs/11_DEVELOPMENT/MIGRATION_0_9_TO_0_10.md`.
102
+
103
+ ## Boundary
104
+
105
+ | Concern | Owner |
106
+ |---|---|
107
+ | bronze / silver / gold APIs | Medallantic |
108
+ | portable graph, plan, reports | ETLantic |
109
+ | legacy mapping + parity fixtures | Medallantic migration layer |
110
+ | physical execution | ETLantic engine and storage plugins |
@@ -0,0 +1,372 @@
1
+ # Medallantic Roadmap
2
+
3
+ Medallantic is the engine-agnostic medallion pipeline facade built on
4
+ [ETLantic](https://github.com/eddiethedean/etlantic). It will provide one
5
+ bronze/silver/gold authoring model across local Python, Polars, Pandas, SQL,
6
+ and PySpark while delegating contracts, graph validation, deterministic
7
+ planning, execution coordination, reports, and plugin trust to ETLantic.
8
+
9
+ This roadmap defines “full parity” against both legacy SparkForge surfaces:
10
+
11
+ - `pipeline_builder` (PySpark/Sparkless)
12
+ - `sql_pipeline_builder` (SQLAlchemy/Moltres)
13
+
14
+ Parity means preserving supported user outcomes and semantics, not copying
15
+ the two legacy implementations or exposing backend objects in the portable
16
+ model.
17
+
18
+ ## Product boundary
19
+
20
+ Medallantic owns:
21
+
22
+ - bronze, silver, and gold vocabulary and conventions
23
+ - the fluent medallion builder and declarative configuration
24
+ - layer-aware dependency defaults and quality policies
25
+ - migration from both SparkForge builders
26
+ - medallion-oriented run results, explanations, and documentation
27
+
28
+ ETLantic owns:
29
+
30
+ - typed pipeline contracts and the logical graph
31
+ - validation, diagnostics, plans, run requests, and normalized reports
32
+ - artifact, state, lineage, security, and plugin coordination
33
+ - backend-neutral execution and compilation contracts
34
+
35
+ Execution plugins own:
36
+
37
+ - dataframe and relational execution
38
+ - SQL dialect and database transaction behavior
39
+ - Spark session and cluster behavior
40
+ - Delta Lake and other storage-specific operations
41
+ - engine-native expression compilation and optimization
42
+
43
+ Medallantic will not recreate separate Spark and SQL builder hierarchies.
44
+ Unsupported behavior must fail with a capability diagnostic; it must never
45
+ silently change semantics or select another engine.
46
+
47
+ ### Promoting capabilities into ETLantic
48
+
49
+ ETLantic may be extended whenever Medallantic reveals a capability that is
50
+ useful beyond medallion architecture. Promotion is expected for portable
51
+ concepts such as typed multi-output steps, state transitions, materialization
52
+ policies, transaction boundaries, plan diagnostics, or plugin capability
53
+ negotiation.
54
+
55
+ A capability belongs in ETLantic when it:
56
+
57
+ - has the same semantics outside bronze/silver/gold pipelines,
58
+ - must be shared by more than one facade or execution plugin,
59
+ - affects portable validation, planning, execution, reports, or security, and
60
+ - can be named without medallion or engine-specific terminology.
61
+
62
+ Layer names, layer defaults, medallion dependency conventions, and migration
63
+ compatibility remain in Medallantic. Each milestone may therefore include
64
+ prerequisite Etlantic work; those prerequisites should land with their own
65
+ core tests before Medallantic consumes them.
66
+
67
+ ## Current baseline
68
+
69
+ The renamed package starts with the former `etlantic-sparkforge` IR adapter.
70
+ It currently provides:
71
+
72
+ - SparkForge medallion IR parsing
73
+ - bronze/silver/gold-to-ETLantic graph adaptation
74
+ - dependency validation and cycle rejection
75
+ - layer quality-threshold mapping
76
+ - write-intent and retry-policy mapping
77
+ - run-intent and run-selection mapping
78
+ - plan enrichment
79
+ - SparkForge result normalization with secret redaction
80
+ - Delta capability checks
81
+ - IR fixture parity tests without SparkForge or PySpark installed
82
+
83
+ The baseline does **not** yet provide a native `MedallionPipeline` builder,
84
+ execute legacy transformation callables, or reach live Spark/SQL behavioral
85
+ parity.
86
+
87
+ ## Joint pre-1.0 sequence
88
+
89
+ Medallantic milestones are release-gated with ETLantic's pre-1.0 roadmap:
90
+
91
+ | ETLantic release | Medallantic phase | Joint focus |
92
+ |---|---|---|
93
+ | 0.27 | M0 (partial) | Rename, workspace/CI, first `medallantic` PyPI publish |
94
+ | 0.28 | M0 closeout | Quadruple-minor burn-in, Plugin `/1` freeze, facade boundary |
95
+ | 0.29 | M1 | Native medallion authoring and facade conformance |
96
+ | 0.30 | M2 | Portable quality/rule semantics |
97
+ | 0.31 | M3 | Execution, state, writes, and materialization |
98
+ | 0.32 | M4 | PySpark/SparkForge differential parity |
99
+ | 0.33 | M5 | SQLAlchemy/relational differential parity |
100
+ | 0.34 | M6 | Operations, evidence, and production readiness |
101
+ | 0.35 | M7 | Migration completion and joint freeze |
102
+ | 0.36–0.98 | — | Joint compatibility burn-in |
103
+ | 0.99 | — | Shared release-candidate rehearsal |
104
+
105
+ The [ETLantic roadmap](../../ROADMAP.md) is authoritative for the core
106
+ capability promoted at each phase and the joint exit gate. This document is
107
+ authoritative for Medallantic feature parity and migration scope.
108
+
109
+ ## Definition of full parity
110
+
111
+ Full parity is reached only when all required rows below have:
112
+
113
+ 1. a public Medallantic API,
114
+ 2. an explicit ETLantic mapping,
115
+ 3. conformance tests shared by all applicable engines,
116
+ 4. live PySpark and SQL integration tests where backend behavior matters,
117
+ 5. migration documentation and a declared compatibility result.
118
+
119
+ “Equivalent” permits an intentional API improvement. “Plugin” means the
120
+ portable intent is in Medallantic/ETLantic and the physical behavior is
121
+ implemented by a capability-bearing plugin. “Do not carry forward” records
122
+ legacy behavior that would be unsafe or architecturally incorrect.
123
+
124
+ ## Parity matrix
125
+
126
+ | Capability | Spark builder | SQL builder | Target | Priority |
127
+ |---|---:|---:|---|---|
128
+ | Fluent bronze/silver/gold builder | Yes | Yes | Native `MedallionPipeline`/builder | P0 |
129
+ | Partial pipelines (any layer subset) | Yes | Yes | Equivalent | P0 |
130
+ | Unique step names and construction-time validation | Yes | Yes | Equivalent diagnostics | P0 |
131
+ | Automatic dependency ordering | Yes | Yes | ETLantic deterministic planner | P0 |
132
+ | Cycle and missing-dependency detection | Yes | Yes | Fail closed with stable codes | P0 |
133
+ | Bronze source to silver wiring | Yes | Yes | Typed output references | P0 |
134
+ | Multiple silver inputs for gold | Yes | Yes | Named typed input ports | P0 |
135
+ | Prior silver result access | Yes | Yes | Run-scoped artifact context | P0 |
136
+ | Cross-schema reads and writes | Yes | Yes | Dataset bindings plus profiles | P0 |
137
+ | Layer descriptions and metadata | Yes | Partial | Portable metadata | P1 |
138
+ | Per-layer validation thresholds | Yes | Yes | Named medallion quality policy | P0 |
139
+ | Multiple rules per column | Yes | Yes | Contract-backed quality gates | P0 |
140
+ | Valid/invalid row separation | Yes | Yes | Typed accepted/rejected outputs | P0 |
141
+ | Validation-only steps and runs | Yes | Yes | `RunIntent.VALIDATE`, no writes | P0 |
142
+ | PySpark expression rules | Yes | No | PySpark compiler/plugin | P0 |
143
+ | String rule shorthand | Yes | No | Medallantic rule DSL | P1 |
144
+ | Moltres expression rules | No | Yes | SQL compiler compatibility | P0 |
145
+ | SQLAlchemy expression compatibility | No | Yes | SQL migration adapter | P0 |
146
+ | Callable transforms | Yes | Yes | Backend implementation refs | P0 |
147
+ | Initial load | Yes | Yes | Initialize intent | P0 |
148
+ | Incremental load | Yes | Yes | Incremental strategy plus state | P0 |
149
+ | Full refresh | Yes | Equivalent | Refresh intent | P0 |
150
+ | Bronze incremental column | Yes | Yes | Watermark strategy | P0 |
151
+ | Silver watermark column | Yes | Yes | State strategy | P0 |
152
+ | Append writes | Yes | Yes | Portable write intent | P0 |
153
+ | Overwrite writes | Yes | Yes | Portable write intent | P0 |
154
+ | Partition overwrite | Yes | Backend-specific | Plugin capability | P1 |
155
+ | Merge/upsert | Delta | Database-specific | Keyed merge capability | P0 |
156
+ | Ignore/skip-if-exists | Yes | Partial | Portable write intent | P1 |
157
+ | Schema compatibility checks | Yes | ORM model | Contracts plus sink checks | P0 |
158
+ | Schema override/evolution policy | Yes | ORM model | Explicit mutation policy | P1 |
159
+ | Table create/drop/refresh | Yes | Yes | Storage plugin | P0 |
160
+ | Silver initial recreate | N/A/overwrite | Yes | Refresh policy | P0 |
161
+ | Gold replace on every run | Yes | Yes | Layer default, overridable | P0 |
162
+ | SQLAlchemy ORM model table creation | No | Yes | SQL plugin compatibility | P0 |
163
+ | Primary-key validation | No | Yes | Merge/publication validation | P0 |
164
+ | Moltres lazy DataFrame transforms | No | Yes | SQL compiler | P0 |
165
+ | SQLAlchemy `Select`/compound selects | No | Yes | SQL compiler | P0 |
166
+ | Sync SQLAlchemy sessions | No | Yes | SQL runtime | P0 |
167
+ | Async SQLAlchemy sessions | No | Yes | SQL runtime | P1 |
168
+ | Multi-database SQLAlchemy support | No | Yes | Dialect conformance matrix | P1 |
169
+ | Spark and Sparkless execution | Yes | No | PySpark plus local test backend | P0 |
170
+ | JDBC sources and targets | Yes | No | SQL/PySpark I/O plugins | P1 |
171
+ | SQLAlchemy sources and targets from Spark | Yes | No | Explicit bridge capability | P2 |
172
+ | Delta merge | Yes | No | Delta plugin | P0 |
173
+ | Delta optimize, vacuum, history | Yes | No | Delta plugin | P1 |
174
+ | Delta time travel | Yes | No | Delta source capability | P1 |
175
+ | Run one / run until | Yes | No | ETLantic run selection | P0 |
176
+ | Stateful debug session | Yes | No | Medallantic convenience facade | P1 |
177
+ | Runtime parameter overrides | Yes | No | ETLantic run request | P1 |
178
+ | Transform/rule overrides for debug | Yes | No | Scoped implementation overrides | P1 |
179
+ | Downstream invalidation and rerun | Yes | No | Artifact provenance/invalidation | P1 |
180
+ | Skip writes during debugging | Yes | No | No-write materialization policy | P0 |
181
+ | Retry attempts and delays | Yes | Shared base | ETLantic retry policy | P0 |
182
+ | Contextual pipeline/step logging | Yes | Yes | Structured lifecycle events | P0 |
183
+ | Normalized run and step reports | Yes | Yes | Medallantic result facade | P0 |
184
+ | Counts, duration, validation and table metrics | Yes | Yes | Normalized report fields | P0 |
185
+ | Persisted execution-log writer | Yes | Shared base | Observability provider | P1 |
186
+ | Log table create/append/read | Yes | Shared base | Provider conformance | P1 |
187
+ | Trend and quality analytics | Yes | No | Event consumer/reference provider | P2 |
188
+ | Anomaly detection queries | Yes | No | Observability integration | P2 |
189
+ | Parallel candidates/execution groups | Analysis | Async SQL claim | Planner explain plus executor | P1 |
190
+ | Dependency recommendations | Yes | Shared base | Structured lint findings | P2 |
191
+ | Development/testing/production presets | Yes | Shared base | Profile templates | P1 |
192
+ | Serialization of configuration/results | Yes | Yes | Stable versioned schemas | P0 |
193
+ | Detailed errors with suggestions | Yes | Yes | Stable diagnostics/remediation | P0 |
194
+ | Engine-explicit configuration | Partial | Partial | Required profile selection | P0 |
195
+ | Silent runtime/mock auto-detection | Yes | N/A | Do not carry forward | Never |
196
+ | Automatic cycle breaking | Legacy analyzer | Legacy analyzer | Do not carry forward | Never |
197
+ | Separate public builders per engine | Yes | Yes | Do not carry forward | Never |
198
+
199
+ ## Delivery milestones
200
+
201
+ ### M0 / ETLantic 0.27–0.28 — Rename, release hygiene, and M0 closeout
202
+
203
+ **Shipped in 0.27.0**
204
+
205
+ - [x] Rename distribution to `medallantic`.
206
+ - [x] Rename import package to `medallantic`.
207
+ - [x] Rename workspace paths, tests, documentation, extras, and release checks.
208
+ - [x] Preserve SparkForge-specific conversion helper names where they describe
209
+ the legacy input format.
210
+ - [x] Publish the first `medallantic` distribution (`medallantic==0.27.0`).
211
+
212
+ **Owned by 0.28 (M0 closeout)**
213
+
214
+ - [ ] Decide whether to publish a final `etlantic-sparkforge` compatibility
215
+ release that depends on Medallantic and emits a deprecation warning.
216
+ - [ ] Document facade-package release category and ongoing trusted-publishing
217
+ evidence for `medallantic`.
218
+
219
+ Exit criteria: clean build, install, import, docs, lockfile, and adapter suite on
220
+ every release; core remains importable without Medallantic; no medallion
221
+ identifier in ETLantic wire schemas.
222
+
223
+ ### M1 / ETLantic 0.29 — Native medallion authoring
224
+
225
+ - [ ] Add `MedallionPipeline`, `MedallionBuilder`, `Bronze`, `Silver`, and
226
+ `Gold` public surfaces.
227
+ - [ ] Support fluent and declarative/serialized authoring.
228
+ - [ ] Map every layer definition to ordinary ETLantic nodes, typed ports,
229
+ quality gates, sinks, and policies.
230
+ - [ ] Support partial pipelines, multiple branches, prior-result references,
231
+ cross-schema bindings, descriptions, tags, and deterministic names.
232
+ - [ ] Add stable `MDL1xx` construction and graph diagnostics.
233
+ - [ ] Keep the current IR adapter as `medallantic.migrate.sparkforge`.
234
+
235
+ Exit criteria: representative SparkForge pipelines can be authored natively,
236
+ validated, planned, serialized, and explained without SparkForge installed.
237
+
238
+ ### M2 / ETLantic 0.30 — Quality and rules parity
239
+
240
+ - [ ] Define an engine-neutral rule AST/DSL for common shorthand:
241
+ `not_null`, comparisons, membership, ranges, regex, length, uniqueness,
242
+ and custom contract rules.
243
+ - [ ] Compile rules to ETLantic/ContractModel quality gates.
244
+ - [ ] Add PySpark, SQL/Moltres, Polars, and Pandas rule compilers.
245
+ - [ ] Return accepted and rejected typed artifacts with counts and reasons.
246
+ - [ ] Implement named per-layer defaults and per-step overrides.
247
+ - [ ] Make validation cost and unsupported-rule fallback visible in plans.
248
+
249
+ Exit criteria: shared fixtures produce equivalent pass/fail decisions,
250
+ accepted/rejected counts, and diagnostics across supported engines.
251
+
252
+ ### M3 / ETLantic 0.31 — Execution and materialization parity
253
+
254
+ - [ ] Execute native callable transforms through ETLantic implementation
255
+ references.
256
+ - [ ] Implement initial, incremental, refresh, standard, and validation-only
257
+ behavior.
258
+ - [ ] Map incremental columns and watermarks to atomic ETLantic state
259
+ transitions.
260
+ - [ ] Implement append, replace, keyed merge, skip-if-exists, and partition
261
+ replacement with capability checks.
262
+ - [ ] Implement layer defaults for bronze preservation, silver refresh, and
263
+ gold publication without hard-coding them into ETLantic core.
264
+ - [ ] Support retries only when the planned operation is safely retryable.
265
+ - [ ] Normalize run, step, validation, artifact, write, and state results.
266
+
267
+ Exit criteria: engine-neutral conformance fixtures pass for local, Polars,
268
+ Pandas, SQL, and PySpark where each engine advertises support.
269
+
270
+ ### M4 / ETLantic 0.32 — PySpark/SparkForge parity
271
+
272
+ - [ ] Add a live migration bridge for `PipelineBuilder` definitions.
273
+ - [ ] Support PySpark Column validation expressions and transform callables.
274
+ - [ ] Support real PySpark and Sparkless test modes explicitly.
275
+ - [ ] Cover schema/catalog management, cross-schema access, caches, JDBC I/O,
276
+ and Spark-native metrics through plugins.
277
+ - [ ] Add Delta capabilities for merge, optimize, vacuum, history, schema
278
+ evolution, and time travel.
279
+ - [ ] Reproduce run-one, run-until, no-write, parameter override, transform
280
+ override, rerun, and downstream invalidation workflows.
281
+ - [ ] Compare logical order, writes, validation outcomes, and normalized
282
+ reports against frozen SparkForge fixtures.
283
+
284
+ Exit criteria: every supported `pipeline_builder` fixture has a documented
285
+ `equivalent`, `plugin-dependent`, or `intentionally rejected` result.
286
+
287
+ ### M5 / ETLantic 0.33 — SQL pipeline-builder parity
288
+
289
+ - [ ] Add a live migration bridge for `SqlPipelineBuilder` definitions.
290
+ - [ ] Accept Moltres DataFrames/expressions and SQLAlchemy ORM, `Select`, and
291
+ compound-select sources during migration.
292
+ - [ ] Preserve lazy relational execution and avoid unnecessary table
293
+ round-trips between steps.
294
+ - [ ] Support model-driven table creation and primary-key validation.
295
+ - [ ] Match initial/incremental silver behavior and gold replacement defaults.
296
+ - [ ] Support sync and async SQLAlchemy execution with transaction rollback.
297
+ - [ ] Validate missing sources, ambiguous/duplicate columns, invalid transform
298
+ results, conversion failures, and write failures consistently.
299
+ - [ ] Establish dialect tiers and live CI for SQLite and PostgreSQL, followed
300
+ by additional SQLAlchemy dialects.
301
+
302
+ Exit criteria: the SQL parity matrix passes on SQLite and PostgreSQL, with
303
+ other dialect support accurately capability-gated.
304
+
305
+ ### M6 / ETLantic 0.34 — Operations, observability, and production readiness
306
+
307
+ - [ ] Provide medallion-oriented structured explain output.
308
+ - [ ] Emit normalized lifecycle events with pipeline, layer, step, attempt,
309
+ plan, run, and backend context.
310
+ - [ ] Add durable run-history provider conformance for create/append/read.
311
+ - [ ] Port trend, quality, performance, and anomaly analytics as optional
312
+ event consumers rather than core storage logic.
313
+ - [ ] Add development, testing, and production profile templates.
314
+ - [ ] Complete redaction, plugin allowlist, schema-mutation, concurrency,
315
+ cancellation, timeout, and recovery tests.
316
+ - [ ] Publish compatibility, security, performance, and production-readiness
317
+ documentation with explicit support tiers.
318
+
319
+ Exit criteria: Medallantic meets ETLantic’s production profile requirements
320
+ and has no undocumented fallback or mutation behavior.
321
+
322
+ ### M7 / ETLantic 0.35 — Migration completion
323
+
324
+ - [ ] Ship an automated scanner that inventories a SparkForge project and
325
+ emits a migration report.
326
+ - [ ] Generate native Medallantic definitions where conversion is safe.
327
+ - [ ] Produce stable diagnostics for manual conversion points.
328
+ - [ ] Maintain golden before/after plans and run reports.
329
+ - [ ] Publish versioned deprecation timelines for legacy imports.
330
+ - [ ] Remove transitional adapters only in a major release.
331
+
332
+ Exit criteria: both legacy builders have documented, tested migration paths
333
+ and all claimed parity rows are backed by conformance evidence.
334
+
335
+ ## Test strategy
336
+
337
+ The parity suite will have four layers:
338
+
339
+ 1. **IR tests** — no SparkForge, SQLAlchemy, or PySpark dependency.
340
+ 2. **Semantic conformance** — one logical fixture and normalized assertions
341
+ across local, Polars, Pandas, SQL, and PySpark.
342
+ 3. **Legacy differential tests** — run frozen SparkForge and Medallantic
343
+ fixtures and compare graph order, validation, writes, and reports.
344
+ 4. **Backend integration tests** — real SQLite/PostgreSQL, PySpark, and Delta
345
+ environments for physical semantics.
346
+
347
+ Every parity claim must identify its fixture, engines, capability requirements,
348
+ and normalized assertions. Unit-test coverage alone cannot establish backend
349
+ parity.
350
+
351
+ ## Compatibility policy
352
+
353
+ - SparkForge names may remain in migration-only APIs and serialized legacy IR.
354
+ - New authoring APIs use Medallantic names exclusively.
355
+ - Diagnostic codes and serialized fields already consumed externally remain
356
+ stable until a documented major-version migration.
357
+ - Backend-specific expressions are accepted only as implementation details;
358
+ portable definitions use contracts, rule AST nodes, and typed references.
359
+ - A capability gap is an explicit diagnostic, never an implicit fallback.
360
+
361
+ ## Release gates
362
+
363
+ A release may claim full parity only when:
364
+
365
+ - every P0 matrix row is complete,
366
+ - all P1 rows are complete or explicitly deferred with a documented support
367
+ limitation,
368
+ - both legacy differential suites pass,
369
+ - SQLite, PostgreSQL, PySpark, and Delta integration suites pass,
370
+ - package build/install/import and documentation checks pass,
371
+ - security/redaction and schema-mutation gates pass,
372
+ - the compatibility table is generated from test evidence.