ssot-core 0.2.17.dev1__tar.gz → 0.2.18.dev9__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.
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/PKG-INFO +10 -4
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/README.md +4 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/pyproject.toml +6 -4
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_core.egg-info/PKG-INFO +10 -4
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_core.egg-info/SOURCES.txt +7 -0
- ssot_core-0.2.18.dev9/src/ssot_core.egg-info/requires.txt +7 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/__init__.py +25 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/claims.py +22 -3
- ssot_core-0.2.18.dev9/src/ssot_registry/api/config.py +283 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/documents.py +103 -10
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/entity_ops.py +102 -12
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/init.py +3 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/lifecycle.py +3 -0
- ssot_core-0.2.18.dev9/src/ssot_registry/api/local_assurance.py +234 -0
- ssot_core-0.2.18.dev9/src/ssot_registry/api/origin.py +98 -0
- ssot_core-0.2.18.dev9/src/ssot_registry/api/packs.py +486 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/plan.py +6 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/status_sync.py +40 -16
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/test_execution.py +1 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/upgrade.py +78 -5
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/validate.py +4 -0
- ssot_core-0.2.18.dev9/src/ssot_registry/guards/__init__.py +53 -0
- ssot_core-0.2.18.dev9/src/ssot_registry/guards/claim_tier_gates.py +317 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/claim.py +2 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/document.py +35 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/enums.py +20 -4
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/evidence.py +1 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/feature.py +1 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/schema_version.py +1 -1
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/test.py +1 -0
- ssot_core-0.2.18.dev9/src/ssot_registry/templates/registry.full.json +1 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/templates/registry.minimal.json +1 -1
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/document_io.py +8 -4
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/__init__.py +4 -0
- ssot_core-0.2.18.dev9/src/ssot_registry/validators/claim_lineage.py +27 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/documents.py +26 -2
- ssot_core-0.2.18.dev9/src/ssot_registry/validators/origin.py +31 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/structure.py +50 -1
- ssot_core-0.2.17.dev1/src/ssot_core.egg-info/requires.txt +0 -6
- ssot_core-0.2.17.dev1/src/ssot_registry/guards/__init__.py +0 -23
- ssot_core-0.2.17.dev1/src/ssot_registry/templates/registry.full.json +0 -1
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/setup.cfg +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_core.egg-info/dependency_links.txt +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_core.egg-info/top_level.txt +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/__main__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/boundary.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/evidence.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/graph.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/load.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/profile_eval.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/profile_resolution.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/registry.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/release.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/api/save.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/adr_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/boundary_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/claim_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/common.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/evidence_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/feature_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/graph_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/init_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/issue_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/main.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/profile_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/registry_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/release_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/risk_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/spec_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/test_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/upgrade_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/cli/validate_cmd.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/graph/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/graph/export_dot.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/graph/export_json.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/certification.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/claim_closure.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/document_lifecycle.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/document_supersession.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/feature_claims.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/feature_requirements.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/lifecycle.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/profile_requirements.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/promotion.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/guards/publication.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/boundary.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/ids.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/issue.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/profile.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/registry.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/release.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/model/risk.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/reports/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/reports/certification_report.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/reports/summary.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/reports/validation_report.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/snapshots/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/snapshots/boundary_snapshot.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/snapshots/hashing.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/snapshots/published_snapshot.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/snapshots/release_snapshot.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/templates/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/__init__.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/errors.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/formatting.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/fs.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/jcs.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/jsonio.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/registry_lock.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/util/time.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/bidirectional.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/bounds.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/coverage.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/filesystem.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/identity.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/lifecycle.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/promotion.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/references.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/reservations.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/validators/tiers.py +0 -0
- {ssot_core-0.2.17.dev1 → ssot_core-0.2.18.dev9}/src/ssot_registry/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ssot-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.18.dev9
|
|
4
4
|
Summary: Core Python runtime, registry model, validation, and release workflow APIs for SSOT.
|
|
5
5
|
Author-email: Jacob Stewart <jacob@swarmauri.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
25
|
Classifier: Topic :: Database
|
|
25
26
|
Classifier: Topic :: File Formats :: JSON
|
|
26
27
|
Classifier: Topic :: File Formats :: JSON :: JSON Schema
|
|
@@ -32,11 +33,12 @@ Classifier: Topic :: Software Development :: Quality Assurance
|
|
|
32
33
|
Classifier: Topic :: Software Development :: Testing
|
|
33
34
|
Classifier: Topic :: System :: Archiving
|
|
34
35
|
Classifier: Topic :: Utilities
|
|
35
|
-
Requires-Python: <3.
|
|
36
|
+
Requires-Python: <3.15,>=3.10
|
|
36
37
|
Description-Content-Type: text/markdown
|
|
37
38
|
Requires-Dist: orjson<4.0,>=3.10
|
|
38
|
-
Requires-Dist: ssot-contracts==0.2.
|
|
39
|
-
Requires-Dist: ssot-
|
|
39
|
+
Requires-Dist: ssot-contracts==0.2.18.dev9
|
|
40
|
+
Requires-Dist: ssot-pack-contracts<0.3.0,>=0.2.17
|
|
41
|
+
Requires-Dist: ssot-views==0.2.18.dev9
|
|
40
42
|
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
41
43
|
|
|
42
44
|
<div align="center">
|
|
@@ -49,6 +51,10 @@ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
|
49
51
|
<a href="https://pypi.org/project/ssot-core/"><img src="https://img.shields.io/pypi/pyversions/ssot-core?label=Python" alt="Supported Python versions" /></a>
|
|
50
52
|
<a href="https://pepy.tech/project/ssot-core"><img src="https://static.pepy.tech/badge/ssot-core" alt="Downloads" /></a>
|
|
51
53
|
<a href="https://hits.sh/github.com/groupsum/ssot-registry/"><img src="https://hits.sh/github.com/groupsum/ssot-registry.svg?style=flat-square" alt="Hits" /></a>
|
|
54
|
+
<!-- ssot-schema-badges:start -->
|
|
55
|
+
<img src="https://img.shields.io/badge/schema_version-0.5.0-blue" alt="schema_version 0.5.0" />
|
|
56
|
+
<img src="https://img.shields.io/badge/migration%20coverage-12%2F12-brightgreen" alt="Migration coverage 12/12" />
|
|
57
|
+
<!-- ssot-schema-badges:end -->
|
|
52
58
|
</div>
|
|
53
59
|
|
|
54
60
|
`ssot-core` is the core Python runtime package for SSOT.
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
<a href="https://pypi.org/project/ssot-core/"><img src="https://img.shields.io/pypi/pyversions/ssot-core?label=Python" alt="Supported Python versions" /></a>
|
|
9
9
|
<a href="https://pepy.tech/project/ssot-core"><img src="https://static.pepy.tech/badge/ssot-core" alt="Downloads" /></a>
|
|
10
10
|
<a href="https://hits.sh/github.com/groupsum/ssot-registry/"><img src="https://hits.sh/github.com/groupsum/ssot-registry.svg?style=flat-square" alt="Hits" /></a>
|
|
11
|
+
<!-- ssot-schema-badges:start -->
|
|
12
|
+
<img src="https://img.shields.io/badge/schema_version-0.5.0-blue" alt="schema_version 0.5.0" />
|
|
13
|
+
<img src="https://img.shields.io/badge/migration%20coverage-12%2F12-brightgreen" alt="Migration coverage 12/12" />
|
|
14
|
+
<!-- ssot-schema-badges:end -->
|
|
11
15
|
</div>
|
|
12
16
|
|
|
13
17
|
`ssot-core` is the core Python runtime package for SSOT.
|
|
@@ -4,16 +4,17 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ssot-core"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.18.dev9"
|
|
8
8
|
description = "Core Python runtime, registry model, validation, and release workflow APIs for SSOT."
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.10,<3.
|
|
10
|
+
requires-python = ">=3.10,<3.15"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
|
|
13
13
|
dependencies = [
|
|
14
14
|
"orjson>=3.10,<4.0",
|
|
15
|
-
"ssot-contracts==0.2.
|
|
16
|
-
"ssot-
|
|
15
|
+
"ssot-contracts==0.2.18.dev9",
|
|
16
|
+
"ssot-pack-contracts>=0.2.17,<0.3.0",
|
|
17
|
+
"ssot-views==0.2.18.dev9",
|
|
17
18
|
"tomli>=2.0.1; python_version < '3.11'",
|
|
18
19
|
]
|
|
19
20
|
keywords = ["ssot", "core", "registry", "validation", "release-management", "governance", "compliance"]
|
|
@@ -31,6 +32,7 @@ classifiers = [
|
|
|
31
32
|
"Programming Language :: Python :: 3.11",
|
|
32
33
|
"Programming Language :: Python :: 3.12",
|
|
33
34
|
"Programming Language :: Python :: 3.13",
|
|
35
|
+
"Programming Language :: Python :: 3.14",
|
|
34
36
|
"Topic :: Database",
|
|
35
37
|
"Topic :: File Formats :: JSON",
|
|
36
38
|
"Topic :: File Formats :: JSON :: JSON Schema",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ssot-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.18.dev9
|
|
4
4
|
Summary: Core Python runtime, registry model, validation, and release workflow APIs for SSOT.
|
|
5
5
|
Author-email: Jacob Stewart <jacob@swarmauri.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
25
|
Classifier: Topic :: Database
|
|
25
26
|
Classifier: Topic :: File Formats :: JSON
|
|
26
27
|
Classifier: Topic :: File Formats :: JSON :: JSON Schema
|
|
@@ -32,11 +33,12 @@ Classifier: Topic :: Software Development :: Quality Assurance
|
|
|
32
33
|
Classifier: Topic :: Software Development :: Testing
|
|
33
34
|
Classifier: Topic :: System :: Archiving
|
|
34
35
|
Classifier: Topic :: Utilities
|
|
35
|
-
Requires-Python: <3.
|
|
36
|
+
Requires-Python: <3.15,>=3.10
|
|
36
37
|
Description-Content-Type: text/markdown
|
|
37
38
|
Requires-Dist: orjson<4.0,>=3.10
|
|
38
|
-
Requires-Dist: ssot-contracts==0.2.
|
|
39
|
-
Requires-Dist: ssot-
|
|
39
|
+
Requires-Dist: ssot-contracts==0.2.18.dev9
|
|
40
|
+
Requires-Dist: ssot-pack-contracts<0.3.0,>=0.2.17
|
|
41
|
+
Requires-Dist: ssot-views==0.2.18.dev9
|
|
40
42
|
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
41
43
|
|
|
42
44
|
<div align="center">
|
|
@@ -49,6 +51,10 @@ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
|
49
51
|
<a href="https://pypi.org/project/ssot-core/"><img src="https://img.shields.io/pypi/pyversions/ssot-core?label=Python" alt="Supported Python versions" /></a>
|
|
50
52
|
<a href="https://pepy.tech/project/ssot-core"><img src="https://static.pepy.tech/badge/ssot-core" alt="Downloads" /></a>
|
|
51
53
|
<a href="https://hits.sh/github.com/groupsum/ssot-registry/"><img src="https://hits.sh/github.com/groupsum/ssot-registry.svg?style=flat-square" alt="Hits" /></a>
|
|
54
|
+
<!-- ssot-schema-badges:start -->
|
|
55
|
+
<img src="https://img.shields.io/badge/schema_version-0.5.0-blue" alt="schema_version 0.5.0" />
|
|
56
|
+
<img src="https://img.shields.io/badge/migration%20coverage-12%2F12-brightgreen" alt="Migration coverage 12/12" />
|
|
57
|
+
<!-- ssot-schema-badges:end -->
|
|
52
58
|
</div>
|
|
53
59
|
|
|
54
60
|
`ssot-core` is the core Python runtime package for SSOT.
|
|
@@ -11,6 +11,7 @@ src/ssot_registry/version.py
|
|
|
11
11
|
src/ssot_registry/api/__init__.py
|
|
12
12
|
src/ssot_registry/api/boundary.py
|
|
13
13
|
src/ssot_registry/api/claims.py
|
|
14
|
+
src/ssot_registry/api/config.py
|
|
14
15
|
src/ssot_registry/api/documents.py
|
|
15
16
|
src/ssot_registry/api/entity_ops.py
|
|
16
17
|
src/ssot_registry/api/evidence.py
|
|
@@ -18,6 +19,9 @@ src/ssot_registry/api/graph.py
|
|
|
18
19
|
src/ssot_registry/api/init.py
|
|
19
20
|
src/ssot_registry/api/lifecycle.py
|
|
20
21
|
src/ssot_registry/api/load.py
|
|
22
|
+
src/ssot_registry/api/local_assurance.py
|
|
23
|
+
src/ssot_registry/api/origin.py
|
|
24
|
+
src/ssot_registry/api/packs.py
|
|
21
25
|
src/ssot_registry/api/plan.py
|
|
22
26
|
src/ssot_registry/api/profile_eval.py
|
|
23
27
|
src/ssot_registry/api/profile_resolution.py
|
|
@@ -53,6 +57,7 @@ src/ssot_registry/graph/export_json.py
|
|
|
53
57
|
src/ssot_registry/guards/__init__.py
|
|
54
58
|
src/ssot_registry/guards/certification.py
|
|
55
59
|
src/ssot_registry/guards/claim_closure.py
|
|
60
|
+
src/ssot_registry/guards/claim_tier_gates.py
|
|
56
61
|
src/ssot_registry/guards/document_lifecycle.py
|
|
57
62
|
src/ssot_registry/guards/document_supersession.py
|
|
58
63
|
src/ssot_registry/guards/feature_claims.py
|
|
@@ -100,11 +105,13 @@ src/ssot_registry/util/time.py
|
|
|
100
105
|
src/ssot_registry/validators/__init__.py
|
|
101
106
|
src/ssot_registry/validators/bidirectional.py
|
|
102
107
|
src/ssot_registry/validators/bounds.py
|
|
108
|
+
src/ssot_registry/validators/claim_lineage.py
|
|
103
109
|
src/ssot_registry/validators/coverage.py
|
|
104
110
|
src/ssot_registry/validators/documents.py
|
|
105
111
|
src/ssot_registry/validators/filesystem.py
|
|
106
112
|
src/ssot_registry/validators/identity.py
|
|
107
113
|
src/ssot_registry/validators/lifecycle.py
|
|
114
|
+
src/ssot_registry/validators/origin.py
|
|
108
115
|
src/ssot_registry/validators/promotion.py
|
|
109
116
|
src/ssot_registry/validators/references.py
|
|
110
117
|
src/ssot_registry/validators/reservations.py
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .boundary import freeze_boundary
|
|
2
2
|
from .claims import evaluate_claims
|
|
3
|
+
from .config import ensure_repo_config, load_repo_config, run_repo_automation, validate_repo_config
|
|
3
4
|
from .documents import (
|
|
4
5
|
create_document,
|
|
5
6
|
create_document_reservation,
|
|
@@ -9,6 +10,7 @@ from .documents import (
|
|
|
9
10
|
list_document_reservations,
|
|
10
11
|
list_documents,
|
|
11
12
|
remove_spec_adr_links,
|
|
13
|
+
repair_document_hashes,
|
|
12
14
|
set_document_status,
|
|
13
15
|
sync_all_documents,
|
|
14
16
|
sync_documents,
|
|
@@ -42,9 +44,18 @@ from .profile_eval import evaluate_feature_passing, evaluate_profile, evaluate_p
|
|
|
42
44
|
from .evidence import verify_evidence_rows
|
|
43
45
|
from .graph import export_graph
|
|
44
46
|
from .init import initialize_repo
|
|
47
|
+
from .local_assurance import (
|
|
48
|
+
build_artifact_manifest,
|
|
49
|
+
build_local_evidence_bundle,
|
|
50
|
+
build_source_snapshot,
|
|
51
|
+
deterministic_root_hash,
|
|
52
|
+
verify_local_release,
|
|
53
|
+
)
|
|
45
54
|
from .lifecycle import set_feature_lifecycle
|
|
46
55
|
from .load import load_registry
|
|
47
56
|
from .plan import plan_features, plan_issues
|
|
57
|
+
from .packs import inspect_pack, preflight_pack, sync_pack
|
|
58
|
+
from .origin import sync_origin_assurance_rows
|
|
48
59
|
from .registry import export_registry
|
|
49
60
|
from .release import certify_release, promote_release, publish_release, revoke_release
|
|
50
61
|
from .save import save_registry
|
|
@@ -58,12 +69,17 @@ __all__ = [
|
|
|
58
69
|
"load_registry",
|
|
59
70
|
"save_registry",
|
|
60
71
|
"validate_registry",
|
|
72
|
+
"ensure_repo_config",
|
|
73
|
+
"load_repo_config",
|
|
74
|
+
"validate_repo_config",
|
|
75
|
+
"run_repo_automation",
|
|
61
76
|
"create_document",
|
|
62
77
|
"get_document",
|
|
63
78
|
"list_documents",
|
|
64
79
|
"update_document",
|
|
65
80
|
"add_spec_adr_links",
|
|
66
81
|
"remove_spec_adr_links",
|
|
82
|
+
"repair_document_hashes",
|
|
67
83
|
"set_document_status",
|
|
68
84
|
"supersede_documents",
|
|
69
85
|
"delete_document",
|
|
@@ -94,7 +110,16 @@ __all__ = [
|
|
|
94
110
|
"remove_release_evidence",
|
|
95
111
|
"plan_features",
|
|
96
112
|
"plan_issues",
|
|
113
|
+
"inspect_pack",
|
|
114
|
+
"preflight_pack",
|
|
115
|
+
"sync_pack",
|
|
116
|
+
"sync_origin_assurance_rows",
|
|
97
117
|
"set_feature_lifecycle",
|
|
118
|
+
"build_artifact_manifest",
|
|
119
|
+
"build_local_evidence_bundle",
|
|
120
|
+
"build_source_snapshot",
|
|
121
|
+
"deterministic_root_hash",
|
|
122
|
+
"verify_local_release",
|
|
98
123
|
"evaluate_claims",
|
|
99
124
|
"evaluate_feature_passing",
|
|
100
125
|
"evaluate_profile",
|
|
@@ -3,12 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
from ssot_registry.guards.claim_closure import evaluate_claim_guard
|
|
6
|
+
from ssot_registry.guards.claim_tier_gates import evaluate_claim_tier_gate
|
|
6
7
|
from ssot_registry.validators.identity import build_index
|
|
7
8
|
from .load import load_registry
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
def evaluate_claims(path: str | Path, claim_id: str | None = None) -> dict[str, object]:
|
|
11
|
-
registry_path,
|
|
11
|
+
def evaluate_claims(path: str | Path, claim_id: str | None = None, *, include_tier_gate: bool = False) -> dict[str, object]:
|
|
12
|
+
registry_path, repo_root, registry = load_registry(path)
|
|
12
13
|
failures: list[str] = []
|
|
13
14
|
index = build_index(registry, failures)
|
|
14
15
|
|
|
@@ -25,8 +26,26 @@ def evaluate_claims(path: str | Path, claim_id: str | None = None) -> dict[str,
|
|
|
25
26
|
if claim_id is not None
|
|
26
27
|
else [index["claims"][entity_id] for entity_id in sorted(index["claims"])]
|
|
27
28
|
)
|
|
28
|
-
reports = [
|
|
29
|
+
reports = []
|
|
30
|
+
for claim in selected:
|
|
31
|
+
report = evaluate_claim_guard(claim, index, registry.get("guard_policies", {}))
|
|
32
|
+
if include_tier_gate:
|
|
33
|
+
report["tier_gate"] = evaluate_claim_tier_gate(
|
|
34
|
+
registry,
|
|
35
|
+
claim,
|
|
36
|
+
index,
|
|
37
|
+
str(claim.get("tier", "T0")),
|
|
38
|
+
repo_root=repo_root,
|
|
39
|
+
policy=registry.get("guard_policies", {}).get("claim_tier_gates", {}),
|
|
40
|
+
)
|
|
41
|
+
reports.append(report)
|
|
29
42
|
all_failures = failures + [failure for report in reports for failure in report["failures"]]
|
|
43
|
+
if include_tier_gate:
|
|
44
|
+
all_failures.extend(
|
|
45
|
+
failure
|
|
46
|
+
for report in reports
|
|
47
|
+
for failure in report.get("tier_gate", {}).get("failures", [])
|
|
48
|
+
)
|
|
30
49
|
return {
|
|
31
50
|
"passed": not all_failures,
|
|
32
51
|
"registry_path": registry_path.as_posix(),
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ssot_registry.util.errors import ValidationError
|
|
8
|
+
|
|
9
|
+
from .graph import export_graph
|
|
10
|
+
from .validate import validate_registry
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import tomllib
|
|
14
|
+
except ModuleNotFoundError: # pragma: no cover - Python < 3.11
|
|
15
|
+
import tomli as tomllib
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
CONFIG_RELATIVE_PATH = ".ssot/ssot.toml"
|
|
19
|
+
_AUTOMATION_MODE_CHOICES = {"manual", "automatic"}
|
|
20
|
+
_GRAPH_FORMAT_CHOICES = {"json", "dot", "png", "svg"}
|
|
21
|
+
|
|
22
|
+
_DEFAULT_CONFIG: dict[str, Any] = {
|
|
23
|
+
"policy": {
|
|
24
|
+
"interactive": False,
|
|
25
|
+
"fail_closed": True,
|
|
26
|
+
},
|
|
27
|
+
"sync": {
|
|
28
|
+
"docs": "manual",
|
|
29
|
+
"templates": "manual",
|
|
30
|
+
"upstream_packages": "manual",
|
|
31
|
+
},
|
|
32
|
+
"validate": {
|
|
33
|
+
"after_registry_change": "automatic",
|
|
34
|
+
},
|
|
35
|
+
"generation": {
|
|
36
|
+
"mode": "manual",
|
|
37
|
+
"formats": ["json"],
|
|
38
|
+
"targets": {
|
|
39
|
+
"graphs": False,
|
|
40
|
+
},
|
|
41
|
+
"graphs": {
|
|
42
|
+
"mode": "manual",
|
|
43
|
+
"formats": ["json"],
|
|
44
|
+
"output_dir": ".ssot/graphs",
|
|
45
|
+
"basename": "registry.graph",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_DEFAULT_TEMPLATE = """[policy]
|
|
51
|
+
interactive = false
|
|
52
|
+
fail_closed = true
|
|
53
|
+
|
|
54
|
+
[sync]
|
|
55
|
+
docs = "manual"
|
|
56
|
+
templates = "manual"
|
|
57
|
+
upstream_packages = "manual"
|
|
58
|
+
|
|
59
|
+
[validate]
|
|
60
|
+
after_registry_change = "automatic"
|
|
61
|
+
|
|
62
|
+
[generation]
|
|
63
|
+
mode = "manual"
|
|
64
|
+
formats = ["json"]
|
|
65
|
+
|
|
66
|
+
[generation.targets]
|
|
67
|
+
graphs = false
|
|
68
|
+
|
|
69
|
+
[generation.graphs]
|
|
70
|
+
mode = "manual"
|
|
71
|
+
formats = ["json"]
|
|
72
|
+
output_dir = ".ssot/graphs"
|
|
73
|
+
basename = "registry.graph"
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
_AUTOMATION_DEPTH = 0
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _repo_root_from_path(path: str | Path) -> Path:
|
|
80
|
+
candidate = Path(path).expanduser()
|
|
81
|
+
if candidate.is_file():
|
|
82
|
+
if candidate.name == "registry.json" and candidate.parent.name == ".ssot":
|
|
83
|
+
return candidate.parent.parent
|
|
84
|
+
if candidate.parent.name == ".ssot":
|
|
85
|
+
return candidate.parent.parent
|
|
86
|
+
return candidate.parent
|
|
87
|
+
if candidate.name == ".ssot":
|
|
88
|
+
return candidate.parent
|
|
89
|
+
return candidate
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _config_path(repo_root: Path) -> Path:
|
|
93
|
+
return repo_root / CONFIG_RELATIVE_PATH
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _deep_merge(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]:
|
|
97
|
+
merged = deepcopy(base)
|
|
98
|
+
for key, value in override.items():
|
|
99
|
+
current = merged.get(key)
|
|
100
|
+
if isinstance(current, dict) and isinstance(value, dict):
|
|
101
|
+
merged[key] = _deep_merge(current, value)
|
|
102
|
+
else:
|
|
103
|
+
merged[key] = deepcopy(value)
|
|
104
|
+
return merged
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _expect_table(config: dict[str, Any], key: str) -> dict[str, Any]:
|
|
108
|
+
value = config.get(key)
|
|
109
|
+
if not isinstance(value, dict):
|
|
110
|
+
raise ValidationError(f"{key} must be a TOML table")
|
|
111
|
+
return value
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _expect_bool(table: dict[str, Any], key: str, *, prefix: str) -> None:
|
|
115
|
+
value = table.get(key)
|
|
116
|
+
if not isinstance(value, bool):
|
|
117
|
+
raise ValidationError(f"{prefix}.{key} must be a boolean")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _expect_choice(table: dict[str, Any], key: str, choices: set[str], *, prefix: str) -> None:
|
|
121
|
+
value = table.get(key)
|
|
122
|
+
if not isinstance(value, str) or value not in choices:
|
|
123
|
+
allowed = ", ".join(sorted(choices))
|
|
124
|
+
raise ValidationError(f"{prefix}.{key} must be one of: {allowed}")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _expect_string(table: dict[str, Any], key: str, *, prefix: str) -> None:
|
|
128
|
+
value = table.get(key)
|
|
129
|
+
if not isinstance(value, str) or not value.strip():
|
|
130
|
+
raise ValidationError(f"{prefix}.{key} must be a non-empty string")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _expect_scalar_string_list(table: dict[str, Any], key: str, choices: set[str] | None = None, *, prefix: str) -> None:
|
|
134
|
+
value = table.get(key)
|
|
135
|
+
if not isinstance(value, list) or any(not isinstance(item, str) for item in value):
|
|
136
|
+
raise ValidationError(f"{prefix}.{key} must be a list of strings")
|
|
137
|
+
if choices is not None:
|
|
138
|
+
invalid = [item for item in value if item not in choices]
|
|
139
|
+
if invalid:
|
|
140
|
+
allowed = ", ".join(sorted(choices))
|
|
141
|
+
raise ValidationError(f"{prefix}.{key} contains unsupported values {invalid}; allowed: {allowed}")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def validate_repo_config_payload(config: dict[str, Any]) -> dict[str, Any]:
|
|
145
|
+
normalized = _deep_merge(_DEFAULT_CONFIG, config)
|
|
146
|
+
|
|
147
|
+
policy = _expect_table(normalized, "policy")
|
|
148
|
+
_expect_bool(policy, "interactive", prefix="policy")
|
|
149
|
+
_expect_bool(policy, "fail_closed", prefix="policy")
|
|
150
|
+
|
|
151
|
+
sync = _expect_table(normalized, "sync")
|
|
152
|
+
for field_name in ("docs", "templates", "upstream_packages"):
|
|
153
|
+
_expect_choice(sync, field_name, _AUTOMATION_MODE_CHOICES, prefix="sync")
|
|
154
|
+
|
|
155
|
+
validate_cfg = _expect_table(normalized, "validate")
|
|
156
|
+
_expect_choice(validate_cfg, "after_registry_change", _AUTOMATION_MODE_CHOICES, prefix="validate")
|
|
157
|
+
|
|
158
|
+
generation = _expect_table(normalized, "generation")
|
|
159
|
+
_expect_choice(generation, "mode", _AUTOMATION_MODE_CHOICES, prefix="generation")
|
|
160
|
+
_expect_scalar_string_list(generation, "formats", choices={"json", "yaml", "toml", "md", "dot", "png", "svg"}, prefix="generation")
|
|
161
|
+
|
|
162
|
+
targets = _expect_table(generation, "targets")
|
|
163
|
+
_expect_bool(targets, "graphs", prefix="generation.targets")
|
|
164
|
+
|
|
165
|
+
graphs = _expect_table(generation, "graphs")
|
|
166
|
+
_expect_choice(graphs, "mode", _AUTOMATION_MODE_CHOICES, prefix="generation.graphs")
|
|
167
|
+
_expect_scalar_string_list(graphs, "formats", choices=_GRAPH_FORMAT_CHOICES, prefix="generation.graphs")
|
|
168
|
+
_expect_string(graphs, "output_dir", prefix="generation.graphs")
|
|
169
|
+
_expect_string(graphs, "basename", prefix="generation.graphs")
|
|
170
|
+
|
|
171
|
+
return normalized
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def ensure_repo_config(path: str | Path, *, overwrite: bool = False) -> dict[str, Any]:
|
|
175
|
+
repo_root = _repo_root_from_path(path)
|
|
176
|
+
repo_root.mkdir(parents=True, exist_ok=True)
|
|
177
|
+
config_path = _config_path(repo_root)
|
|
178
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
179
|
+
existed = config_path.exists()
|
|
180
|
+
|
|
181
|
+
if existed and not overwrite:
|
|
182
|
+
payload = load_repo_config(path)
|
|
183
|
+
return {
|
|
184
|
+
"passed": True,
|
|
185
|
+
"config_path": payload["config_path"],
|
|
186
|
+
"created": False,
|
|
187
|
+
"overwritten": False,
|
|
188
|
+
"config": payload["config"],
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
config_path.write_text(_DEFAULT_TEMPLATE, encoding="utf-8", newline="\n")
|
|
192
|
+
payload = load_repo_config(path)
|
|
193
|
+
return {
|
|
194
|
+
"passed": True,
|
|
195
|
+
"config_path": payload["config_path"],
|
|
196
|
+
"created": not existed,
|
|
197
|
+
"overwritten": existed and overwrite,
|
|
198
|
+
"config": payload["config"],
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def load_repo_config(path: str | Path) -> dict[str, Any]:
|
|
203
|
+
repo_root = _repo_root_from_path(path)
|
|
204
|
+
config_path = _config_path(repo_root)
|
|
205
|
+
if not config_path.exists():
|
|
206
|
+
raise FileNotFoundError(f"Repo-local SSOT config not found: {config_path.as_posix()}")
|
|
207
|
+
raw = tomllib.loads(config_path.read_text(encoding="utf-8"))
|
|
208
|
+
if not isinstance(raw, dict):
|
|
209
|
+
raise ValidationError("Repo-local SSOT config must decode to a TOML table")
|
|
210
|
+
normalized = validate_repo_config_payload(raw)
|
|
211
|
+
return {
|
|
212
|
+
"passed": True,
|
|
213
|
+
"repo_root": repo_root.as_posix(),
|
|
214
|
+
"config_path": config_path.as_posix(),
|
|
215
|
+
"config": normalized,
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def validate_repo_config(path: str | Path) -> dict[str, Any]:
|
|
220
|
+
payload = load_repo_config(path)
|
|
221
|
+
return {
|
|
222
|
+
"passed": True,
|
|
223
|
+
"repo_root": payload["repo_root"],
|
|
224
|
+
"config_path": payload["config_path"],
|
|
225
|
+
"config": payload["config"],
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def run_repo_automation(path: str | Path) -> dict[str, Any]:
|
|
230
|
+
global _AUTOMATION_DEPTH
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
payload = load_repo_config(path)
|
|
234
|
+
except FileNotFoundError as exc:
|
|
235
|
+
return {
|
|
236
|
+
"passed": True,
|
|
237
|
+
"config_path": str(exc).removeprefix("Repo-local SSOT config not found: "),
|
|
238
|
+
"skipped": True,
|
|
239
|
+
"sync": None,
|
|
240
|
+
"validation": None,
|
|
241
|
+
"generation": {
|
|
242
|
+
"graphs": [],
|
|
243
|
+
},
|
|
244
|
+
}
|
|
245
|
+
config = payload["config"]
|
|
246
|
+
results: dict[str, Any] = {
|
|
247
|
+
"passed": True,
|
|
248
|
+
"config_path": payload["config_path"],
|
|
249
|
+
"skipped": False,
|
|
250
|
+
"sync": None,
|
|
251
|
+
"validation": None,
|
|
252
|
+
"generation": {
|
|
253
|
+
"graphs": [],
|
|
254
|
+
},
|
|
255
|
+
}
|
|
256
|
+
if _AUTOMATION_DEPTH > 0:
|
|
257
|
+
results["skipped"] = True
|
|
258
|
+
return results
|
|
259
|
+
|
|
260
|
+
_AUTOMATION_DEPTH += 1
|
|
261
|
+
try:
|
|
262
|
+
if config["sync"]["docs"] == "automatic":
|
|
263
|
+
from .documents import sync_all_documents
|
|
264
|
+
|
|
265
|
+
results["sync"] = sync_all_documents(path)
|
|
266
|
+
|
|
267
|
+
if config["validate"]["after_registry_change"] == "automatic":
|
|
268
|
+
validation = validate_registry(path)
|
|
269
|
+
if not validation["passed"] and config["policy"]["fail_closed"]:
|
|
270
|
+
raise ValidationError("Repo-local automation validation failed after registry change")
|
|
271
|
+
results["validation"] = validation
|
|
272
|
+
|
|
273
|
+
graph_cfg = config["generation"]["graphs"]
|
|
274
|
+
if config["generation"]["targets"]["graphs"] and graph_cfg["mode"] == "automatic":
|
|
275
|
+
repo_root = Path(payload["repo_root"])
|
|
276
|
+
for output_format in graph_cfg["formats"]:
|
|
277
|
+
output_path = repo_root / graph_cfg["output_dir"] / f"{graph_cfg['basename']}.{output_format}"
|
|
278
|
+
graph_result = export_graph(path=path, output_format=output_format, output=output_path.as_posix())
|
|
279
|
+
results["generation"]["graphs"].append(graph_result["output_path"])
|
|
280
|
+
finally:
|
|
281
|
+
_AUTOMATION_DEPTH -= 1
|
|
282
|
+
|
|
283
|
+
return results
|