cricore 0.6.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 (36) hide show
  1. cricore-0.6.0/LICENSE +17 -0
  2. cricore-0.6.0/PKG-INFO +263 -0
  3. cricore-0.6.0/README.md +239 -0
  4. cricore-0.6.0/pyproject.toml +42 -0
  5. cricore-0.6.0/setup.cfg +4 -0
  6. cricore-0.6.0/src/cricore/__init__.py +20 -0
  7. cricore-0.6.0/src/cricore/attestation/__init__.py +0 -0
  8. cricore-0.6.0/src/cricore/cli/__init__.py +0 -0
  9. cricore-0.6.0/src/cricore/contract/__init__.py +0 -0
  10. cricore-0.6.0/src/cricore/contract/loader.py +109 -0
  11. cricore-0.6.0/src/cricore/enforcement/__init__.py +0 -0
  12. cricore-0.6.0/src/cricore/enforcement/execution.py +158 -0
  13. cricore-0.6.0/src/cricore/enforcement/independence.py +239 -0
  14. cricore-0.6.0/src/cricore/enforcement/integrity.py +339 -0
  15. cricore-0.6.0/src/cricore/enforcement/lifecycle.py +282 -0
  16. cricore-0.6.0/src/cricore/enforcement/publication.py +135 -0
  17. cricore-0.6.0/src/cricore/enforcement/repository_integrity.py +138 -0
  18. cricore-0.6.0/src/cricore/enforcement/stage_ids.py +55 -0
  19. cricore-0.6.0/src/cricore/errors.py +42 -0
  20. cricore-0.6.0/src/cricore/integrity/binding.py +185 -0
  21. cricore-0.6.0/src/cricore/integrity/finalize.py +99 -0
  22. cricore-0.6.0/src/cricore/integrity/manifest.py +99 -0
  23. cricore-0.6.0/src/cricore/integrity/payload.py +100 -0
  24. cricore-0.6.0/src/cricore/integrity/repository.py +180 -0
  25. cricore-0.6.0/src/cricore/integrity/seal.py +160 -0
  26. cricore-0.6.0/src/cricore/loader.py +97 -0
  27. cricore-0.6.0/src/cricore/results/__init__.py +0 -0
  28. cricore-0.6.0/src/cricore/results/model.py +69 -0
  29. cricore-0.6.0/src/cricore/results/stage.py +64 -0
  30. cricore-0.6.0/src/cricore/run/__init__.py +0 -0
  31. cricore-0.6.0/src/cricore/run/paths.py +64 -0
  32. cricore-0.6.0/src/cricore/run/structure.py +211 -0
  33. cricore-0.6.0/src/cricore.egg-info/PKG-INFO +263 -0
  34. cricore-0.6.0/src/cricore.egg-info/SOURCES.txt +34 -0
  35. cricore-0.6.0/src/cricore.egg-info/dependency_links.txt +1 -0
  36. cricore-0.6.0/src/cricore.egg-info/top_level.txt +1 -0
