ssot-core 0.2.19.dev1__tar.gz → 0.2.20.dev1__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.19.dev1 → ssot_core-0.2.20.dev1}/PKG-INFO +7 -6
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/README.md +3 -2
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/pyproject.toml +4 -4
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_core.egg-info/PKG-INFO +7 -6
- ssot_core-0.2.20.dev1/src/ssot_core.egg-info/requires.txt +7 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/__init__.py +2 -1
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/init.py +2 -2
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/profile_eval.py +9 -3
- ssot_core-0.2.20.dev1/src/ssot_registry/api/save.py +37 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/status_sync.py +4 -4
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/scaffold.py +2 -2
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/claim_closure.py +43 -3
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/feature_claims.py +53 -1
- ssot_core-0.2.19.dev1/src/ssot_core.egg-info/requires.txt +0 -7
- ssot_core-0.2.19.dev1/src/ssot_registry/api/save.py +0 -9
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/setup.cfg +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_core.egg-info/SOURCES.txt +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_core.egg-info/dependency_links.txt +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_core.egg-info/top_level.txt +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/__main__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/acl/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/acl/policy.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/acl/wrapper.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/boundary.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/claims.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/config.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/documents.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/entity_ops.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/evidence.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/graph.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/lifecycle.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/load.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/local_assurance.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/origin.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/packs.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/plan.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/profile_resolution.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/registry.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/release.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/test_execution.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/upgrade.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/api/validate.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/adr_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/boundary_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/claim_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/common.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/evidence_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/feature_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/graph_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/init_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/issue_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/main.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/profile_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/registry_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/release_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/risk_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/spec_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/test_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/upgrade_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/cli/validate_cmd.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/events.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/models.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/paths.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/service.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/sqlite_store.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/control/sse.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/graph/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/graph/export_dot.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/graph/export_json.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/certification.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/claim_tier_gates.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/completion.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/document_lifecycle.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/document_supersession.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/feature_requirements.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/lifecycle.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/profile_requirements.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/promotion.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/publication.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/maturation/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/maturation/selector.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/boundary.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/claim.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/document.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/enums.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/evidence.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/feature.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/ids.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/issue.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/profile.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/registry.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/release.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/risk.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/schema_version.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/model/test.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/reports/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/reports/certification_report.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/reports/summary.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/reports/validation_report.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/boundary_snapshot.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/hashing.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/published_snapshot.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/release_snapshot.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/templates/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/templates/registry.full.json +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/templates/registry.minimal.json +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/document_io.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/errors.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/formatting.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/fs.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/jcs.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/jsonio.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/registry_lock.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/util/time.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/bidirectional.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/bounds.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/claim_lineage.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/coverage.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/documents.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/feature_parent_links.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/filesystem.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/identity.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/lifecycle.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/origin.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/promotion.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/references.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/reservations.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/structure.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/tiers.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/version.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/watch/__init__.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/watch/git_status.py +0 -0
- {ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/watch/observer.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.20.dev1
|
|
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
|
|
@@ -36,9 +36,9 @@ Classifier: Topic :: Utilities
|
|
|
36
36
|
Requires-Python: <3.15,>=3.10
|
|
37
37
|
Description-Content-Type: text/markdown
|
|
38
38
|
Requires-Dist: orjson<4.0,>=3.10
|
|
39
|
-
Requires-Dist: ssot-contracts==0.2.
|
|
40
|
-
Requires-Dist: ssot-pack-contracts<0.3.0,>=0.2.
|
|
41
|
-
Requires-Dist: ssot-views==0.2.
|
|
39
|
+
Requires-Dist: ssot-contracts==0.2.20.dev1
|
|
40
|
+
Requires-Dist: ssot-pack-contracts<0.3.0,>=0.2.21.dev1
|
|
41
|
+
Requires-Dist: ssot-views==0.2.20.dev1
|
|
42
42
|
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
43
43
|
|
|
44
44
|
<div align="center">
|
|
@@ -59,7 +59,7 @@ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
|
59
59
|
|
|
60
60
|
`ssot-core` is the core Python runtime package for SSOT.
|
|
61
61
|
|
|
62
|
-
It owns the canonical registry model, core APIs for loading and mutating registries, validation and guard logic, planning and release workflows, and the domain operations that [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), and [ssot-tui](https://pypi.org/project/ssot-tui/) build on top of.
|
|
62
|
+
It owns the canonical registry model, core APIs for loading and mutating registries, validation and guard logic, planning and release workflows, and the domain operations that [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-mcp](https://pypi.org/project/ssot-mcp/), and [ssot-tui](https://pypi.org/project/ssot-tui/) build on top of.
|
|
63
63
|
|
|
64
64
|
- GitHub: https://github.com/groupsum/ssot-registry
|
|
65
65
|
|
|
@@ -103,6 +103,7 @@ ADR and SPEC companion documents are canonically authored as JSON under `.ssot/a
|
|
|
103
103
|
python -m pip install ssot-core # core library/runtime only
|
|
104
104
|
python -m pip install ssot-cli # primary CLI distribution + ssot-core + ssot-conformance
|
|
105
105
|
python -m pip install ssot-registry # umbrella bundle: ssot-core + ssot-cli + ssot-conformance
|
|
106
|
+
python -m pip install "ssot-registry[mcp]" # optional MCP server bundle
|
|
106
107
|
python -m pip install "ssot-registry[tui]" # optional TUI bundle
|
|
107
108
|
```
|
|
108
109
|
|
|
@@ -941,6 +942,6 @@ ssot-registry registry export . --format toml --output .ssot/exports/registry.to
|
|
|
941
942
|
|
|
942
943
|
- Package type: core runtime/library package
|
|
943
944
|
- Depends on: [ssot-contracts](https://pypi.org/project/ssot-contracts/), [ssot-views](https://pypi.org/project/ssot-views/)
|
|
944
|
-
- Consumed by: [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-tui](https://pypi.org/project/ssot-tui/), direct Python integrations, and automation
|
|
945
|
+
- Consumed by: [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-mcp](https://pypi.org/project/ssot-mcp/), [ssot-tui](https://pypi.org/project/ssot-tui/), direct Python integrations, and automation
|
|
945
946
|
|
|
946
947
|
If you are embedding SSOT behavior inside Python code, this is the package to import. If you need the primary CLI distribution, install [ssot-cli](https://pypi.org/project/ssot-cli/) alongside it.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
`ssot-core` is the core Python runtime package for SSOT.
|
|
18
18
|
|
|
19
|
-
It owns the canonical registry model, core APIs for loading and mutating registries, validation and guard logic, planning and release workflows, and the domain operations that [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), and [ssot-tui](https://pypi.org/project/ssot-tui/) build on top of.
|
|
19
|
+
It owns the canonical registry model, core APIs for loading and mutating registries, validation and guard logic, planning and release workflows, and the domain operations that [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-mcp](https://pypi.org/project/ssot-mcp/), and [ssot-tui](https://pypi.org/project/ssot-tui/) build on top of.
|
|
20
20
|
|
|
21
21
|
- GitHub: https://github.com/groupsum/ssot-registry
|
|
22
22
|
|
|
@@ -60,6 +60,7 @@ ADR and SPEC companion documents are canonically authored as JSON under `.ssot/a
|
|
|
60
60
|
python -m pip install ssot-core # core library/runtime only
|
|
61
61
|
python -m pip install ssot-cli # primary CLI distribution + ssot-core + ssot-conformance
|
|
62
62
|
python -m pip install ssot-registry # umbrella bundle: ssot-core + ssot-cli + ssot-conformance
|
|
63
|
+
python -m pip install "ssot-registry[mcp]" # optional MCP server bundle
|
|
63
64
|
python -m pip install "ssot-registry[tui]" # optional TUI bundle
|
|
64
65
|
```
|
|
65
66
|
|
|
@@ -898,6 +899,6 @@ ssot-registry registry export . --format toml --output .ssot/exports/registry.to
|
|
|
898
899
|
|
|
899
900
|
- Package type: core runtime/library package
|
|
900
901
|
- Depends on: [ssot-contracts](https://pypi.org/project/ssot-contracts/), [ssot-views](https://pypi.org/project/ssot-views/)
|
|
901
|
-
- Consumed by: [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-tui](https://pypi.org/project/ssot-tui/), direct Python integrations, and automation
|
|
902
|
+
- Consumed by: [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-mcp](https://pypi.org/project/ssot-mcp/), [ssot-tui](https://pypi.org/project/ssot-tui/), direct Python integrations, and automation
|
|
902
903
|
|
|
903
904
|
If you are embedding SSOT behavior inside Python code, this is the package to import. If you need the primary CLI distribution, install [ssot-cli](https://pypi.org/project/ssot-cli/) alongside it.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ssot-core"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.20.dev1"
|
|
8
8
|
description = "Core Python runtime, registry model, validation, and release workflow APIs for SSOT."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10,<3.15"
|
|
@@ -12,9 +12,9 @@ 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-pack-contracts>=0.2.
|
|
17
|
-
"ssot-views==0.2.
|
|
15
|
+
"ssot-contracts==0.2.20.dev1",
|
|
16
|
+
"ssot-pack-contracts>=0.2.21.dev1,<0.3.0",
|
|
17
|
+
"ssot-views==0.2.20.dev1",
|
|
18
18
|
"tomli>=2.0.1; python_version < '3.11'",
|
|
19
19
|
]
|
|
20
20
|
keywords = ["ssot", "core", "registry", "validation", "release-management", "governance", "compliance"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ssot-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.20.dev1
|
|
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
|
|
@@ -36,9 +36,9 @@ Classifier: Topic :: Utilities
|
|
|
36
36
|
Requires-Python: <3.15,>=3.10
|
|
37
37
|
Description-Content-Type: text/markdown
|
|
38
38
|
Requires-Dist: orjson<4.0,>=3.10
|
|
39
|
-
Requires-Dist: ssot-contracts==0.2.
|
|
40
|
-
Requires-Dist: ssot-pack-contracts<0.3.0,>=0.2.
|
|
41
|
-
Requires-Dist: ssot-views==0.2.
|
|
39
|
+
Requires-Dist: ssot-contracts==0.2.20.dev1
|
|
40
|
+
Requires-Dist: ssot-pack-contracts<0.3.0,>=0.2.21.dev1
|
|
41
|
+
Requires-Dist: ssot-views==0.2.20.dev1
|
|
42
42
|
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
43
43
|
|
|
44
44
|
<div align="center">
|
|
@@ -59,7 +59,7 @@ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
|
59
59
|
|
|
60
60
|
`ssot-core` is the core Python runtime package for SSOT.
|
|
61
61
|
|
|
62
|
-
It owns the canonical registry model, core APIs for loading and mutating registries, validation and guard logic, planning and release workflows, and the domain operations that [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), and [ssot-tui](https://pypi.org/project/ssot-tui/) build on top of.
|
|
62
|
+
It owns the canonical registry model, core APIs for loading and mutating registries, validation and guard logic, planning and release workflows, and the domain operations that [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-mcp](https://pypi.org/project/ssot-mcp/), and [ssot-tui](https://pypi.org/project/ssot-tui/) build on top of.
|
|
63
63
|
|
|
64
64
|
- GitHub: https://github.com/groupsum/ssot-registry
|
|
65
65
|
|
|
@@ -103,6 +103,7 @@ ADR and SPEC companion documents are canonically authored as JSON under `.ssot/a
|
|
|
103
103
|
python -m pip install ssot-core # core library/runtime only
|
|
104
104
|
python -m pip install ssot-cli # primary CLI distribution + ssot-core + ssot-conformance
|
|
105
105
|
python -m pip install ssot-registry # umbrella bundle: ssot-core + ssot-cli + ssot-conformance
|
|
106
|
+
python -m pip install "ssot-registry[mcp]" # optional MCP server bundle
|
|
106
107
|
python -m pip install "ssot-registry[tui]" # optional TUI bundle
|
|
107
108
|
```
|
|
108
109
|
|
|
@@ -941,6 +942,6 @@ ssot-registry registry export . --format toml --output .ssot/exports/registry.to
|
|
|
941
942
|
|
|
942
943
|
- Package type: core runtime/library package
|
|
943
944
|
- Depends on: [ssot-contracts](https://pypi.org/project/ssot-contracts/), [ssot-views](https://pypi.org/project/ssot-views/)
|
|
944
|
-
- Consumed by: [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-tui](https://pypi.org/project/ssot-tui/), direct Python integrations, and automation
|
|
945
|
+
- Consumed by: [ssot-cli](https://pypi.org/project/ssot-cli/), [ssot-conformance](https://pypi.org/project/ssot-conformance/), [ssot-mcp](https://pypi.org/project/ssot-mcp/), [ssot-tui](https://pypi.org/project/ssot-tui/), direct Python integrations, and automation
|
|
945
946
|
|
|
946
947
|
If you are embedding SSOT behavior inside Python code, this is the package to import. If you need the primary CLI distribution, install [ssot-cli](https://pypi.org/project/ssot-cli/) alongside it.
|
|
@@ -62,7 +62,7 @@ from .packs import inspect_pack, preflight_pack, sync_pack
|
|
|
62
62
|
from .origin import sync_origin_assurance_rows
|
|
63
63
|
from .registry import export_registry
|
|
64
64
|
from .release import certify_release, promote_release, publish_release, revoke_release
|
|
65
|
-
from .save import save_registry
|
|
65
|
+
from .save import save_registry, save_registry_unchecked
|
|
66
66
|
from .status_sync import sync_automated_statuses
|
|
67
67
|
from .test_execution import run_boundary_tests, run_resolved_test_rows, run_spec_tests, run_tests
|
|
68
68
|
from .upgrade import upgrade_registry
|
|
@@ -72,6 +72,7 @@ __all__ = [
|
|
|
72
72
|
"initialize_repo",
|
|
73
73
|
"load_registry",
|
|
74
74
|
"save_registry",
|
|
75
|
+
"save_registry_unchecked",
|
|
75
76
|
"validate_registry",
|
|
76
77
|
"ensure_repo_config",
|
|
77
78
|
"load_repo_config",
|
|
@@ -7,7 +7,7 @@ from ssot_registry.api.documents import sync_all_documents
|
|
|
7
7
|
from ssot_registry.model.registry import build_minimal_registry, default_paths
|
|
8
8
|
from ssot_registry.util.errors import RegistryError
|
|
9
9
|
from .config import ensure_repo_config
|
|
10
|
-
from .save import
|
|
10
|
+
from .save import save_registry_unchecked
|
|
11
11
|
from .validate import validate_registry
|
|
12
12
|
|
|
13
13
|
|
|
@@ -37,7 +37,7 @@ def initialize_repo(
|
|
|
37
37
|
(repo_root / relative_path).mkdir(parents=True, exist_ok=True)
|
|
38
38
|
|
|
39
39
|
registry = build_minimal_registry(repo_id, repo_name, version)
|
|
40
|
-
|
|
40
|
+
save_registry_unchecked(registry_path, registry)
|
|
41
41
|
|
|
42
42
|
_copy_schema_tree(repo_root / paths["schema_root"])
|
|
43
43
|
config_result = ensure_repo_config(repo_root)
|
|
@@ -46,23 +46,29 @@ def evaluate_feature_passing(
|
|
|
46
46
|
|
|
47
47
|
checked_claim_ids: list[str] = []
|
|
48
48
|
satisfying_claim_ids: list[str] = []
|
|
49
|
+
failed_claim_ids: list[str] = []
|
|
49
50
|
active_claims = active_required_feature_claims(feature, index)
|
|
50
51
|
for claim in active_claims:
|
|
51
52
|
claim_id = str(claim["id"])
|
|
52
53
|
checked_claim_ids.append(claim_id)
|
|
53
54
|
guard = evaluate_claim_guard(claim, index, guard_policies)
|
|
54
55
|
if not guard.get("passed"):
|
|
56
|
+
failed_claim_ids.append(claim_id)
|
|
55
57
|
continue
|
|
56
58
|
if claim.get("tier") != "T0" and (required_tier is None or CLAIM_TIER_RANK[claim["tier"]] >= CLAIM_TIER_RANK[required_tier]):
|
|
57
59
|
satisfying_claim_ids.append(claim_id)
|
|
58
60
|
|
|
59
|
-
checks["claim_target_met"] = bool(
|
|
61
|
+
checks["claim_target_met"] = bool(satisfying_claim_ids) and not failed_claim_ids
|
|
60
62
|
if not checks["claim_target_met"]:
|
|
61
63
|
if required_tier is None:
|
|
62
64
|
failures.append(f"Feature {feature_id} has no effective required claim tier")
|
|
63
65
|
else:
|
|
64
|
-
failures.append(f"Feature {feature_id} does not have
|
|
65
|
-
failures.extend(
|
|
66
|
+
failures.append(f"Feature {feature_id} does not have an active evidenced claim satisfying tier {required_tier}")
|
|
67
|
+
failures.extend(f"Claim {claim_id} does not pass claim guard" for claim_id in failed_claim_ids)
|
|
68
|
+
failures.extend(
|
|
69
|
+
failure.removeprefix(f"features.{feature_id} ")
|
|
70
|
+
for failure in feature_claim_ceiling_failures(feature, index, require_evidenced_status=False)
|
|
71
|
+
)
|
|
66
72
|
|
|
67
73
|
return {
|
|
68
74
|
"feature_id": feature_id,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from ssot_registry.util.errors import ValidationError
|
|
6
|
+
from ssot_registry.util.registry_lock import save_registry_json_locked
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _repo_root_for_registry_path(registry_path: str | Path) -> Path:
|
|
10
|
+
path = Path(registry_path)
|
|
11
|
+
if path.name == "registry.json" and path.parent.name == ".ssot":
|
|
12
|
+
return path.parent.parent
|
|
13
|
+
if path.parent.name == ".ssot":
|
|
14
|
+
return path.parent.parent
|
|
15
|
+
return path.parent
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def save_registry_unchecked(registry_path: str | Path, registry: dict[str, object]) -> None:
|
|
19
|
+
save_registry_json_locked(registry_path, registry)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def save_registry(
|
|
23
|
+
registry_path: str | Path,
|
|
24
|
+
registry: dict[str, object],
|
|
25
|
+
*,
|
|
26
|
+
repo_root: str | Path | None = None,
|
|
27
|
+
action: str = "saving registry",
|
|
28
|
+
) -> dict[str, object]:
|
|
29
|
+
from .validate import validate_registry_document
|
|
30
|
+
|
|
31
|
+
resolved_repo_root = Path(repo_root) if repo_root is not None else _repo_root_for_registry_path(registry_path)
|
|
32
|
+
report = validate_registry_document(registry, registry_path, resolved_repo_root)
|
|
33
|
+
if not report["passed"]:
|
|
34
|
+
detail = "; ".join(report["failures"])
|
|
35
|
+
raise ValidationError(f"Registry validation failed before {action}: {detail}")
|
|
36
|
+
save_registry_unchecked(registry_path, registry)
|
|
37
|
+
return report
|
|
@@ -234,22 +234,22 @@ def _sync_features_once(registry: dict[str, Any]) -> list[dict[str, object]]:
|
|
|
234
234
|
required_features = [index["features"][required_id] for required_id in feature.get("requires", []) if required_id in index["features"]]
|
|
235
235
|
required_tier = feature.get("plan", {}).get("target_claim_tier")
|
|
236
236
|
tests_pass = bool(linked_tests) and all(test.get("status") == "passing" for test in linked_tests)
|
|
237
|
-
claims_pass = bool(active_claims) and
|
|
237
|
+
claims_pass = bool(active_claims) and any(_claim_satisfies_feature(claim, required_tier) for claim in active_claims)
|
|
238
238
|
requirements_pass = all(required.get("implementation_status") == "implemented" for required in required_features)
|
|
239
|
+
ceiling_failures = feature_claim_ceiling_failures(feature, index)
|
|
239
240
|
only_planned_support = (
|
|
240
241
|
bool(linked_tests or linked_claims)
|
|
241
242
|
and all(test.get("status") == "planned" for test in linked_tests)
|
|
242
243
|
and all(CLAIM_STATUS_RANK.get(claim.get("status"), -999) <= CLAIM_STATUS_RANK["proposed"] for claim in active_claims)
|
|
243
244
|
)
|
|
244
|
-
if tests_pass and claims_pass and requirements_pass:
|
|
245
|
+
if tests_pass and claims_pass and requirements_pass and not ceiling_failures:
|
|
245
246
|
status = "implemented"
|
|
246
|
-
reason = "feature has passing tests,
|
|
247
|
+
reason = "feature has passing tests, an active required claim satisfies implementation, and implemented requirements"
|
|
247
248
|
elif only_planned_support:
|
|
248
249
|
status = "absent"
|
|
249
250
|
reason = "feature has only planned verification support"
|
|
250
251
|
elif linked_tests or linked_claims or required_features:
|
|
251
252
|
status = "partial"
|
|
252
|
-
ceiling_failures = feature_claim_ceiling_failures(feature, index)
|
|
253
253
|
reason = "; ".join(ceiling_failures) if ceiling_failures else "feature has linked support but does not yet satisfy implementation criteria"
|
|
254
254
|
else:
|
|
255
255
|
status = "absent"
|
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
7
|
from ssot_registry.api.load import load_registry
|
|
8
|
-
from ssot_registry.api.save import
|
|
8
|
+
from ssot_registry.api.save import save_registry_unchecked
|
|
9
9
|
from ssot_registry.api.validate import validate_registry_document
|
|
10
10
|
from ssot_registry.maturation.selector import build_registry_index
|
|
11
11
|
from ssot_registry.util.jsonio import stable_json_dumps
|
|
@@ -148,7 +148,7 @@ def scaffold_target_claim_wiring(repo_root: str | Path, feature_id: str, target_
|
|
|
148
148
|
"new_validation_failures": new_failures,
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
save_registry_unchecked(registry_path, working)
|
|
152
152
|
return {
|
|
153
153
|
"passed": True,
|
|
154
154
|
"validation_clean": bool(report.get("passed")),
|
|
@@ -4,6 +4,45 @@ from ssot_registry.guards.feature_requirements import evaluate_required_feature_
|
|
|
4
4
|
from ssot_registry.model.enums import CLAIM_STATUS_RANK, CLAIM_TIER_RANK
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
def _dependency_closure_contains(
|
|
8
|
+
claim: dict[str, object],
|
|
9
|
+
target_claim_id: str,
|
|
10
|
+
index: dict[str, dict[str, dict[str, object]]],
|
|
11
|
+
*,
|
|
12
|
+
seen: set[str] | None = None,
|
|
13
|
+
) -> bool:
|
|
14
|
+
seen = seen or set()
|
|
15
|
+
for dependency_id in claim.get("depends_on_claim_ids", []):
|
|
16
|
+
if dependency_id == target_claim_id:
|
|
17
|
+
return True
|
|
18
|
+
if dependency_id in seen or dependency_id not in index["claims"]:
|
|
19
|
+
continue
|
|
20
|
+
seen.add(str(dependency_id))
|
|
21
|
+
if _dependency_closure_contains(index["claims"][dependency_id], target_claim_id, index, seen=seen):
|
|
22
|
+
return True
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _has_target_tier_successor(
|
|
27
|
+
claim: dict[str, object],
|
|
28
|
+
feature: dict[str, object],
|
|
29
|
+
feature_target_tier: str,
|
|
30
|
+
index: dict[str, dict[str, dict[str, object]]],
|
|
31
|
+
) -> bool:
|
|
32
|
+
claim_id = str(claim["id"])
|
|
33
|
+
for candidate_id in feature.get("claim_ids", []):
|
|
34
|
+
candidate = index["claims"].get(candidate_id)
|
|
35
|
+
if candidate is None or candidate.get("status") == "retired":
|
|
36
|
+
continue
|
|
37
|
+
if CLAIM_TIER_RANK[candidate["tier"]] < CLAIM_TIER_RANK[feature_target_tier]:
|
|
38
|
+
continue
|
|
39
|
+
if CLAIM_STATUS_RANK.get(candidate.get("status"), -999) < CLAIM_STATUS_RANK["evidenced"]:
|
|
40
|
+
continue
|
|
41
|
+
if _dependency_closure_contains(candidate, claim_id, index):
|
|
42
|
+
return True
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
7
46
|
def evaluate_claim_guard(
|
|
8
47
|
claim: dict[str, object],
|
|
9
48
|
index: dict[str, dict[str, dict[str, object]]],
|
|
@@ -64,9 +103,10 @@ def evaluate_claim_guard(
|
|
|
64
103
|
for feature in linked_features:
|
|
65
104
|
feature_target_tier = feature.get("plan", {}).get("target_claim_tier")
|
|
66
105
|
if feature_target_tier is not None and CLAIM_TIER_RANK[claim["tier"]] < CLAIM_TIER_RANK[feature_target_tier]:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
106
|
+
if not _has_target_tier_successor(claim, feature, feature_target_tier, index):
|
|
107
|
+
feature_target_failures.append(
|
|
108
|
+
f"Claim {claim['id']} tier {claim['tier']} is below feature target tier {feature_target_tier} on {feature['id']}"
|
|
109
|
+
)
|
|
70
110
|
requirement_failures.extend(
|
|
71
111
|
f"Claim {claim['id']} linked feature requirement failure: {failure}"
|
|
72
112
|
for failure in evaluate_required_feature_failures(feature["id"], index)
|
|
@@ -29,6 +29,34 @@ def claim_satisfies_feature_implementation(
|
|
|
29
29
|
return CLAIM_STATUS_RANK.get(claim.get("status"), -999) >= CLAIM_STATUS_RANK["evidenced"]
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def _dependency_closure_contains(
|
|
33
|
+
claim: dict[str, object],
|
|
34
|
+
target_claim_id: str,
|
|
35
|
+
index: dict[str, dict[str, dict[str, object]]],
|
|
36
|
+
*,
|
|
37
|
+
seen: set[str] | None = None,
|
|
38
|
+
) -> bool:
|
|
39
|
+
seen = seen or set()
|
|
40
|
+
for dependency_id in claim.get("depends_on_claim_ids", []):
|
|
41
|
+
if dependency_id == target_claim_id:
|
|
42
|
+
return True
|
|
43
|
+
if dependency_id in seen or dependency_id not in index["claims"]:
|
|
44
|
+
continue
|
|
45
|
+
seen.add(str(dependency_id))
|
|
46
|
+
if _dependency_closure_contains(index["claims"][dependency_id], target_claim_id, index, seen=seen):
|
|
47
|
+
return True
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _has_satisfying_successor(
|
|
52
|
+
claim: dict[str, object],
|
|
53
|
+
satisfying_claims: list[dict[str, object]],
|
|
54
|
+
index: dict[str, dict[str, dict[str, object]]],
|
|
55
|
+
) -> bool:
|
|
56
|
+
claim_id = str(claim["id"])
|
|
57
|
+
return any(_dependency_closure_contains(candidate, claim_id, index) for candidate in satisfying_claims)
|
|
58
|
+
|
|
59
|
+
|
|
32
60
|
def feature_claim_ceiling_failures(
|
|
33
61
|
feature: dict[str, Any],
|
|
34
62
|
index: dict[str, dict[str, dict[str, object]]],
|
|
@@ -37,8 +65,32 @@ def feature_claim_ceiling_failures(
|
|
|
37
65
|
) -> list[str]:
|
|
38
66
|
feature_id = str(feature["id"])
|
|
39
67
|
required_tier = feature.get("plan", {}).get("target_claim_tier")
|
|
68
|
+
active_claims = active_required_feature_claims(feature, index)
|
|
69
|
+
satisfying_claims = [
|
|
70
|
+
claim
|
|
71
|
+
for claim in active_claims
|
|
72
|
+
if claim.get("tier") != "T0"
|
|
73
|
+
and (required_tier is None or CLAIM_TIER_RANK[claim["tier"]] >= CLAIM_TIER_RANK[required_tier])
|
|
74
|
+
and (
|
|
75
|
+
not require_evidenced_status
|
|
76
|
+
or CLAIM_STATUS_RANK.get(claim.get("status"), -999) >= CLAIM_STATUS_RANK["evidenced"]
|
|
77
|
+
)
|
|
78
|
+
]
|
|
79
|
+
if satisfying_claims:
|
|
80
|
+
failures: list[str] = []
|
|
81
|
+
for claim in active_claims:
|
|
82
|
+
claim_tier = str(claim["tier"])
|
|
83
|
+
if claim in satisfying_claims:
|
|
84
|
+
continue
|
|
85
|
+
if required_tier is None or CLAIM_TIER_RANK[claim_tier] < CLAIM_TIER_RANK[required_tier]:
|
|
86
|
+
if not _has_satisfying_successor(claim, satisfying_claims, index):
|
|
87
|
+
failures.append(
|
|
88
|
+
f"features.{feature_id} is capped below implemented by claim {claim['id']} outside satisfying claim lineage"
|
|
89
|
+
)
|
|
90
|
+
return failures
|
|
91
|
+
|
|
40
92
|
failures: list[str] = []
|
|
41
|
-
for claim in
|
|
93
|
+
for claim in active_claims:
|
|
42
94
|
claim_id = str(claim["id"])
|
|
43
95
|
claim_tier = str(claim["tier"])
|
|
44
96
|
claim_status = str(claim.get("status"))
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from ssot_registry.util.registry_lock import save_registry_json_locked
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def save_registry(registry_path: str | Path, registry: dict[str, object]) -> None:
|
|
9
|
-
save_registry_json_locked(registry_path, registry)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/claim_tier_gates.py
RENAMED
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/document_lifecycle.py
RENAMED
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/document_supersession.py
RENAMED
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/feature_requirements.py
RENAMED
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/guards/profile_requirements.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/reports/certification_report.py
RENAMED
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/reports/validation_report.py
RENAMED
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/boundary_snapshot.py
RENAMED
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/published_snapshot.py
RENAMED
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/snapshots/release_snapshot.py
RENAMED
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/templates/registry.full.json
RENAMED
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/templates/registry.minimal.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/bidirectional.py
RENAMED
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/claim_lineage.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/feature_parent_links.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ssot_core-0.2.19.dev1 → ssot_core-0.2.20.dev1}/src/ssot_registry/validators/reservations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|