diff --git a/production-lifecycle-source.json b/production-lifecycle-source.json index e8fb4b71a..190cb13c3 100644 --- a/production-lifecycle-source.json +++ b/production-lifecycle-source.json @@ -1,17 +1,17 @@ { "schema_version": "openadapt.production-readme-source/v1", "repository": "OpenAdaptAI/openadapt-ops", - "source_commit": "ef29c08ad27b05637abc75fc3ceb3e026821fdda", + "source_commit": "9246994b5d2645aed3fe9bfb25163fdce507a27f", "files": { "projection": { "path": "docs/production-lifecycle.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/openadapt-ops/ef29c08ad27b05637abc75fc3ceb3e026821fdda/docs/production-lifecycle.json", - "sha256": "sha256:6c3819c7c68acb1bea8045fa1f059721e535c960707998b8705438f8541fb3d7" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/openadapt-ops/9246994b5d2645aed3fe9bfb25163fdce507a27f/docs/production-lifecycle.json", + "sha256": "sha256:7acc2884b5f70bd94521288d07e0567269501d679cf52f1f216cbaf7b81e6a16" }, "schema": { "path": "docs/schemas/production-lifecycle-public.schema.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/openadapt-ops/ef29c08ad27b05637abc75fc3ceb3e026821fdda/docs/schemas/production-lifecycle-public.schema.json", - "sha256": "sha256:f681a9bb47ff727b409df994e69e62e7c45b38e912911af4c99eca7dd3be40eb" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/openadapt-ops/9246994b5d2645aed3fe9bfb25163fdce507a27f/docs/schemas/production-lifecycle-public.schema.json", + "sha256": "sha256:c6db48d6089314d745c2cf1af7bced511f359c7fee9cacc2e35b758fc22d7073" } } } diff --git a/scripts/render_readme_maturity.py b/scripts/render_readme_maturity.py index bb5137ebc..4494c9e25 100644 --- a/scripts/render_readme_maturity.py +++ b/scripts/render_readme_maturity.py @@ -47,6 +47,9 @@ "evidence_manifest_schema": ( "schemas/production-lifecycle-evidence-manifest.schema.json" ), + "evidence_registry": "evidence-registry.json", + "evidence_registry_schema": "schemas/evidence-registry.schema.json", + "evidence_registry_validator": "scripts/validate_evidence_registry.py", "evidence_summary_schema": ( "schemas/production-lifecycle-evidence-summary.schema.json" ), @@ -307,6 +310,14 @@ def _run_canonical_validator(inputs: Mapping[str, bytes]) -> dict[str, str]: if spec is None or spec.loader is None: raise MaturityError("canonical lifecycle validator cannot be loaded") module = importlib.util.module_from_spec(spec) + # The validator imports its sibling scripts by bare module name, so the + # materialized script directory has to be importable. It is prepended + # for the duration of the call and removed again, together with every + # module the validator imported from it, so nothing leaks into the + # importing process. + script_directory = str(validator_path.parent) + sys.path.insert(0, script_directory) + before = set(sys.modules) try: spec.loader.exec_module(module) active = module.validate_files(root) @@ -314,6 +325,15 @@ def _run_canonical_validator(inputs: Mapping[str, bytes]) -> dict[str, str]: raise MaturityError( f"canonical lifecycle validator refused: {exc}" ) from exc + finally: + for name in set(sys.modules) - before: + origin = getattr(sys.modules[name], "__file__", None) + if origin is not None and origin.startswith(script_directory): + del sys.modules[name] + try: + sys.path.remove(script_directory) + except ValueError: + pass if not isinstance(active, dict) or not all( isinstance(key, str) and isinstance(value, str) for key, value in active.items() ):