cricore-0.6.0/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright (c) 2025 Shawn C. Wright and contributors
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
cricore-0.6.0/PKG-INFO ADDED
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.4
2
+ Name: cricore
3
+ Version: 0.6.0
4
+ Summary: CRI-CORE — Deterministic structural enforcement kernel for governed state transitions.
5
+ Author-email: "Shawn C. Wright" <swright@waveframelabs.org>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://waveframelabs.org
8
+ Project-URL: Source, https://github.com/Waveframe-Labs/CRI-CORE
9
+ Project-URL: Issues, https://github.com/Waveframe-Labs/CRI-CORE/issues
10
+ Keywords: governance,enforcement,deterministic,reproducibility,separation-of-duties
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: license-file
24
+
25
+ ---
26
+ title: "CRI-CORE — Deterministic Enforcement Kernel"
27
+ filetype: "documentation"
28
+ type: "repository-overview"
29
+ domain: "enforcement"
30
+ version: "0.6.0"
31
+ doi: "TBD"
32
+ status: "Active"
33
+ created: "2026-02-19"
34
+ updated: "2026-03-02"
35
+
36
+ author:
37
+ name: "Shawn C. Wright"
38
+ email: "swright@waveframelabs.org"
39
+ orcid: "https://orcid.org/0009-0006-6043-9295"
40
+
41
+ maintainer:
42
+ name: "Waveframe Labs"
43
+ url: "https://waveframelabs.org"
44
+
45
+ license: "Apache-2.0"
46
+
47
+ copyright:
48
+ holder: "Waveframe Labs"
49
+ year: "2026"
50
+
51
+ ai_assisted: "partial"
52
+
53
+ dependencies: []
54
+
55
+ anchors:
56
+ - "CRI-CORE v0.6.0"
57
+ - "Deterministic Enforcement Kernel"
58
+ ---
59
+
60
+ # CRI-CORE
61
+
62
+ **CRI-CORE v0.6.0 --- Deterministic Enforcement Kernel**
63
+
64
+ CRI-CORE is a deterministic structural enforcement engine for governed
65
+ state transitions.
66
+
67
+ It evaluates a run directory against explicit structural, authority,
68
+ integrity, binding, sealing, and publication constraints and returns a
69
+ single authoritative mutation decision.
70
+
71
+ The kernel does not interpret meaning.\
72
+ It evaluates structure and invariants only.
73
+
74
+ ------------------------------------------------------------------------
75
+
76
+ ## Installation
77
+
78
+ Install from PyPI:
79
+
80
+ pip install cricore
81
+
82
+ Requires Python 3.10+.
83
+
84
+ ------------------------------------------------------------------------
85
+
86
+ ## Minimal Usage
87
+
88
+ The supported public entrypoint is:
89
+
90
+ from cricore.enforcement.execution import run_enforcement_pipeline
91
+
92
+ Example:
93
+
94
+ from cricore.enforcement.execution import run_enforcement_pipeline
95
+
96
+ results, commit_allowed = run_enforcement_pipeline(
97
+ run_path=".",
98
+ expected_contract_version="0.3.0"
99
+ )
100
+
101
+ The function returns:
102
+
103
+ (results: List[StageResult], commit_allowed: bool)
104
+
105
+ `commit_allowed` is the sole commit authorization signal.
106
+
107
+ ------------------------------------------------------------------------
108
+
109
+ ## Core Model
110
+
111
+ Exploration (high velocity, non-deterministic)
112
+
113
+ Deterministic structural gate (CRI-CORE)
114
+
115
+ Governed state mutation
116
+
117
+ The kernel ensures that only structurally valid and cryptographically
118
+ sealed runs are permitted to mutate governed state.
119
+
120
+ ------------------------------------------------------------------------
121
+
122
+ ## Enforcement Pipeline (v0.6.0)
123
+
124
+ Canonical stage order:
125
+
126
+ 1. run-structure\
127
+ 2. structure-contract-version-gate\
128
+ 3. independence\
129
+ 4. integrity (verification)\
130
+ 5. integrity-finalization\
131
+ 6. publication\
132
+ 7. publication-commit
133
+
134
+ The pipeline is deterministic and ordered.
135
+
136
+ ------------------------------------------------------------------------
137
+
138
+ ## Contract-Version Behavior
139
+
140
+ CRI-CORE enforces versioned structural guarantees:
141
+
142
+ For `contract_version < 0.3.0`: - Structural validation - Independence
143
+ enforcement - Integrity manifest verification
144
+
145
+ For `contract_version ≥ 0.3.0`: - binding.json required - SEAL.json
146
+ required - Strict cryptographic seal validation - Immutable artifact
147
+ boundary enforcement
148
+
149
+ Enforcement meaning is isolated per declared contract version.\
150
+ Historical runs are validated under their declared version.
151
+
152
+ ------------------------------------------------------------------------
153
+
154
+ ## Independence Model
155
+
156
+ The kernel enforces structural role separation:
157
+
158
+ - Explicit actor identities
159
+ - Optional declared role requirements (`required_roles`)
160
+ - Strict prohibition on multi-role identity when roles are required
161
+ - Explicit override pathway (recorded, never implicit)
162
+
163
+ The kernel evaluates identity structure only.\
164
+ It does not evaluate competence or review quality.
165
+
166
+ ------------------------------------------------------------------------
167
+
168
+ ## Cryptographic Guarantees
169
+
170
+ Finalized runs must include:
171
+
172
+ - Deterministic SHA256 manifest
173
+ - Payload archive
174
+ - Structural binding artifact
175
+ - Deterministic SEAL.json
176
+
177
+ The seal covers:
178
+
179
+ - All run files (deterministic ordering)
180
+ - Binding artifact
181
+ - Manifest hash
182
+ - Payload hash
183
+
184
+ Any mutation changes the seal hash.
185
+
186
+ The seal provides tamper evidence.\
187
+ It is not a signature.
188
+
189
+ ------------------------------------------------------------------------
190
+
191
+ ## Atomic Commit Semantics
192
+
193
+ CRI-CORE does not mutate state.
194
+
195
+ It emits a deterministic authorization decision:
196
+
197
+ commit_allowed = publication_commit_stage.passed
198
+
199
+ The caller decides whether to mutate.
200
+
201
+ The kernel centralizes the commit decision.\
202
+ It does not enforce it outside its invocation boundary.
203
+
204
+ ------------------------------------------------------------------------
205
+
206
+ ## What CRI-CORE Does Not Do
207
+
208
+ CRI-CORE does not:
209
+
210
+ - Interpret lifecycle semantics
211
+ - Judge correctness of domain objects
212
+ - Evaluate epistemic sufficiency
213
+ - Enforce governance policy meaning
214
+ - Perform distributed consensus
215
+ - Prevent bypass outside invocation
216
+
217
+ It is a deterministic structural gate only.
218
+
219
+ ------------------------------------------------------------------------
220
+
221
+ ## Design Principles
222
+
223
+ - Deterministic evaluation
224
+ - No network calls
225
+ - No model calls
226
+ - No semantic inference
227
+ - Opaque reference handling
228
+ - Versioned enforcement meaning
229
+ - Strict immutability after finalization
230
+
231
+ ------------------------------------------------------------------------
232
+
233
+ ## Intended Use
234
+
235
+ CRI-CORE is designed to sit beneath:
236
+
237
+ - Workflow engines
238
+ - CI pipelines
239
+ - Agent execution runtimes
240
+ - Domain governance systems
241
+
242
+ It provides:
243
+
244
+ - Structural admissibility validation
245
+ - Cryptographic immutability guarantees
246
+ - Centralized commit authorization
247
+
248
+ It is domain-agnostic.
249
+
250
+ ------------------------------------------------------------------------
251
+
252
+ ## Status
253
+
254
+ v0.6.0 represents the first public PyPI distribution of CRI-CORE.
255
+
256
+ The enforcement interface is stable within the 0.x series but may evolve
257
+ prior to 1.0.
258
+
259
+ ---
260
+
261
+ <div align="center">
262
+ <sub>© 2025 Waveframe Labs — Independent Open-Science Research Entity • Governed under the Aurora Research Initiative (ARI)</sub>
263
+ </div>
@@ -0,0 +1,239 @@
1
+ ---
2
+ title: "CRI-CORE — Deterministic Enforcement Kernel"
3
+ filetype: "documentation"
4
+ type: "repository-overview"
5
+ domain: "enforcement"
6
+ version: "0.6.0"
7
+ doi: "TBD"
8
+ status: "Active"
9
+ created: "2026-02-19"
10
+ updated: "2026-03-02"
11
+
12
+ author:
13
+ name: "Shawn C. Wright"
14
+ email: "swright@waveframelabs.org"
15
+ orcid: "https://orcid.org/0009-0006-6043-9295"
16
+
17
+ maintainer:
18
+ name: "Waveframe Labs"
19
+ url: "https://waveframelabs.org"
20
+
21
+ license: "Apache-2.0"
22
+
23
+ copyright:
24
+ holder: "Waveframe Labs"
25
+ year: "2026"
26
+
27
+ ai_assisted: "partial"
28
+
29
+ dependencies: []
30
+
31
+ anchors:
32
+ - "CRI-CORE v0.6.0"
33
+ - "Deterministic Enforcement Kernel"
34
+ ---
35
+
36
+ # CRI-CORE
37
+
38
+ **CRI-CORE v0.6.0 --- Deterministic Enforcement Kernel**
39
+
40
+ CRI-CORE is a deterministic structural enforcement engine for governed
41
+ state transitions.
42
+
43
+ It evaluates a run directory against explicit structural, authority,
44
+ integrity, binding, sealing, and publication constraints and returns a
45
+ single authoritative mutation decision.
46
+
47
+ The kernel does not interpret meaning.\
48
+ It evaluates structure and invariants only.
49
+
50
+ ------------------------------------------------------------------------
51
+
52
+ ## Installation
53
+
54
+ Install from PyPI:
55
+
56
+ pip install cricore
57
+
58
+ Requires Python 3.10+.
59
+
60
+ ------------------------------------------------------------------------
61
+
62
+ ## Minimal Usage
63
+
64
+ The supported public entrypoint is:
65
+
66
+ from cricore.enforcement.execution import run_enforcement_pipeline
67
+
68
+ Example:
69
+
70
+ from cricore.enforcement.execution import run_enforcement_pipeline
71
+
72
+ results, commit_allowed = run_enforcement_pipeline(
73
+ run_path=".",
74
+ expected_contract_version="0.3.0"
75
+ )
76
+
77
+ The function returns:
78
+
79
+ (results: List[StageResult], commit_allowed: bool)
80
+
81
+ `commit_allowed` is the sole commit authorization signal.
82
+
83
+ ------------------------------------------------------------------------
84
+
85
+ ## Core Model
86
+
87
+ Exploration (high velocity, non-deterministic)
88
+
89
+ Deterministic structural gate (CRI-CORE)
90
+
91
+ Governed state mutation
92
+
93
+ The kernel ensures that only structurally valid and cryptographically
94
+ sealed runs are permitted to mutate governed state.
95
+
96
+ ------------------------------------------------------------------------
97
+
98
+ ## Enforcement Pipeline (v0.6.0)
99
+
100
+ Canonical stage order:
101
+
102
+ 1. run-structure\
103
+ 2. structure-contract-version-gate\
104
+ 3. independence\
105
+ 4. integrity (verification)\
106
+ 5. integrity-finalization\
107
+ 6. publication\
108
+ 7. publication-commit
109
+
110
+ The pipeline is deterministic and ordered.
111
+
112
+ ------------------------------------------------------------------------
113
+
114
+ ## Contract-Version Behavior
115
+
116
+ CRI-CORE enforces versioned structural guarantees:
117
+
118
+ For `contract_version < 0.3.0`: - Structural validation - Independence
119
+ enforcement - Integrity manifest verification
120
+
121
+ For `contract_version ≥ 0.3.0`: - binding.json required - SEAL.json
122
+ required - Strict cryptographic seal validation - Immutable artifact
123
+ boundary enforcement
124
+
125
+ Enforcement meaning is isolated per declared contract version.\
126
+ Historical runs are validated under their declared version.
127
+
128
+ ------------------------------------------------------------------------
129
+
130
+ ## Independence Model
131
+
132
+ The kernel enforces structural role separation:
133
+
134
+ - Explicit actor identities
135
+ - Optional declared role requirements (`required_roles`)
136
+ - Strict prohibition on multi-role identity when roles are required
137
+ - Explicit override pathway (recorded, never implicit)
138
+
139
+ The kernel evaluates identity structure only.\
140
+ It does not evaluate competence or review quality.
141
+
142
+ ------------------------------------------------------------------------
143
+
144
+ ## Cryptographic Guarantees
145
+
146
+ Finalized runs must include:
147
+
148
+ - Deterministic SHA256 manifest
149
+ - Payload archive
150
+ - Structural binding artifact
151
+ - Deterministic SEAL.json
152
+
153
+ The seal covers:
154
+
155
+ - All run files (deterministic ordering)
156
+ - Binding artifact
157
+ - Manifest hash
158
+ - Payload hash
159
+
160
+ Any mutation changes the seal hash.
161
+
162
+ The seal provides tamper evidence.\
163
+ It is not a signature.
164
+
165
+ ------------------------------------------------------------------------
166
+
167
+ ## Atomic Commit Semantics
168
+
169
+ CRI-CORE does not mutate state.
170
+
171
+ It emits a deterministic authorization decision:
172
+
173
+ commit_allowed = publication_commit_stage.passed
174
+
175
+ The caller decides whether to mutate.
176
+
177
+ The kernel centralizes the commit decision.\
178
+ It does not enforce it outside its invocation boundary.
179
+
180
+ ------------------------------------------------------------------------
181
+
182
+ ## What CRI-CORE Does Not Do
183
+
184
+ CRI-CORE does not:
185
+
186
+ - Interpret lifecycle semantics
187
+ - Judge correctness of domain objects
188
+ - Evaluate epistemic sufficiency
189
+ - Enforce governance policy meaning
190
+ - Perform distributed consensus
191
+ - Prevent bypass outside invocation
192
+
193
+ It is a deterministic structural gate only.
194
+
195
+ ------------------------------------------------------------------------
196
+
197
+ ## Design Principles
198
+
199
+ - Deterministic evaluation
200
+ - No network calls
201
+ - No model calls
202
+ - No semantic inference
203
+ - Opaque reference handling
204
+ - Versioned enforcement meaning
205
+ - Strict immutability after finalization
206
+
207
+ ------------------------------------------------------------------------
208
+
209
+ ## Intended Use
210
+
211
+ CRI-CORE is designed to sit beneath:
212
+
213
+ - Workflow engines
214
+ - CI pipelines
215
+ - Agent execution runtimes
216
+ - Domain governance systems
217
+
218
+ It provides:
219
+
220
+ - Structural admissibility validation
221
+ - Cryptographic immutability guarantees
222
+ - Centralized commit authorization
223
+
224
+ It is domain-agnostic.
225
+
226
+ ------------------------------------------------------------------------
227
+
228
+ ## Status
229
+
230
+ v0.6.0 represents the first public PyPI distribution of CRI-CORE.
231
+
232
+ The enforcement interface is stable within the 0.x series but may evolve
233
+ prior to 1.0.
234
+
235
+ ---
236
+
237
+ <div align="center">
238
+ <sub>© 2025 Waveframe Labs — Independent Open-Science Research Entity • Governed under the Aurora Research Initiative (ARI)</sub>
239
+ </div>
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cricore"
7
+ version = "0.6.0"
8
+ description = "CRI-CORE — Deterministic structural enforcement kernel for governed state transitions."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "Apache-2.0" }
12
+
13
+ authors = [
14
+ { name = "Shawn C. Wright", email = "swright@waveframelabs.org" }
15
+ ]
16
+
17
+ keywords = ["governance", "enforcement", "deterministic", "reproducibility", "separation-of-duties"]
18
+
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Developers",
22
+ "Intended Audience :: Science/Research",
23
+ "License :: OSI Approved :: Apache Software License",
24
+ "Operating System :: OS Independent",
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ ]
30
+
31
+ dependencies = []
32
+
33
+ [project.urls]
34
+ Homepage = "https://waveframelabs.org"
35
+ Source = "https://github.com/Waveframe-Labs/CRI-CORE"
36
+ Issues = "https://github.com/Waveframe-Labs/CRI-CORE/issues"
37
+
38
+ [tool.setuptools]
39
+ package-dir = {"" = "src"}
40
+
41
+ [tool.setuptools.packages.find]
42
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,20 @@
1
+ """
2
+ CRI-CORE — Deterministic Enforcement Kernel
3
+ Public package surface.
4
+ """
5
+
6
+ from importlib.metadata import version, PackageNotFoundError
7
+
8
+ try:
9
+ __version__ = version("cricore")
10
+ except PackageNotFoundError:
11
+ __version__ = "0.6.0"
12
+
13
+
14
+ # Public API surface
15
+ from .enforcement.execution import run_enforcement_pipeline
16
+
17
+ __all__ = [
18
+ "__version__",
19
+ "run_enforcement_pipeline",
20
+ ]
File without changes
File without changes
File without changes
@@ -0,0 +1,109 @@
1
+ """
2
+ ---
3
+ title: "CRI-CORE Run Contract Declaration Loader"
4
+ filetype: "operational"
5
+ type: "specification"
6
+ domain: "enforcement"
7
+ version: "0.1.0"
8
+ doi: "TBD-0.1.0"
9
+ status: "Active"
10
+ created: "2026-02-09"
11
+ updated: "2026-02-11"
12
+
13
+ author:
14
+ name: "Shawn C. Wright"
15
+ email: "swright@waveframelabs.org"
16
+ orcid: "https://orcid.org/0009-0006-6043-9295"
17
+
18
+ maintainer:
19
+ name: "Waveframe Labs"
20
+ url: "https://waveframelabs.org"
21
+
22
+ license: "Apache-2.0"
23
+
24
+ copyright:
25
+ holder: "Waveframe Labs"
26
+ year: "2026"
27
+
28
+ ai_assisted: "partial"
29
+ ai_assistance_details: "AI-assisted implementation of a minimal structural loader for CRI run contract declarations, enforcing only presence and structural fields required by the CRI-CORE enforcement contract."
30
+
31
+ dependencies:
32
+ - "../errors.py"
33
+
34
+ anchors:
35
+ - "CRI-CORE-ContractDeclarationLoader-v0.1.0"
36
+ ---
37
+ """
38
+
39
+ from __future__ import annotations
40
+
41
+ import json
42
+ from pathlib import Path
43
+ from typing import Any, Mapping, Optional
44
+
45
+
46
+ class ContractDeclarationError(Exception):
47
+ """
48
+ Raised when a run contract declaration cannot be loaded or parsed.
49
+ """
50
+ pass
51
+
52
+
53
+ def load_contract_declaration(run_root: Path) -> Mapping[str, Any]:
54
+ """
55
+ Load and minimally parse runs/<RUN_ID>/contract.json.
56
+
57
+ Structural enforcement only:
58
+ - file exists
59
+ - valid JSON
60
+ - root is an object
61
+ """
62
+
63
+ contract_path = run_root / "contract.json"
64
+
65
+ if not contract_path.exists():
66
+ raise ContractDeclarationError("contract.json is missing")
67
+
68
+ if not contract_path.is_file():
69
+ raise ContractDeclarationError("contract.json is not a file")
70
+
71
+ try:
72
+ raw = contract_path.read_text(encoding="utf-8")
73
+ except OSError as exc:
74
+ raise ContractDeclarationError(
75
+ f"failed to read contract.json: {exc}"
76
+ ) from exc
77
+
78
+ try:
79
+ obj = json.loads(raw)
80
+ except json.JSONDecodeError as exc:
81
+ raise ContractDeclarationError(
82
+ f"invalid JSON in contract.json: {exc}"
83
+ ) from exc
84
+
85
+ if not isinstance(obj, Mapping):
86
+ raise ContractDeclarationError("contract.json must contain a JSON object")
87
+
88
+ return obj
89
+
90
+
91
+ def extract_contract_version(contract_obj: Mapping[str, Any]) -> Optional[str]:
92
+ value = contract_obj.get("contract_version")
93
+ if isinstance(value, str):
94
+ return value
95
+ return None
96
+
97
+
98
+ def extract_run_id(contract_obj: Mapping[str, Any]) -> Optional[str]:
99
+ value = contract_obj.get("run_id")
100
+ if isinstance(value, str):
101
+ return value
102
+ return None
103
+
104
+
105
+ def extract_created_utc(contract_obj: Mapping[str, Any]) -> Optional[str]:
106
+ value = contract_obj.get("created_utc")
107
+ if isinstance(value, str):
108
+ return value
109
+ return None
File without changes