zeromodel-artifacts 1.1.0__py3-none-any.whl

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,120 @@
1
+ from __future__ import annotations
2
+
3
+ from zeromodel.artifacts.adapted_report_persistence import (
4
+ ADAPTED_REPORT_ARTIFACT_KIND,
5
+ load_adapted_report,
6
+ store_adapted_report,
7
+ )
8
+ from zeromodel.artifacts.adapter import ReportAdapter
9
+ from zeromodel.artifacts.aggregate import (
10
+ CompiledReportClosureReceiptDTO,
11
+ ResolvedCompiledReportAggregateDTO,
12
+ build_compiled_report_closure_receipt,
13
+ load_compiled_report_aggregate,
14
+ load_compiled_report_vpm,
15
+ validate_compiled_report_aggregate,
16
+ )
17
+ from zeromodel.artifacts.canonicalization import canonical_json_bytes, sha256_digest
18
+ from zeromodel.artifacts.compatibility_schema import (
19
+ compute_compatibility_schema_id,
20
+ compute_report_semantics_id,
21
+ )
22
+ from zeromodel.artifacts.compiled_artifact import (
23
+ CellBindingDTO,
24
+ CompiledReportArtifactDTO,
25
+ CoreArtifactRefs,
26
+ )
27
+ from zeromodel.artifacts.core_artifact_persistence import (
28
+ LAYOUT_RECIPE_ARTIFACT_KIND,
29
+ SCORE_TABLE_ARTIFACT_KIND,
30
+ VPM_ARTIFACT_ARTIFACT_KIND,
31
+ load_layout_recipe,
32
+ load_score_table,
33
+ load_vpm_artifact,
34
+ store_layout_recipe,
35
+ store_score_table,
36
+ store_vpm_artifact,
37
+ )
38
+ from zeromodel.artifacts.ref import ARTIFACT_REF_VERSION, ArtifactRef, is_sha256_digest
39
+ from zeromodel.artifacts.report_adapter_contract_persistence import (
40
+ REPORT_ADAPTER_CONTRACT_ARTIFACT_KIND,
41
+ load_report_adapter_contract,
42
+ store_report_adapter_contract,
43
+ )
44
+ from zeromodel.artifacts.report_compiler import compile_report
45
+ from zeromodel.artifacts.report_dto import (
46
+ AdaptedDimensionDTO,
47
+ AdaptedReportDTO,
48
+ AdaptedSubjectDTO,
49
+ AdaptedValueDTO,
50
+ ReportAdapterContractDTO,
51
+ ReportFindingRefDTO,
52
+ SourceBindingDTO,
53
+ )
54
+ from zeromodel.artifacts.report_errors import (
55
+ ReportAdaptationError,
56
+ ReportCompilationError,
57
+ )
58
+ from zeromodel.artifacts.report_loading import load_compiled_report_artifact
59
+ from zeromodel.artifacts.score_semantics import ScoreSemantics
60
+ from zeromodel.artifacts.store import (
61
+ ArtifactIntegrityError,
62
+ ArtifactManifestConflictError,
63
+ ArtifactNotFoundError,
64
+ ArtifactResolver,
65
+ ArtifactStore,
66
+ InMemoryArtifactStore,
67
+ )
68
+
69
+ __all__ = [
70
+ "ADAPTED_REPORT_ARTIFACT_KIND",
71
+ "ARTIFACT_REF_VERSION",
72
+ "LAYOUT_RECIPE_ARTIFACT_KIND",
73
+ "REPORT_ADAPTER_CONTRACT_ARTIFACT_KIND",
74
+ "SCORE_TABLE_ARTIFACT_KIND",
75
+ "VPM_ARTIFACT_ARTIFACT_KIND",
76
+ "AdaptedDimensionDTO",
77
+ "AdaptedReportDTO",
78
+ "AdaptedSubjectDTO",
79
+ "AdaptedValueDTO",
80
+ "ArtifactIntegrityError",
81
+ "ArtifactManifestConflictError",
82
+ "ArtifactNotFoundError",
83
+ "ArtifactRef",
84
+ "ArtifactResolver",
85
+ "ArtifactStore",
86
+ "CellBindingDTO",
87
+ "CompiledReportArtifactDTO",
88
+ "CompiledReportClosureReceiptDTO",
89
+ "CoreArtifactRefs",
90
+ "InMemoryArtifactStore",
91
+ "ReportAdaptationError",
92
+ "ReportAdapter",
93
+ "ReportAdapterContractDTO",
94
+ "ReportCompilationError",
95
+ "ReportFindingRefDTO",
96
+ "ResolvedCompiledReportAggregateDTO",
97
+ "ScoreSemantics",
98
+ "SourceBindingDTO",
99
+ "build_compiled_report_closure_receipt",
100
+ "canonical_json_bytes",
101
+ "compile_report",
102
+ "compute_compatibility_schema_id",
103
+ "compute_report_semantics_id",
104
+ "is_sha256_digest",
105
+ "load_adapted_report",
106
+ "load_compiled_report_aggregate",
107
+ "load_compiled_report_artifact",
108
+ "load_compiled_report_vpm",
109
+ "load_layout_recipe",
110
+ "load_report_adapter_contract",
111
+ "load_score_table",
112
+ "load_vpm_artifact",
113
+ "sha256_digest",
114
+ "store_adapted_report",
115
+ "store_layout_recipe",
116
+ "store_report_adapter_contract",
117
+ "store_score_table",
118
+ "store_vpm_artifact",
119
+ "validate_compiled_report_aggregate",
120
+ ]
@@ -0,0 +1,91 @@
1
+ """Persist and reload `AdaptedReportDTO` as a first-class artifact.
2
+
3
+ Before this module, `AdaptedReportDTO` only ever existed as a discarded
4
+ local Python object inside `compile_report()`: the compiled report named it
5
+ by digest (`adapted_report_id`) but nothing made that digest resolvable
6
+ after the process exited. Raw values, per-value confidence, per-value
7
+ importance, source bindings, and parent-report lineage - none of which the
8
+ VPM matrix preserves completely - were unrecoverable once compilation
9
+ finished. This module closes that gap using the same decode-and-verify
10
+ pattern as `core_artifact_persistence.py`: resolve canonical bytes,
11
+ recompute the digest, require it to equal the requested ref's
12
+ `artifact_id`, decode, and reconstruct via `AdaptedReportDTO.__post_init__`
13
+ - never trusting a store's manifest as authoritative.
14
+
15
+ Canonical format: the stored payload is exactly
16
+ `adapted_report_signing_payload(adapted_report)` - the same payload
17
+ `AdaptedReportDTO.adapted_report_id` is computed over, with the
18
+ self-referential id field excluded. Because `ArtifactStore.put()` computes
19
+ `ref.artifact_id` as `sha256_digest(canonical_bytes)` over that same
20
+ payload, `ref.artifact_id == adapted_report.adapted_report_id` always
21
+ holds - the artifact-store identity and the DTO's own content identity are
22
+ the same digest, not two independent layers that happen to agree.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import json
28
+
29
+ from zeromodel.artifacts.canonicalization import canonical_json_bytes, sha256_digest
30
+ from zeromodel.artifacts.ref import ArtifactRef
31
+ from zeromodel.artifacts.report_decode import (
32
+ decode_attributes,
33
+ decode_dimension,
34
+ decode_subject,
35
+ decode_value,
36
+ )
37
+ from zeromodel.artifacts.report_dto import (
38
+ AdaptedReportDTO,
39
+ adapted_report_signing_payload,
40
+ )
41
+ from zeromodel.artifacts.report_errors import ReportCompilationError
42
+ from zeromodel.artifacts.store import ArtifactResolver, ArtifactStore
43
+
44
+ ADAPTED_REPORT_ARTIFACT_KIND = "zeromodel.artifacts.adapted-report/v1"
45
+
46
+
47
+ def store_adapted_report(
48
+ adapted_report: AdaptedReportDTO, *, store: ArtifactStore
49
+ ) -> ArtifactRef:
50
+ canonical_bytes = canonical_json_bytes(
51
+ adapted_report_signing_payload(adapted_report)
52
+ )
53
+ ref = store.put(ADAPTED_REPORT_ARTIFACT_KIND, canonical_bytes, manifest=None)
54
+ if ref.artifact_id != adapted_report.adapted_report_id:
55
+ raise ReportCompilationError(
56
+ "stored adapted-report digest does not match adapted_report_id "
57
+ f"(stored={ref.artifact_id}, adapted_report_id={adapted_report.adapted_report_id})"
58
+ )
59
+ return ref
60
+
61
+
62
+ def load_adapted_report(
63
+ ref: ArtifactRef, *, resolver: ArtifactResolver
64
+ ) -> AdaptedReportDTO:
65
+ if ref.artifact_kind != ADAPTED_REPORT_ARTIFACT_KIND:
66
+ raise ReportCompilationError(
67
+ f"load_adapted_report requires artifact_kind={ADAPTED_REPORT_ARTIFACT_KIND!r}, "
68
+ f"got {ref.artifact_kind!r}"
69
+ )
70
+ canonical_bytes = resolver.resolve_canonical_bytes(ref)
71
+ actual_digest = sha256_digest(canonical_bytes)
72
+ if actual_digest != ref.artifact_id:
73
+ raise ReportCompilationError(
74
+ f"resolved canonical bytes for {ref.artifact_id} do not hash to the requested id "
75
+ f"(got {actual_digest})"
76
+ )
77
+ payload = json.loads(canonical_bytes)
78
+
79
+ return AdaptedReportDTO(
80
+ adapted_report_id=ref.artifact_id,
81
+ report_id=payload["report_id"],
82
+ report_kind=payload["report_kind"],
83
+ adapter_contract_id=payload["adapter_contract_id"],
84
+ compatibility_id=payload["compatibility_id"],
85
+ subjects=tuple(decode_subject(item) for item in payload["subjects"]),
86
+ dimensions=tuple(decode_dimension(item) for item in payload["dimensions"]),
87
+ values=tuple(decode_value(item) for item in payload["values"]),
88
+ parent_report_ids=tuple(payload["parent_report_ids"]),
89
+ attributes=decode_attributes(payload["attributes"]),
90
+ spec_version=payload["spec_version"],
91
+ )
@@ -0,0 +1,30 @@
1
+ """The adapter protocol - the ingress boundary for domain reports.
2
+
3
+ Concrete adapters live in the external application (e.g.
4
+ `writer.integrations.zeromodel.AIArtifactReportAdapter`), never in this
5
+ package. An adapter must not write directly to an `ArtifactStore`,
6
+ construct rendered images, or calculate artifact identity itself - it only
7
+ translates one typed domain report into a neutral `AdaptedReportDTO`;
8
+ `compile_report` (see `report_compiler.py`) owns validation and identity.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Generic, Protocol, TypeVar, runtime_checkable
14
+
15
+ from zeromodel.artifacts.report_dto import AdaptedReportDTO, ReportAdapterContractDTO
16
+
17
+ ReportT = TypeVar("ReportT", contravariant=True)
18
+
19
+
20
+ @runtime_checkable
21
+ class ReportAdapter(Protocol, Generic[ReportT]):
22
+ """Domain-owned translation from one typed report into neutral ZeroModel form."""
23
+
24
+ def contract(self) -> ReportAdapterContractDTO:
25
+ """Return the stable contract governing this adapter's translation."""
26
+ ...
27
+
28
+ def adapt(self, report: ReportT) -> AdaptedReportDTO:
29
+ """Convert one domain report into the neutral ZeroModel report form."""
30
+ ...