eb-contracts 0.2.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.
Files changed (52) hide show
  1. eb_contracts-0.2.0/.github/workflows/ci.yml +33 -0
  2. eb_contracts-0.2.0/.github/workflows/pypi-smoke.yml +20 -0
  3. eb_contracts-0.2.0/.github/workflows/release.yml +18 -0
  4. eb_contracts-0.2.0/.gitignore +288 -0
  5. eb_contracts-0.2.0/LICENSE +28 -0
  6. eb_contracts-0.2.0/PKG-INFO +134 -0
  7. eb_contracts-0.2.0/README.md +101 -0
  8. eb_contracts-0.2.0/docs/api/definitions.md +7 -0
  9. eb_contracts-0.2.0/docs/api/migrate_forecast.md +7 -0
  10. eb_contracts-0.2.0/docs/api/validate.md +7 -0
  11. eb_contracts-0.2.0/docs/index.md +31 -0
  12. eb_contracts-0.2.0/llm.txt +107 -0
  13. eb_contracts-0.2.0/pyproject.toml +114 -0
  14. eb_contracts-0.2.0/src/eb_contracts/__init__.py +24 -0
  15. eb_contracts-0.2.0/src/eb_contracts/api/__init__.py +27 -0
  16. eb_contracts-0.2.0/src/eb_contracts/api/migrate_forecast.py +122 -0
  17. eb_contracts-0.2.0/src/eb_contracts/api/validate.py +81 -0
  18. eb_contracts-0.2.0/src/eb_contracts/contracts/__init__.py +9 -0
  19. eb_contracts-0.2.0/src/eb_contracts/contracts/_internal/__init__.py +8 -0
  20. eb_contracts-0.2.0/src/eb_contracts/contracts/_internal/runtime.py +48 -0
  21. eb_contracts-0.2.0/src/eb_contracts/contracts/_internal/typing.py +37 -0
  22. eb_contracts-0.2.0/src/eb_contracts/contracts/context/__init__.py +14 -0
  23. eb_contracts-0.2.0/src/eb_contracts/contracts/context/v1/__init__.py +8 -0
  24. eb_contracts-0.2.0/src/eb_contracts/contracts/context/v1/run_context.py +202 -0
  25. eb_contracts-0.2.0/src/eb_contracts/contracts/costs/__init__.py +14 -0
  26. eb_contracts-0.2.0/src/eb_contracts/contracts/costs/v1/__init__.py +8 -0
  27. eb_contracts-0.2.0/src/eb_contracts/contracts/costs/v1/cost_asymmetry_spec.py +143 -0
  28. eb_contracts-0.2.0/src/eb_contracts/contracts/demand_panel/__init__.py +24 -0
  29. eb_contracts-0.2.0/src/eb_contracts/contracts/demand_panel/v1/__init__.py +9 -0
  30. eb_contracts-0.2.0/src/eb_contracts/contracts/demand_panel/v1/panel_demand.py +239 -0
  31. eb_contracts-0.2.0/src/eb_contracts/contracts/forecast_panel/__init__.py +24 -0
  32. eb_contracts-0.2.0/src/eb_contracts/contracts/forecast_panel/v1/__init__.py +9 -0
  33. eb_contracts-0.2.0/src/eb_contracts/contracts/forecast_panel/v1/forecast_panel.py +195 -0
  34. eb_contracts-0.2.0/src/eb_contracts/contracts/readiness/v1/__init__.py +9 -0
  35. eb_contracts-0.2.0/src/eb_contracts/contracts/readiness/v1/panel_fpc_result.py +316 -0
  36. eb_contracts-0.2.0/src/eb_contracts/contracts/results/__init__.py +14 -0
  37. eb_contracts-0.2.0/src/eb_contracts/contracts/results/v1/__init__.py +9 -0
  38. eb_contracts-0.2.0/src/eb_contracts/contracts/results/v1/panel_point_result.py +117 -0
  39. eb_contracts-0.2.0/src/eb_contracts/definitions/__init__.py +123 -0
  40. eb_contracts-0.2.0/src/eb_contracts/definitions/conventions.py +129 -0
  41. eb_contracts-0.2.0/src/eb_contracts/definitions/glossary.py +103 -0
  42. eb_contracts-0.2.0/src/eb_contracts/definitions/semantics.py +134 -0
  43. eb_contracts-0.2.0/src/eb_contracts/definitions/units.py +136 -0
  44. eb_contracts-0.2.0/src/eb_contracts/validation/errors.py +29 -0
  45. eb_contracts-0.2.0/tests/api/test_validate.py +283 -0
  46. eb_contracts-0.2.0/tests/contracts/costs/v1/test_cost_asymmetry_spec.py +136 -0
  47. eb_contracts-0.2.0/tests/contracts/demand_panel/v1/test_panel_demand.py +231 -0
  48. eb_contracts-0.2.0/tests/contracts/forecast_panel/v1/test_forecast_panel.py +171 -0
  49. eb_contracts-0.2.0/tests/contracts/readiness/v1/test_panel_fpc_result.py +96 -0
  50. eb_contracts-0.2.0/tests/contracts/results/v1/test_panel_point_result.py +79 -0
  51. eb_contracts-0.2.0/tests/definitions/test_definitions.py +16 -0
  52. eb_contracts-0.2.0/tooling +1 -0
@@ -0,0 +1,33 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+ # Only trigger if relevant files change
8
+ paths-ignore:
9
+ - '**.md'
10
+ - 'docs/**'
11
+ - 'LICENSE'
12
+ workflow_dispatch: # Allows manual "Run workflow" trigger
13
+
14
+ # Cancel previous runs if you push new code to the same PR
15
+ concurrency:
16
+ group: ${{ github.workflow }}-${{ github.ref }}
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ ci:
21
+ # Use 'permissions' to be explicit for the called workflow
22
+ permissions:
23
+ contents: read
24
+ packages: read
25
+ uses: Economistician/eb-integration/.github/workflows/pr-gate.yml@main
26
+ with:
27
+ os: '["ubuntu-latest", "windows-latest"]'
28
+ python_versions: '["3.11", "3.12", "3.13"]'
29
+ tooling_python_version: "3.13"
30
+ run_precommit: true
31
+ enable_typecheck: true
32
+ import_module: "eb_contracts"
33
+ extras: "all"
@@ -0,0 +1,20 @@
1
+ name: PyPI Smoke Test
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 0 * * 0" # Weekly on Sundays
6
+ workflow_run:
7
+ workflows: ["PyPI Release"]
8
+ types:
9
+ - completed
10
+ workflow_dispatch: # Allows you to click "Run workflow" in GitHub UI
11
+
12
+ jobs:
13
+ smoke-test:
14
+ # Only run if the release was a success, OR if it's a scheduled/manual run
15
+ if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name != 'workflow_run' }}
16
+ uses: Economistician/eb-integration/.github/workflows/pypi-smoke.yml@main
17
+ with:
18
+ python-version: "3.12"
19
+ package: "eb-contracts"
20
+ import_module: "eb_contracts"
@@ -0,0 +1,18 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ release:
11
+ name: Call Centralized PyPI Release
12
+ permissions:
13
+ contents: read
14
+ uses: Economistician/eb-integration/.github/workflows/pypi-release.yml@main
15
+ with:
16
+ python-version: "3.12"
17
+ build-command: "python -m build --sdist --wheel"
18
+ secrets: inherit
@@ -0,0 +1,288 @@
1
+ ###############################################################################
2
+ # Byte-compiled / optimized / DLL files
3
+ ###############################################################################
4
+ __pycache__/
5
+ **/__pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+
10
+ ###############################################################################
11
+ # C extensions
12
+ ###############################################################################
13
+ *.so
14
+
15
+
16
+ ###############################################################################
17
+ # Distribution / packaging
18
+ ###############################################################################
19
+ .Python
20
+ build/
21
+ develop-eggs/
22
+ dist/
23
+ downloads/
24
+ eggs/
25
+ .eggs/
26
+ lib/
27
+ lib64/
28
+ parts/
29
+ sdist/
30
+ var/
31
+ wheels/
32
+ share/python-wheels/
33
+ *.egg-info/
34
+ .installed.cfg
35
+ *.egg
36
+ MANIFEST
37
+
38
+
39
+ ###############################################################################
40
+ # PyInstaller
41
+ ###############################################################################
42
+ # Usually these files are written by a python script from a template
43
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
44
+ *.manifest
45
+ *.spec
46
+
47
+
48
+ ###############################################################################
49
+ # Installer logs
50
+ ###############################################################################
51
+ pip-log.txt
52
+ pip-delete-this-directory.txt
53
+
54
+
55
+ ###############################################################################
56
+ # Unit test / coverage reports
57
+ ###############################################################################
58
+ htmlcov/
59
+ .tox/
60
+ .nox/
61
+ .coverage
62
+ .coverage.*
63
+ .cache
64
+ nosetests.xml
65
+ coverage.xml
66
+ *.cover
67
+ *.py.cover
68
+ .hypothesis/
69
+ .pytest_cache/
70
+ cover/
71
+
72
+
73
+ ###############################################################################
74
+ # Translations
75
+ ###############################################################################
76
+ *.mo
77
+ *.pot
78
+
79
+
80
+ ###############################################################################
81
+ # Django
82
+ ###############################################################################
83
+ *.log
84
+ local_settings.py
85
+ db.sqlite3
86
+ db.sqlite3-journal
87
+
88
+
89
+ ###############################################################################
90
+ # Flask
91
+ ###############################################################################
92
+ instance/
93
+ .webassets-cache
94
+
95
+
96
+ ###############################################################################
97
+ # Scrapy
98
+ ###############################################################################
99
+ .scrapy
100
+
101
+
102
+ ###############################################################################
103
+ # Sphinx documentation
104
+ ###############################################################################
105
+ docs/_build/
106
+
107
+
108
+ ###############################################################################
109
+ # PyBuilder
110
+ ###############################################################################
111
+ .pybuilder/
112
+ target/
113
+
114
+
115
+ ###############################################################################
116
+ # Jupyter Notebook
117
+ ###############################################################################
118
+ .ipynb_checkpoints/
119
+
120
+
121
+ ###############################################################################
122
+ # IPython
123
+ ###############################################################################
124
+ profile_default/
125
+ ipython_config.py
126
+
127
+
128
+ ###############################################################################
129
+ # pyenv
130
+ ###############################################################################
131
+ # .python-version
132
+
133
+
134
+ ###############################################################################
135
+ # pipenv
136
+ ###############################################################################
137
+ # Pipfile.lock
138
+
139
+
140
+ ###############################################################################
141
+ # UV
142
+ ###############################################################################
143
+ # uv.lock
144
+
145
+
146
+ ###############################################################################
147
+ # poetry
148
+ ###############################################################################
149
+ # poetry.lock
150
+ # poetry.toml
151
+
152
+
153
+ ###############################################################################
154
+ # pdm
155
+ ###############################################################################
156
+ .pdm-python
157
+ .pdm-build/
158
+ # pdm.lock
159
+ # pdm.toml
160
+
161
+
162
+ ###############################################################################
163
+ # pixi
164
+ ###############################################################################
165
+ .pixi
166
+ # pixi.lock
167
+
168
+
169
+ ###############################################################################
170
+ # PEP 582
171
+ ###############################################################################
172
+ __pypackages__/
173
+
174
+
175
+ ###############################################################################
176
+ # Celery
177
+ ###############################################################################
178
+ celerybeat-schedule
179
+ celerybeat.pid
180
+
181
+
182
+ ###############################################################################
183
+ # SageMath
184
+ ###############################################################################
185
+ *.sage.py
186
+
187
+
188
+ ###############################################################################
189
+ # Environments
190
+ ###############################################################################
191
+ .env
192
+ .envrc
193
+ .venv
194
+ env/
195
+ venv/
196
+ ENV/
197
+ env.bak/
198
+ venv.bak/
199
+
200
+
201
+ ###############################################################################
202
+ # Spyder
203
+ ###############################################################################
204
+ .spyderproject
205
+ .spyproject
206
+
207
+
208
+ ###############################################################################
209
+ # Rope
210
+ ###############################################################################
211
+ .ropeproject
212
+
213
+
214
+ ###############################################################################
215
+ # mkdocs
216
+ ###############################################################################
217
+ /site
218
+
219
+
220
+ ###############################################################################
221
+ # mypy
222
+ ###############################################################################
223
+ .mypy_cache/
224
+ .dmypy.json
225
+ dmypy.json
226
+
227
+
228
+ ###############################################################################
229
+ # Pyre
230
+ ###############################################################################
231
+ .pyre/
232
+
233
+
234
+ ###############################################################################
235
+ # pytype
236
+ ###############################################################################
237
+ .pytype/
238
+
239
+
240
+ ###############################################################################
241
+ # Cython debug symbols
242
+ ###############################################################################
243
+ cython_debug/
244
+
245
+
246
+ ###############################################################################
247
+ # PyCharm
248
+ ###############################################################################
249
+ # .idea/
250
+
251
+
252
+ ###############################################################################
253
+ # Abstra
254
+ ###############################################################################
255
+ .abstra/
256
+
257
+
258
+ ###############################################################################
259
+ # Visual Studio Code
260
+ ###############################################################################
261
+ # .vscode/
262
+
263
+
264
+ ###############################################################################
265
+ # Ruff
266
+ ###############################################################################
267
+ .ruff_cache/
268
+
269
+
270
+ ###############################################################################
271
+ # PyPI configuration
272
+ ###############################################################################
273
+ .pypirc
274
+
275
+
276
+ ###############################################################################
277
+ # Cursor
278
+ ###############################################################################
279
+ .cursorignore
280
+ .cursorindexingignore
281
+
282
+
283
+ ###############################################################################
284
+ # Marimo
285
+ ###############################################################################
286
+ marimo/_static/
287
+ marimo/_lsp/
288
+ __marimo__/
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Kyle Corrie
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: eb-contracts
3
+ Version: 0.2.0
4
+ Summary: Electric Barometer data contracts and validation utilities.
5
+ Project-URL: Homepage, https://github.com/Economistician/eb-contracts
6
+ Project-URL: Repository, https://github.com/Economistician/eb-contracts
7
+ Project-URL: Issues, https://github.com/Economistician/eb-contracts/issues
8
+ Author: Electric Barometer
9
+ License: BSD-3-Clause
10
+ License-File: LICENSE
11
+ Keywords: data-contracts,electric-barometer,forecasting,validation
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: BSD License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: pandas>=2.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
24
+ Requires-Dist: pyright>=1.1.380; extra == 'dev'
25
+ Requires-Dist: pytest>=8; extra == 'dev'
26
+ Requires-Dist: ruff>=0.6; extra == 'dev'
27
+ Provides-Extra: docs
28
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
29
+ Requires-Dist: mkdocs>=1.6; extra == 'docs'
30
+ Provides-Extra: test
31
+ Requires-Dist: pytest>=8; extra == 'test'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Electric Barometer · Contracts (`eb-contracts`)
35
+
36
+ ![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)
37
+
38
+ Data contract and validation layer for the Electric Barometer ecosystem, defining canonical schemas, semantics, and enforcement for forecasts, costs, results, and run context.
39
+
40
+ ---
41
+
42
+ ## Overview
43
+
44
+ This repository contains the data contract and validation layer of the Electric Barometer ecosystem. It defines the canonical schemas, semantics, and invariants that govern how forecasts, costs, results, and contextual metadata are represented, validated, and exchanged across systems.
45
+
46
+ Rather than producing forecasts, computing metrics, or applying optimization logic, this repository focuses on structural correctness and shared meaning: how data artifacts are shaped, what guarantees they provide, and how violations are detected and handled. By formalizing these contracts as versioned, validated artifacts, eb-contracts ensures that all downstream components operate on consistent, explicit, and auditable data interfaces—reducing ambiguity, preventing silent errors, and enabling long-term evolution without breaking consumers.
47
+
48
+ ---
49
+
50
+ ## Role in the Electric Barometer Ecosystem
51
+
52
+ `eb-contracts` defines the canonical data contracts and validation boundaries used throughout the Electric Barometer ecosystem. It is responsible for specifying how core data artifacts—such as forecasts, cost specifications, evaluation results, and run context—are structured, interpreted, and validated before they are consumed by downstream systems.
53
+
54
+ This repository focuses exclusively on data shape, semantic consistency, and enforcement. It does not generate forecasts, compute metrics, select parameters, perform optimization, or orchestrate evaluation workflows. Those responsibilities are handled by adjacent layers in the ecosystem that produce predictions, compute metric values, calibrate parameters, or apply decision logic in operational settings.
55
+
56
+ By separating data contracts and validation from computation and policy concerns, eb-contracts provides a stable, versioned interface layer that enables interoperability, reduces ambiguity, and ensures that all components of the Electric Barometer ecosystem operate on shared, explicit assumptions—supporting long-term evolution without breaking consumers.
57
+
58
+ ---
59
+
60
+ ## Installation
61
+
62
+ `eb-optimization` is distributed as a standard Python package.
63
+
64
+ ```bash
65
+ pip install eb-contracts
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Core Concepts
71
+
72
+ - **Canonical data contracts** — Core data artifacts (forecasts, cost specifications, results, and context) are represented using explicit, versioned schemas rather than implicit conventions or ad-hoc DataFrame shapes.
73
+
74
+ - **Semantic consistency** — Column names, units, grain, and meaning are standardized and enforced so that downstream systems can rely on shared interpretation rather than contextual knowledge or undocumented assumptions.
75
+
76
+ - **Validation as a boundary** — Contract validation establishes a clear boundary between “valid” and “invalid” data, preventing silent failures and making structural issues visible at ingestion time rather than during downstream computation.
77
+
78
+ - **Versioned evolution** — Contracts are versioned to allow schemas and semantics to evolve over time without breaking existing consumers, enabling forward progress while preserving backward compatibility.
79
+
80
+ - **Explicit migration** — Adaptation from external or legacy data formats into contract-compliant artifacts is performed through explicit migration utilities, avoiding implicit coercion or guesswork.
81
+
82
+ - **Separation of structure from logic** — Data shape and meaning are defined independently of metric computation, optimization, or execution logic, ensuring that structural correctness is not entangled with algorithmic behavior.
83
+
84
+ ---
85
+
86
+ ## Minimal Example
87
+
88
+ The example below illustrates a typical contract workflow using `eb-contracts`: adapting an external forecast frame into a canonical contract artifact and validating it at the system boundary.
89
+
90
+ ```python
91
+ import pandas as pd
92
+
93
+ from eb_contracts.migrate import (
94
+ PanelPointColumns,
95
+ to_panel_point_v1,
96
+ )
97
+ from eb_contracts.validate import panel_point_v1
98
+ from eb_contracts._runtime import set_validation_mode
99
+
100
+ # External (non-canonical) forecast data
101
+ raw = pd.DataFrame(
102
+ {
103
+ "store": ["A", "A"],
104
+ "timestamp": [
105
+ pd.Timestamp("2025-01-01 00:00:00"),
106
+ pd.Timestamp("2025-01-01 00:30:00"),
107
+ ],
108
+ "actual": [10.0, 12.0],
109
+ "forecast": [11.0, 13.0],
110
+ }
111
+ )
112
+
113
+ # Explicitly map external columns to the EB contract
114
+ columns = PanelPointColumns(
115
+ entity_id="store",
116
+ interval_start="timestamp",
117
+ y_true="actual",
118
+ y_pred="forecast",
119
+ )
120
+
121
+ # Enable strict validation at the contract boundary
122
+ with set_validation_mode("strict"):
123
+ forecast = to_panel_point_v1(raw, columns=columns)
124
+
125
+ # `forecast` is now a validated PanelPointForecastV1 artifact
126
+ print(type(forecast))
127
+ ```
128
+
129
+ ---
130
+
131
+ ## License
132
+
133
+ BSD 3-Clause License.
134
+ © 2025 Kyle Corrie.
@@ -0,0 +1,101 @@
1
+ # Electric Barometer · Contracts (`eb-contracts`)
2
+
3
+ ![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)
4
+
5
+ Data contract and validation layer for the Electric Barometer ecosystem, defining canonical schemas, semantics, and enforcement for forecasts, costs, results, and run context.
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ This repository contains the data contract and validation layer of the Electric Barometer ecosystem. It defines the canonical schemas, semantics, and invariants that govern how forecasts, costs, results, and contextual metadata are represented, validated, and exchanged across systems.
12
+
13
+ Rather than producing forecasts, computing metrics, or applying optimization logic, this repository focuses on structural correctness and shared meaning: how data artifacts are shaped, what guarantees they provide, and how violations are detected and handled. By formalizing these contracts as versioned, validated artifacts, eb-contracts ensures that all downstream components operate on consistent, explicit, and auditable data interfaces—reducing ambiguity, preventing silent errors, and enabling long-term evolution without breaking consumers.
14
+
15
+ ---
16
+
17
+ ## Role in the Electric Barometer Ecosystem
18
+
19
+ `eb-contracts` defines the canonical data contracts and validation boundaries used throughout the Electric Barometer ecosystem. It is responsible for specifying how core data artifacts—such as forecasts, cost specifications, evaluation results, and run context—are structured, interpreted, and validated before they are consumed by downstream systems.
20
+
21
+ This repository focuses exclusively on data shape, semantic consistency, and enforcement. It does not generate forecasts, compute metrics, select parameters, perform optimization, or orchestrate evaluation workflows. Those responsibilities are handled by adjacent layers in the ecosystem that produce predictions, compute metric values, calibrate parameters, or apply decision logic in operational settings.
22
+
23
+ By separating data contracts and validation from computation and policy concerns, eb-contracts provides a stable, versioned interface layer that enables interoperability, reduces ambiguity, and ensures that all components of the Electric Barometer ecosystem operate on shared, explicit assumptions—supporting long-term evolution without breaking consumers.
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ `eb-optimization` is distributed as a standard Python package.
30
+
31
+ ```bash
32
+ pip install eb-contracts
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Core Concepts
38
+
39
+ - **Canonical data contracts** — Core data artifacts (forecasts, cost specifications, results, and context) are represented using explicit, versioned schemas rather than implicit conventions or ad-hoc DataFrame shapes.
40
+
41
+ - **Semantic consistency** — Column names, units, grain, and meaning are standardized and enforced so that downstream systems can rely on shared interpretation rather than contextual knowledge or undocumented assumptions.
42
+
43
+ - **Validation as a boundary** — Contract validation establishes a clear boundary between “valid” and “invalid” data, preventing silent failures and making structural issues visible at ingestion time rather than during downstream computation.
44
+
45
+ - **Versioned evolution** — Contracts are versioned to allow schemas and semantics to evolve over time without breaking existing consumers, enabling forward progress while preserving backward compatibility.
46
+
47
+ - **Explicit migration** — Adaptation from external or legacy data formats into contract-compliant artifacts is performed through explicit migration utilities, avoiding implicit coercion or guesswork.
48
+
49
+ - **Separation of structure from logic** — Data shape and meaning are defined independently of metric computation, optimization, or execution logic, ensuring that structural correctness is not entangled with algorithmic behavior.
50
+
51
+ ---
52
+
53
+ ## Minimal Example
54
+
55
+ The example below illustrates a typical contract workflow using `eb-contracts`: adapting an external forecast frame into a canonical contract artifact and validating it at the system boundary.
56
+
57
+ ```python
58
+ import pandas as pd
59
+
60
+ from eb_contracts.migrate import (
61
+ PanelPointColumns,
62
+ to_panel_point_v1,
63
+ )
64
+ from eb_contracts.validate import panel_point_v1
65
+ from eb_contracts._runtime import set_validation_mode
66
+
67
+ # External (non-canonical) forecast data
68
+ raw = pd.DataFrame(
69
+ {
70
+ "store": ["A", "A"],
71
+ "timestamp": [
72
+ pd.Timestamp("2025-01-01 00:00:00"),
73
+ pd.Timestamp("2025-01-01 00:30:00"),
74
+ ],
75
+ "actual": [10.0, 12.0],
76
+ "forecast": [11.0, 13.0],
77
+ }
78
+ )
79
+
80
+ # Explicitly map external columns to the EB contract
81
+ columns = PanelPointColumns(
82
+ entity_id="store",
83
+ interval_start="timestamp",
84
+ y_true="actual",
85
+ y_pred="forecast",
86
+ )
87
+
88
+ # Enable strict validation at the contract boundary
89
+ with set_validation_mode("strict"):
90
+ forecast = to_panel_point_v1(raw, columns=columns)
91
+
92
+ # `forecast` is now a validated PanelPointForecastV1 artifact
93
+ print(type(forecast))
94
+ ```
95
+
96
+ ---
97
+
98
+ ## License
99
+
100
+ BSD 3-Clause License.
101
+ © 2025 Kyle Corrie.
@@ -0,0 +1,7 @@
1
+ # Definitions
2
+
3
+ This section documents shared definitions and semantic primitives exposed by `eb-contracts`.
4
+
5
+ These definitions provide canonical constants, enums, and structural building blocks used across Electric Barometer contracts and APIs to ensure consistent interpretation of values and fields.
6
+
7
+ ::: eb_contracts.definitions
@@ -0,0 +1,7 @@
1
+ # Forecast migration
2
+
3
+ This section documents utilities for migrating forecast data between contract versions in `eb-contracts`.
4
+
5
+ These helpers support forward-compatible evolution of forecast schemas by transforming historical or legacy forecast structures into their current canonical representations.
6
+
7
+ ::: eb_contracts.api.migrate_forecast
@@ -0,0 +1,7 @@
1
+ # Forecast migration
2
+
3
+ This section documents utilities for migrating forecast data between contract versions in `eb-contracts`.
4
+
5
+ These helpers support forward-compatible evolution of forecast schemas by transforming historical or legacy forecast structures into their current canonical representations.
6
+
7
+ ::: eb_contracts.api.migrate_forecast
@@ -0,0 +1,31 @@
1
+ # eb-contracts
2
+
3
+ `eb-contracts` defines the canonical data contracts, schemas, and structural interfaces used across the Electric Barometer ecosystem.
4
+
5
+ This package establishes **shared meaning and shape**, ensuring that forecasts, evaluations, optimization outputs, and downstream systems interoperate consistently.
6
+
7
+ ## Scope
8
+
9
+ This package is responsible for:
10
+
11
+ - Defining canonical data structures and schemas
12
+ - Formalizing inputs and outputs exchanged between EB components
13
+ - Encoding shared assumptions about forecast results, costs, and runtime context
14
+ - Providing validation and migration utilities for contract evolution
15
+
16
+ It intentionally avoids implementing metrics, models, optimization logic, or workflows.
17
+
18
+ ## Contents
19
+
20
+ - **Core contracts**
21
+ Canonical representations for forecasts, results, costs, and runtime context
22
+
23
+ - **Validation utilities**
24
+ Tools for checking contract conformance and structural integrity
25
+
26
+ - **Migration support**
27
+ Helpers for evolving contracts across versions
28
+
29
+ ## API reference
30
+
31
+ - [Contract definitions](api/index.md)