diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6f82a975..da7f17b7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -222,7 +222,7 @@ jobs: # token). Migrate to project-scoped tokens once the projects exist on PyPI. # # Sequenced via `needs:` because darnit-baseline, darnit-gittuf, - # darnit-reproducibility, and darnit-mcp declare `darnit-core>=...` runtime + # darnit-amber, and darnit-mcp declare `darnit-core>=...` runtime # deps; darnit-mcp additionally depends on the other four. Publishing them # before the deps are on the index briefly produces unresolvable wheels. @@ -289,8 +289,8 @@ jobs: password: ${{ secrets.PYPI_API_TOKEN }} skip-existing: true - publish-darnit-reproducibility: - name: Publish darnit-reproducibility to PyPI + publish-darnit-amber: + name: Publish darnit-amber to PyPI needs: [preflight, build, publish-darnit-core] runs-on: ubuntu-latest timeout-minutes: 10 @@ -303,10 +303,10 @@ jobs: name: dist path: dist/ - - name: Publish darnit-reproducibility + - name: Publish darnit-amber uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 with: - packages-dir: dist/darnit-reproducibility/ + packages-dir: dist/darnit-amber/ password: ${{ secrets.PYPI_API_TOKEN }} skip-existing: true @@ -317,7 +317,7 @@ jobs: - build - publish-darnit-baseline - publish-darnit-gittuf - - publish-darnit-reproducibility + - publish-darnit-amber runs-on: ubuntu-latest timeout-minutes: 10 permissions: @@ -482,7 +482,7 @@ jobs: ## Install - **MCP (Claude Code / Claude Desktop):** \`darnit install\` writes an \`uvx --from darnit-mcp\` config for you. See [docs/install/](https://github.com/${GITHUB_REPOSITORY}/tree/${TAG}/docs/install). - - **PyPI:** \`pip install darnit-mcp==${VERSION}\` (installs the meta-package plus \`darnit-core\`, \`darnit-baseline\`, \`darnit-gittuf\`, \`darnit-reproducibility\`). + - **PyPI:** \`pip install darnit-mcp==${VERSION}\` (installs the meta-package plus \`darnit-core\`, \`darnit-baseline\`, \`darnit-gittuf\`, \`darnit-amber\`). - **Container:** \`docker pull ghcr.io/${owner_lc}/darnit:${TAG}\`. - **Standalone binary / Homebrew:** not yet in this release. Tracked for follow-ups. @@ -512,7 +512,7 @@ jobs: - publish-darnit-core - publish-darnit-baseline - publish-darnit-gittuf - - publish-darnit-reproducibility + - publish-darnit-amber - publish-darnit-mcp - container_build_push - release @@ -527,7 +527,7 @@ jobs: PYPI_CORE: ${{ needs.publish-darnit-core.result }} PYPI_BASELINE: ${{ needs.publish-darnit-baseline.result }} PYPI_GITTUF: ${{ needs.publish-darnit-gittuf.result }} - PYPI_REPRO: ${{ needs.publish-darnit-reproducibility.result }} + PYPI_REPRO: ${{ needs.publish-darnit-amber.result }} PYPI_MCP: ${{ needs.publish-darnit-mcp.result }} CONTAINER: ${{ needs.container_build_push.result }} RELEASE: ${{ needs.release.result }} @@ -540,7 +540,7 @@ jobs: echo "| pypi-darnit-core | $PYPI_CORE |" echo "| pypi-darnit-baseline | $PYPI_BASELINE |" echo "| pypi-darnit-gittuf | $PYPI_GITTUF |" - echo "| pypi-darnit-reproducibility | $PYPI_REPRO |" + echo "| pypi-darnit-amber | $PYPI_REPRO |" echo "| pypi-darnit-mcp | $PYPI_MCP |" echo "| container | $CONTAINER |" echo "| github-release | $RELEASE |" diff --git a/CLAUDE.md b/CLAUDE.md index afcf9dd9..b9cd0321 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -142,7 +142,7 @@ my-framework = "my_framework:register" ### Framework config resolution (feature 021) -`get_framework_config_path()` MUST use `importlib.resources.files(__package__) / ".toml"` -- never `Path(__file__).parent.parent...`. The framework TOML MUST live INSIDE `src//` (alongside `implementation.py`), not sibling to `src/`, so hatchling's default `packages = ["src/"]` includes it in the wheel and `importlib.resources` finds it under both editable and wheel installs. See `packages/darnit-baseline`, `packages/darnit-gittuf`, `packages/darnit-reproducibility` for reference layouts; `packages/darnit-hello` is the minimal template. +`get_framework_config_path()` MUST use `importlib.resources.files(__package__) / ".toml"` -- never `Path(__file__).parent.parent...`. The framework TOML MUST live INSIDE `src//` (alongside `implementation.py`), not sibling to `src/`, so hatchling's default `packages = ["src/"]` includes it in the wheel and `importlib.resources` finds it under both editable and wheel installs. See `packages/darnit-baseline`, `packages/darnit-gittuf`, `packages/darnit-amber` for reference layouts; `packages/darnit-hello` is the minimal template. ## Sieve Pattern @@ -365,7 +365,7 @@ else: ## Active Technologies - Python 3.11/3.12 (workspace targets) plus bash for release scripts and GitHub Actions YAML + `shiv` (binary builder), `cosign` (image + binary signing), `syft` (SBOM generation), `docker buildx` (multi-arch images), `gh` CLI (release creation), Sigstore-action (PyPI wheel signing via `pypa/gh-action-pypi-publish`). No new runtime dependencies in any darnit Python package. (012-packaging-distribution) - External release surfaces only — PyPI, TestPyPI, GHCR, GitHub Releases (binary assets + attestations), `kusari-oss/homebrew-tap` repo (formula). Repo itself stores only build configs and workflow definitions. (012-packaging-distribution) -- Python 3.11/3.12 (workspace targets — same as the rest of darnit) + `pydantic >= 2.0` (already used for `FrameworkConfig`); `packaging` for PEP 440 `SpecifierSet` (declared by `darnit-reproducibility` as of feature 037; darnit-core imports it at runtime without declaring it, which is tracked separately). `tomllib` from stdlib for TOML parsing. No new runtime dependencies. (013-plugin-composition) +- Python 3.11/3.12 (workspace targets — same as the rest of darnit) + `pydantic >= 2.0` (already used for `FrameworkConfig`); `packaging` for PEP 440 `SpecifierSet` (declared by `darnit-amber` as of feature 037; darnit-core imports it at runtime without declaring it, which is tracked separately). `tomllib` from stdlib for TOML parsing. No new runtime dependencies. (013-plugin-composition) - Filesystem only. Composition is resolved in-memory at framework-config load time; no new persistent state. (013-plugin-composition) ## Recent Changes diff --git a/docs/design/reproducibility-attestation-system.md b/docs/design/amber-attestation-system.md similarity index 97% rename from docs/design/reproducibility-attestation-system.md rename to docs/design/amber-attestation-system.md index a0a8e0ed..bd744f0d 100644 --- a/docs/design/reproducibility-attestation-system.md +++ b/docs/design/amber-attestation-system.md @@ -2,7 +2,7 @@ ## Executive Summary -This document describes a system design for **darnit-reproducibility**, an extension to the darnit compliance framework that enables automated reproducibility verification and attestation for computational research software. The system addresses a critical gap in scientific computing: the inability to reliably rebuild and re-execute research software (e.g., protein folding simulations, molecular dynamics, genomics pipelines) in deterministic ways. +This document describes a system design for **darnit-amber**, an extension to the darnit compliance framework that enables automated reproducibility verification and attestation for computational research software. The system addresses a critical gap in scientific computing: the inability to reliably rebuild and re-execute research software (e.g., protein folding simulations, molecular dynamics, genomics pipelines) in deterministic ways. The system operates in two primary flows: @@ -256,7 +256,7 @@ mutation { hasMetadata: { key: "https://darnit.dev/attestations/reproducibility/v1", value: "{...attestation JSON...}", - origin: "darnit-reproducibility", + origin: "darnit-amber", collector: "darnit" } ) @@ -514,7 +514,7 @@ witness_attestation_bundle: #### Ingestor Implementation ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/ingest/witness.py +# packages/darnit-amber/src/darnit_amber/ingest/witness.py from dataclasses import dataclass from typing import Optional, List, Dict, Any @@ -580,7 +580,7 @@ The Provenance Analyzer processes Witness data to understand the complete depend #### Analysis Pipeline ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/analysis/provenance.py +# packages/darnit-amber/src/darnit_amber/analysis/provenance.py from dataclasses import dataclass, field from typing import List, Dict, Set, Optional @@ -745,7 +745,7 @@ Generates environment definitions based on the provenance analysis. #### Generator Interface ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/generate/base.py +# packages/darnit-amber/src/darnit_amber/generate/base.py from abc import ABC, abstractmethod from dataclasses import dataclass @@ -784,7 +784,7 @@ class EnvironmentGenerator(ABC): #### Container Generator (Docker/Singularity) ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/generate/container.py +# packages/darnit-amber/src/darnit_amber/generate/container.py class ContainerGenerator(EnvironmentGenerator): """Generates Dockerfile or Singularity definition files.""" @@ -842,7 +842,7 @@ class ContainerGenerator(EnvironmentGenerator): hardware: HardwareRequirements ) -> str: lines = [ - f"# Auto-generated by darnit-reproducibility", + f"# Auto-generated by darnit-amber", f"# Provenance: {self._provenance_comment()}", f"FROM {base_image}", "", @@ -904,7 +904,7 @@ class ContainerGenerator(EnvironmentGenerator): #### HPC Generator (Slurm/PBS) ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/generate/hpc.py +# packages/darnit-amber/src/darnit_amber/generate/hpc.py class HPCGenerator(EnvironmentGenerator): """Generates HPC job scripts and environment modules.""" @@ -993,7 +993,7 @@ class HPCGenerator(EnvironmentGenerator): #### Nix Generator ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/generate/nix.py +# packages/darnit-amber/src/darnit_amber/generate/nix.py class NixGenerator(EnvironmentGenerator): """Generates Nix derivations for maximum reproducibility.""" @@ -1031,7 +1031,7 @@ class NixGenerator(EnvironmentGenerator): nix_deps: List["NixPackage"] ) -> str: return f'''{{ - description = "Reproducible environment generated by darnit-reproducibility"; + description = "Reproducible environment generated by darnit-amber"; inputs = {{ nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; @@ -1086,7 +1086,7 @@ class NixGenerator(EnvironmentGenerator): Executes builds in generated environments with Witness tracing. ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/execute/engine.py +# packages/darnit-amber/src/darnit_amber/execute/engine.py from dataclasses import dataclass from typing import Optional, List @@ -1224,7 +1224,7 @@ class ExecutionEngine: Generates reproducibility attestations in in-toto format. ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/attestation/reproducibility.py +# packages/darnit-amber/src/darnit_amber/attestation/reproducibility.py from dataclasses import dataclass, field from typing import List, Dict, Any, Optional @@ -1296,7 +1296,7 @@ class ReproducibilityAttestationGenerator: "predicateType": predicate.predicate_type, "predicate": { "assessor": { - "name": "darnit-reproducibility", + "name": "darnit-amber", "version": self.config.version, "timestamp": datetime.utcnow().isoformat() + "Z" }, @@ -1403,7 +1403,7 @@ class ReproducibilityAttestationGenerator: Publishes attestations to OpenSSF GUAC. ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/publish/guac.py +# packages/darnit-amber/src/darnit_amber/publish/guac.py from dataclasses import dataclass from typing import Optional, List, Dict, Any @@ -1554,7 +1554,7 @@ class GUACPublisher: "value": json.dumps(attestation["predicate"]), "timestamp": attestation["predicate"]["assessor"]["timestamp"], "justification": "Reproducibility attestation from darnit", - "origin": "darnit-reproducibility", + "origin": "darnit-amber", "collector": "darnit" } } @@ -1632,7 +1632,7 @@ class GUACPublisher: ### Tool Definitions ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/server/tools.py +# packages/darnit-amber/src/darnit_amber/server/tools.py REPRODUCIBILITY_TOOLS = [ { @@ -1874,12 +1874,12 @@ reproducibility: ### Plugin Registration ```python -# packages/darnit-reproducibility/src/darnit_reproducibility/__init__.py +# packages/darnit-amber/src/darnit_amber/__init__.py from darnit.core.plugin import ComplianceImplementation def register() -> ComplianceImplementation: - """Register darnit-reproducibility as a compliance implementation.""" + """Register darnit-amber as a compliance implementation.""" return ReproducibilityImplementation() class ReproducibilityImplementation: diff --git a/packages/darnit-reproducibility/README.md b/packages/darnit-amber/README.md similarity index 95% rename from packages/darnit-reproducibility/README.md rename to packages/darnit-amber/README.md index 318999c0..7536fdc0 100644 --- a/packages/darnit-reproducibility/README.md +++ b/packages/darnit-amber/README.md @@ -1,4 +1,4 @@ -# darnit-reproducibility +# darnit-amber Scientific reproducibility checks plugin for darnit. diff --git a/packages/darnit-reproducibility/pyproject.toml b/packages/darnit-amber/pyproject.toml similarity index 75% rename from packages/darnit-reproducibility/pyproject.toml rename to packages/darnit-amber/pyproject.toml index 910e760e..57ed993c 100644 --- a/packages/darnit-reproducibility/pyproject.toml +++ b/packages/darnit-amber/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "darnit-reproducibility" +name = "darnit-amber" version = "0.1.0" description = "Scientific reproducibility checks plugin for darnit" readme = "README.md" @@ -15,16 +15,16 @@ dependencies = [ ] [project.entry-points."darnit.implementations"] -reproducibility = "darnit_reproducibility:register" +amber = "darnit_amber:register" [project.entry-points."darnit.frameworks"] -reproducibility = "darnit_reproducibility:get_framework_path" +amber = "darnit_amber:get_framework_path" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] -packages = ["src/darnit_reproducibility"] -# reproducibility.toml lives at src/darnit_reproducibility/reproducibility.toml +packages = ["src/darnit_amber"] +# amber.toml lives at src/darnit_amber/amber.toml # (feature 021) and is packaged automatically by the entry above. diff --git a/packages/darnit-reproducibility/src/darnit_reproducibility/__init__.py b/packages/darnit-amber/src/darnit_amber/__init__.py similarity index 68% rename from packages/darnit-reproducibility/src/darnit_reproducibility/__init__.py rename to packages/darnit-amber/src/darnit_amber/__init__.py index 430ac7b8..213137f5 100644 --- a/packages/darnit-reproducibility/src/darnit_reproducibility/__init__.py +++ b/packages/darnit-amber/src/darnit_amber/__init__.py @@ -2,12 +2,12 @@ from pathlib import Path -from .implementation import ReproducibilityImplementation +from .implementation import AmberImplementation -def register() -> ReproducibilityImplementation: +def register() -> AmberImplementation: """Entry point called by darnit plugin discovery.""" - impl = ReproducibilityImplementation() + impl = AmberImplementation() impl.register_controls() impl.register_sieve_handlers() return impl @@ -19,7 +19,7 @@ def get_framework_path() -> Path: # and name lookup. The 'darnit.implementations' get_framework_config_path() # feeds the audit path instead; both entry points are required. Delegating # here ensures both paths use the same importlib.resources resolver. - return ReproducibilityImplementation().get_framework_config_path() + return AmberImplementation().get_framework_config_path() -__all__ = ["ReproducibilityImplementation", "register", "get_framework_path"] +__all__ = ["AmberImplementation", "register", "get_framework_path"] diff --git a/packages/darnit-reproducibility/src/darnit_reproducibility/reproducibility.toml b/packages/darnit-amber/src/darnit_amber/amber.toml similarity index 98% rename from packages/darnit-reproducibility/src/darnit_reproducibility/reproducibility.toml rename to packages/darnit-amber/src/darnit_amber/amber.toml index bc731804..8af0116a 100644 --- a/packages/darnit-reproducibility/src/darnit_reproducibility/reproducibility.toml +++ b/packages/darnit-amber/src/darnit_amber/amber.toml @@ -1,13 +1,13 @@ [metadata] schema_version = "0.1.0-alpha" -name = "reproducibility" -display_name = "Scientific Reproducibility Checks" +name = "amber" +display_name = "Amber — Scientific Reproducibility Checks" version = "0.1.0" spec_version = "0.1.0" description = "Checks that builds are reproducible and verifiable" [mcp] -name = "reproducibility" +name = "amber" description = "Run scientific reproducibility checks on a repository" [mcp.tools.audit_reproducibility] diff --git a/packages/darnit-reproducibility/src/darnit_reproducibility/container_pinning.py b/packages/darnit-amber/src/darnit_amber/container_pinning.py similarity index 100% rename from packages/darnit-reproducibility/src/darnit_reproducibility/container_pinning.py rename to packages/darnit-amber/src/darnit_amber/container_pinning.py diff --git a/packages/darnit-reproducibility/src/darnit_reproducibility/handlers.py b/packages/darnit-amber/src/darnit_amber/handlers.py similarity index 99% rename from packages/darnit-reproducibility/src/darnit_reproducibility/handlers.py rename to packages/darnit-amber/src/darnit_amber/handlers.py index bb666dcb..41ea9b8a 100644 --- a/packages/darnit-reproducibility/src/darnit_reproducibility/handlers.py +++ b/packages/darnit-amber/src/darnit_amber/handlers.py @@ -15,7 +15,7 @@ from .witness_attestation import WitnessCheckResult, check_witness_attestation -logger = get_logger("darnit_reproducibility.handlers") +logger = get_logger("darnit_amber.handlers") _MAX_EVIDENCE_EXAMPLES = 10 diff --git a/packages/darnit-reproducibility/src/darnit_reproducibility/implementation.py b/packages/darnit-amber/src/darnit_amber/implementation.py similarity index 94% rename from packages/darnit-reproducibility/src/darnit_reproducibility/implementation.py rename to packages/darnit-amber/src/darnit_amber/implementation.py index 2b4f619b..64c66ecb 100644 --- a/packages/darnit-reproducibility/src/darnit_reproducibility/implementation.py +++ b/packages/darnit-amber/src/darnit_amber/implementation.py @@ -4,10 +4,10 @@ from typing import Any from darnit.core.plugin import ControlSpec -from darnit_reproducibility import handlers +from darnit_amber import handlers -class ReproducibilityImplementation: +class AmberImplementation: """Scientific reproducibility checks plugin. Provides checks for dependency pinning, build environment @@ -17,11 +17,11 @@ class ReproducibilityImplementation: @property def name(self) -> str: - return "reproducibility" + return "amber" @property def display_name(self) -> str: - return "Scientific Reproducibility Checks" + return "Amber — Scientific Reproducibility Checks" @property def version(self) -> str: @@ -93,11 +93,11 @@ def get_remediation_registry(self) -> dict[str, Any]: def get_framework_config_path(self) -> Path | None: from importlib.resources import files - resource = files(__package__) / "reproducibility.toml" + resource = files(__package__) / "amber.toml" path = Path(str(resource)) if not path.is_file(): raise FileNotFoundError( - f"reproducibility.toml not found in installed darnit_reproducibility " + f"amber.toml not found in installed darnit_amber " f"package at {path}. This indicates a broken build; check the " f"wheel's force-include configuration." ) diff --git a/packages/darnit-reproducibility/src/darnit_reproducibility/requirements_pins.py b/packages/darnit-amber/src/darnit_amber/requirements_pins.py similarity index 100% rename from packages/darnit-reproducibility/src/darnit_reproducibility/requirements_pins.py rename to packages/darnit-amber/src/darnit_amber/requirements_pins.py diff --git a/packages/darnit-reproducibility/src/darnit_reproducibility/witness_attestation.py b/packages/darnit-amber/src/darnit_amber/witness_attestation.py similarity index 99% rename from packages/darnit-reproducibility/src/darnit_reproducibility/witness_attestation.py rename to packages/darnit-amber/src/darnit_amber/witness_attestation.py index 13016aef..5d00d4b0 100644 --- a/packages/darnit-reproducibility/src/darnit_reproducibility/witness_attestation.py +++ b/packages/darnit-amber/src/darnit_amber/witness_attestation.py @@ -41,7 +41,7 @@ from darnit.core.logging import get_logger from darnit.sieve.handler_registry import HandlerContext -logger = get_logger("darnit_reproducibility.witness_attestation") +logger = get_logger("darnit_amber.witness_attestation") try: from sigstore.models import Bundle diff --git a/packages/darnit/src/darnit/core/discovery.py b/packages/darnit/src/darnit/core/discovery.py index 37ad60ef..3cca04d3 100644 --- a/packages/darnit/src/darnit/core/discovery.py +++ b/packages/darnit/src/darnit/core/discovery.py @@ -111,7 +111,7 @@ def register_implementation_handlers(framework_name: str | None) -> bool: implementations are cached, so repeat calls are cheap and safe. Args: - framework_name: Implementation name (e.g. ``"reproducibility"``). + framework_name: Implementation name (e.g. ``"amber"``). ``None`` is accepted and is a no-op, so callers that may not have resolved a framework do not need to guard. @@ -130,7 +130,7 @@ def register_implementation_handlers(framework_name: str | None) -> bool: # Two method names are in use across in-tree plugins: # register_handlers -- documented in CLAUDE.md; darnit-baseline - # register_sieve_handlers -- darnit-gittuf, darnit-reproducibility + # register_sieve_handlers -- darnit-gittuf, darnit-amber # Those two work today only because their `register()` entry point calls # register_sieve_handlers() during discovery. That is a side channel, not # the protocol: discovery results are cached, so any caller that warmed diff --git a/packaging/README.md b/packaging/README.md index 2f207a91..2b3af2bd 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -95,7 +95,7 @@ Not currently used. rc tags publish directly to real PyPI as GitHub prereleases. - `packages/darnit/pyproject.toml` (name: `darnit-core`) - `packages/darnit-baseline/pyproject.toml` - `packages/darnit-gittuf/pyproject.toml` - - `packages/darnit-reproducibility/pyproject.toml` + - `packages/darnit-amber/pyproject.toml` 4. **Sync and verify locally:** ```bash uv sync --all-extras diff --git a/pyproject.toml b/pyproject.toml index 4765d9d0..7cffdc0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "darnit-core", "darnit-baseline", "darnit-gittuf", - "darnit-reproducibility", + "darnit-amber", ] [project.urls] @@ -31,7 +31,7 @@ Issues = "https://github.com/kusari-oss/darnit/issues" # darnit-mcp is a metadata-only meta-package: no source, only dependencies # that pull in darnit-core, darnit-baseline, darnit-gittuf, and -# darnit-reproducibility. hatchling matches the backend the sibling packages +# darnit-amber. hatchling matches the backend the sibling packages # use; bypass-selection tells it to produce a wheel with no code payload. [build-system] requires = ["hatchling"] @@ -72,7 +72,7 @@ darnit-core = { workspace = true } darnit-baseline = { workspace = true } darnit-example = { workspace = true } darnit-gittuf = { workspace = true } -darnit-reproducibility = { workspace = true } +darnit-amber = { workspace = true } darnit-hello = { workspace = true } darnit-testchecks = { workspace = true } darnit-csl = { workspace = true } diff --git a/scripts/audit_hermetic_real_repos.py b/scripts/audit_hermetic_real_repos.py index a4a13472..81a4b9ba 100644 --- a/scripts/audit_hermetic_real_repos.py +++ b/scripts/audit_hermetic_real_repos.py @@ -15,7 +15,7 @@ import tempfile from pathlib import Path -from darnit_reproducibility.handlers import repro_hermetic_build_handler +from darnit_amber.handlers import repro_hermetic_build_handler from darnit.sieve.handler_registry import HandlerContext diff --git a/tests/darnit/sieve/baseline_capture.py b/tests/darnit/sieve/baseline_capture.py index cc798e49..8600a8ba 100644 --- a/tests/darnit/sieve/baseline_capture.py +++ b/tests/darnit/sieve/baseline_capture.py @@ -54,7 +54,7 @@ # one exercising the most handler dispatch paths. The network-dependent controls # that were dropped are precisely the ones the two-run diff would have excluded # as nondeterministic anyway, so their coverage was illusory. -FRAMEWORK_NAMES = ("reproducibility", "openssf-baseline") +FRAMEWORK_NAMES = ("amber", "openssf-baseline") FIXTURE_NAMES = ("all_pass_repo", "mixed_repo") diff --git a/tests/darnit/sieve/test_handler_authority_regression.py b/tests/darnit/sieve/test_handler_authority_regression.py index c456aa4d..9bf7bf97 100644 --- a/tests/darnit/sieve/test_handler_authority_regression.py +++ b/tests/darnit/sieve/test_handler_authority_regression.py @@ -2,7 +2,7 @@ The `handler_registry.register()` API used to have a `default_authority = "suggestive"` fallback. Every plugin handler in -darnit-gittuf, darnit-reproducibility, and darnit-baseline was registered +darnit-gittuf, darnit-amber, and darnit-baseline was registered without the argument -- so every observation-based control from every plugin silently regressed PASS -> WARN because a suggestive result never terminates the Check phase. @@ -94,7 +94,7 @@ class TestPluginHandlersAreDispositive: # darnit-gittuf "gittuf_verify_policy", "gittuf_commits_signed", - # darnit-reproducibility + # darnit-amber "repro_deps_pinned", "repro_build_env_declared", "repro_hermetic_build", @@ -144,13 +144,13 @@ def _register_all_known_plugin_handlers() -> None: except Exception: pass - # darnit-reproducibility + # darnit-amber try: - from darnit_reproducibility.implementation import ( - ReproducibilityImplementation, + from darnit_amber.implementation import ( + AmberImplementation, ) - ReproducibilityImplementation().register_sieve_handlers() + AmberImplementation().register_sieve_handlers() except Exception: pass diff --git a/tests/darnit/test_plugin_handler_registration.py b/tests/darnit/test_plugin_handler_registration.py index 28f609aa..ae1b5197 100644 --- a/tests/darnit/test_plugin_handler_registration.py +++ b/tests/darnit/test_plugin_handler_registration.py @@ -1,7 +1,7 @@ """Plugin sieve-handler registration and control ordering. Covers issues #427 and #428, both reported against the -`darnit-reproducibility` plugin but rooted in the framework. +`darnit-amber` plugin but rooted in the framework. #427: plugin-provided sieve handlers never reached the registry outside the MCP server path, so every control referencing one fell through to @@ -21,7 +21,7 @@ from darnit.core.discovery import register_implementation_handlers from darnit.sieve.handler_registry import get_sieve_handler_registry -# Handlers shipped by darnit-reproducibility. It is the in-tree plugin that +# Handlers shipped by darnit-amber. It is the in-tree plugin that # exercises the `register_sieve_handlers` spelling (see the naming note in # TestProtocolMethodNaming below). _REPRO_HANDLERS = ( @@ -37,8 +37,8 @@ class TestRegisterImplementationHandlers: """#427: registration must be explicit, not a side effect of discovery.""" @pytest.mark.unit - def test_registers_reproducibility_handlers(self) -> None: - assert register_implementation_handlers("reproducibility") is True + def test_registers_amber_handlers(self) -> None: + assert register_implementation_handlers("amber") is True registry = get_sieve_handler_registry() missing = [h for h in _REPRO_HANDLERS if registry.get(h) is None] @@ -65,7 +65,7 @@ def test_works_when_discovery_cache_is_already_warm(self) -> None: from darnit.core.discovery import discover_implementations discover_implementations() # warm the cache first - assert register_implementation_handlers("reproducibility") is True + assert register_implementation_handlers("amber") is True registry = get_sieve_handler_registry() assert all(registry.get(h) is not None for h in _REPRO_HANDLERS) @@ -82,8 +82,8 @@ def test_unknown_framework_is_a_noop(self) -> None: @pytest.mark.unit def test_is_idempotent(self) -> None: """Called once per audit; repeat calls must not raise.""" - assert register_implementation_handlers("reproducibility") is True - assert register_implementation_handlers("reproducibility") is True + assert register_implementation_handlers("amber") is True + assert register_implementation_handlers("amber") is True @pytest.mark.unit def test_plugin_exception_is_contained(self) -> None: @@ -105,7 +105,7 @@ class TestProtocolMethodNaming: """Both in-tree spellings of the registration method must be honored. `CLAUDE.md` documents `register_handlers()`, and darnit-baseline - implements it. darnit-gittuf and darnit-reproducibility implement + implements it. darnit-gittuf and darnit-amber implement `register_sieve_handlers()` instead. Until those converge, the framework accepts either -- otherwise two of four in-tree plugins register nothing. diff --git a/tests/darnit_reproducibility/__init__.py b/tests/darnit_amber/__init__.py similarity index 100% rename from tests/darnit_reproducibility/__init__.py rename to tests/darnit_amber/__init__.py diff --git a/tests/darnit_reproducibility/baselines/deps_pinned_before.json b/tests/darnit_amber/baselines/deps_pinned_before.json similarity index 100% rename from tests/darnit_reproducibility/baselines/deps_pinned_before.json rename to tests/darnit_amber/baselines/deps_pinned_before.json diff --git a/tests/darnit_reproducibility/conftest.py b/tests/darnit_amber/conftest.py similarity index 97% rename from tests/darnit_reproducibility/conftest.py rename to tests/darnit_amber/conftest.py index d3ff9e5b..812e38ef 100644 --- a/tests/darnit_reproducibility/conftest.py +++ b/tests/darnit_amber/conftest.py @@ -36,7 +36,7 @@ def capture_deps_pinned(repo: Path) -> dict[str, Any]: Imported lazily so this module stays importable regardless of which handler internals exist at any point during the feature's implementation. """ - from darnit_reproducibility.handlers import repro_deps_pinned_handler + from darnit_amber.handlers import repro_deps_pinned_handler result = repro_deps_pinned_handler({}, make_handler_ctx(repo)) return { diff --git a/tests/darnit_reproducibility/fixtures/compound_repo/requirements.txt b/tests/darnit_amber/fixtures/compound_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/compound_repo/requirements.txt rename to tests/darnit_amber/fixtures/compound_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/dev_requirements_repo/requirements-dev.txt b/tests/darnit_amber/fixtures/dev_requirements_repo/requirements-dev.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/dev_requirements_repo/requirements-dev.txt rename to tests/darnit_amber/fixtures/dev_requirements_repo/requirements-dev.txt diff --git a/tests/darnit_reproducibility/fixtures/dev_requirements_repo/requirements/base.txt b/tests/darnit_amber/fixtures/dev_requirements_repo/requirements/base.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/dev_requirements_repo/requirements/base.txt rename to tests/darnit_amber/fixtures/dev_requirements_repo/requirements/base.txt diff --git a/tests/darnit_reproducibility/fixtures/empty_repo/requirements.txt b/tests/darnit_amber/fixtures/empty_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/empty_repo/requirements.txt rename to tests/darnit_amber/fixtures/empty_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/hash_pinned_repo/requirements.txt b/tests/darnit_amber/fixtures/hash_pinned_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/hash_pinned_repo/requirements.txt rename to tests/darnit_amber/fixtures/hash_pinned_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/include_repo/requirements.txt b/tests/darnit_amber/fixtures/include_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/include_repo/requirements.txt rename to tests/darnit_amber/fixtures/include_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/lock_plus_loose_repo/requirements.txt b/tests/darnit_amber/fixtures/lock_plus_loose_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/lock_plus_loose_repo/requirements.txt rename to tests/darnit_amber/fixtures/lock_plus_loose_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/lock_plus_loose_repo/uv.lock b/tests/darnit_amber/fixtures/lock_plus_loose_repo/uv.lock similarity index 100% rename from tests/darnit_reproducibility/fixtures/lock_plus_loose_repo/uv.lock rename to tests/darnit_amber/fixtures/lock_plus_loose_repo/uv.lock diff --git a/tests/darnit_reproducibility/fixtures/markers_repo/requirements.txt b/tests/darnit_amber/fixtures/markers_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/markers_repo/requirements.txt rename to tests/darnit_amber/fixtures/markers_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/mixed_hash_repo/requirements.txt b/tests/darnit_amber/fixtures/mixed_hash_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/mixed_hash_repo/requirements.txt rename to tests/darnit_amber/fixtures/mixed_hash_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/options_repo/requirements.txt b/tests/darnit_amber/fixtures/options_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/options_repo/requirements.txt rename to tests/darnit_amber/fixtures/options_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/partial_pin_repo/requirements.txt b/tests/darnit_amber/fixtures/partial_pin_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/partial_pin_repo/requirements.txt rename to tests/darnit_amber/fixtures/partial_pin_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/unpinned_repo/requirements.txt b/tests/darnit_amber/fixtures/unpinned_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/unpinned_repo/requirements.txt rename to tests/darnit_amber/fixtures/unpinned_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/vcs_branch_repo/requirements.txt b/tests/darnit_amber/fixtures/vcs_branch_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/vcs_branch_repo/requirements.txt rename to tests/darnit_amber/fixtures/vcs_branch_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/vcs_sha_repo/requirements.txt b/tests/darnit_amber/fixtures/vcs_sha_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/vcs_sha_repo/requirements.txt rename to tests/darnit_amber/fixtures/vcs_sha_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/version_pinned_repo/requirements.txt b/tests/darnit_amber/fixtures/version_pinned_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/version_pinned_repo/requirements.txt rename to tests/darnit_amber/fixtures/version_pinned_repo/requirements.txt diff --git a/tests/darnit_reproducibility/fixtures/wildcard_repo/requirements.txt b/tests/darnit_amber/fixtures/wildcard_repo/requirements.txt similarity index 100% rename from tests/darnit_reproducibility/fixtures/wildcard_repo/requirements.txt rename to tests/darnit_amber/fixtures/wildcard_repo/requirements.txt diff --git a/tests/darnit_reproducibility/test_container_pinning.py b/tests/darnit_amber/test_container_pinning.py similarity index 98% rename from tests/darnit_reproducibility/test_container_pinning.py rename to tests/darnit_amber/test_container_pinning.py index d4887439..9885b0ad 100644 --- a/tests/darnit_reproducibility/test_container_pinning.py +++ b/tests/darnit_amber/test_container_pinning.py @@ -8,7 +8,7 @@ from __future__ import annotations import pytest -from darnit_reproducibility.container_pinning import ( +from darnit_amber.container_pinning import ( ContainerClassification, PinKind, classify, diff --git a/tests/darnit_reproducibility/test_deps_pinned_baseline.py b/tests/darnit_amber/test_deps_pinned_baseline.py similarity index 100% rename from tests/darnit_reproducibility/test_deps_pinned_baseline.py rename to tests/darnit_amber/test_deps_pinned_baseline.py diff --git a/tests/darnit_reproducibility/test_handlers.py b/tests/darnit_amber/test_handlers.py similarity index 97% rename from tests/darnit_reproducibility/test_handlers.py rename to tests/darnit_amber/test_handlers.py index d0185383..3c460145 100644 --- a/tests/darnit_reproducibility/test_handlers.py +++ b/tests/darnit_amber/test_handlers.py @@ -3,7 +3,7 @@ from pathlib import Path import pytest -from darnit_reproducibility.handlers import ( +from darnit_amber.handlers import ( _detect_strong_hermeticity_signal, _iter_build_files, _iter_composite_action_files, @@ -19,7 +19,7 @@ repro_hermetic_build_handler, repro_provenance_exists_handler, ) -from darnit_reproducibility.witness_attestation import WitnessCheckResult +from darnit_amber.witness_attestation import WitnessCheckResult from darnit.sieve.handler_registry import HandlerContext, HandlerResultStatus @@ -33,7 +33,7 @@ @pytest.fixture(autouse=True) def _stub_witness_attestation(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr( - "darnit_reproducibility.handlers.check_witness_attestation", + "darnit_amber.handlers.check_witness_attestation", lambda ctx: NO_WITNESS_EVIDENCE, ) @@ -267,7 +267,7 @@ def test_verified_witness_attestation_is_a_signal(self, tmp_path: Path, monkeypa network_clean=True, detail="runtime-trace predicate recorded an empty network log", ) - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: verified) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: verified) signal, witness_result = _detect_strong_hermeticity_signal(tmp_path, [], {}, make_ctx(tmp_path), {}) assert signal is not None assert "Witness" in signal @@ -282,14 +282,14 @@ def test_verified_witness_attestation_with_network_activity_is_not_a_pass_signal network_clean=False, detail="runtime-trace predicate recorded 2 network event(s)", ) - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: dirty) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: dirty) signal, witness_result = _detect_strong_hermeticity_signal(tmp_path, [], {}, make_ctx(tmp_path), {}) assert signal is None assert witness_result.network_clean is False def test_witness_check_disabled_via_config(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: verified = WitnessCheckResult(attempted=True, verified=True, network_clean=True, detail="clean") - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: verified) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: verified) signal, witness_result = _detect_strong_hermeticity_signal( tmp_path, [], {}, make_ctx(tmp_path), {"verify_witness_attestations": False} ) @@ -358,7 +358,7 @@ def test_witness_takes_priority_over_nix(self, tmp_path: Path, monkeypatch: pyte # text-based hint that Witness is in use (e.g. it ran via a reusable # workflow the caller's own CI files never name). verified = WitnessCheckResult(attempted=True, verified=True, network_clean=True, detail="clean") - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: verified) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: verified) (tmp_path / "flake.nix").write_text("{ outputs = {}; }") wf = tmp_path / "ci.yml" wf.write_text("- run: nix build .#default\n") @@ -398,20 +398,20 @@ def spy(ctx: HandlerContext) -> WitnessCheckResult: called = True return WitnessCheckResult(attempted=True, verified=True, network_clean=True) - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", spy) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", spy) result = _maybe_check_witness_attestation(make_ctx(tmp_path), {"verify_witness_attestations": False}) assert called is False assert result.attempted is False def test_enabled_by_default(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: expected = WitnessCheckResult(attempted=True, verified=True, network_clean=True) - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: expected) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: expected) result = _maybe_check_witness_attestation(make_ctx(tmp_path), {}) assert result is expected def test_explicitly_enabled_via_config(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: expected = WitnessCheckResult(attempted=True, verified=True, network_clean=True) - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: expected) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: expected) result = _maybe_check_witness_attestation(make_ctx(tmp_path), {"verify_witness_attestations": True}) assert result is expected @@ -446,9 +446,7 @@ def test_inconclusive_with_pyproject_name_only(self, tmp_path: Path) -> None: assert result.status == HandlerResultStatus.INCONCLUSIVE def test_fail_with_pyproject_dependencies(self, tmp_path: Path) -> None: - (tmp_path / "pyproject.toml").write_text( - "[project]\nname = 'pkg'\ndependencies = ['requests>=2.0']\n" - ) + (tmp_path / "pyproject.toml").write_text("[project]\nname = 'pkg'\ndependencies = ['requests>=2.0']\n") result = repro_deps_pinned_handler({}, make_ctx(tmp_path)) assert result.status == HandlerResultStatus.FAIL @@ -624,7 +622,7 @@ def test_unreadable_file_never_reaches_the_classifier( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """Contract T-7. Cannot be a committed fixture: needs a runtime chmod.""" - import darnit_reproducibility.requirements_pins as pins + import darnit_amber.requirements_pins as pins calls = [] monkeypatch.setattr( @@ -666,7 +664,7 @@ def test_lock_file_short_circuits_before_reading_contents( ) -> None: """FR-001 / US3: the lock file decides and the requirements contents are never consulted.""" - import darnit_reproducibility.requirements_pins as pins + import darnit_amber.requirements_pins as pins calls: list[str] = [] original = pins.classify @@ -928,7 +926,7 @@ def test_pass_verified_witness_attestation(self, tmp_path: Path, monkeypatch: py network_clean=True, detail="runtime-trace predicate recorded an empty network log", ) - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: verified) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: verified) wf_dir = tmp_path / ".github" / "workflows" wf_dir.mkdir(parents=True) (wf_dir / "ci.yml").write_text("steps:\n - uses: testifysec/witness-run-action@v0.1\n") @@ -946,7 +944,7 @@ def test_fail_verified_witness_attestation_with_network_activity( detail="runtime-trace predicate recorded 1 network event(s)", evidence={"artifact": "witness-attestation.json"}, ) - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: dirty) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: dirty) wf_dir = tmp_path / ".github" / "workflows" wf_dir.mkdir(parents=True) (wf_dir / "ci.yml").write_text("steps:\n - run: uv sync\n") @@ -958,7 +956,7 @@ def test_witness_verification_disabled_via_config(self, tmp_path: Path, monkeypa # Even a mocked verified/clean attestation must not produce a PASS # when the pass config opts out of the network round-trip. verified = WitnessCheckResult(attempted=True, verified=True, network_clean=True, detail="clean") - monkeypatch.setattr("darnit_reproducibility.handlers.check_witness_attestation", lambda ctx: verified) + monkeypatch.setattr("darnit_amber.handlers.check_witness_attestation", lambda ctx: verified) wf_dir = tmp_path / ".github" / "workflows" wf_dir.mkdir(parents=True) (wf_dir / "ci.yml").write_text("steps:\n - uses: testifysec/witness-run-action@v0.1\n") diff --git a/tests/darnit_reproducibility/test_implementation.py b/tests/darnit_amber/test_implementation.py similarity index 77% rename from tests/darnit_reproducibility/test_implementation.py rename to tests/darnit_amber/test_implementation.py index 2278d311..22962410 100644 --- a/tests/darnit_reproducibility/test_implementation.py +++ b/tests/darnit_amber/test_implementation.py @@ -1,16 +1,16 @@ -"""Tests for ReproducibilityImplementation plugin protocol compliance.""" +"""Tests for AmberImplementation plugin protocol compliance.""" -from darnit_reproducibility.implementation import ReproducibilityImplementation +from darnit_amber.implementation import AmberImplementation -class TestReproducibilityImplementation: - """Tests that ReproducibilityImplementation satisfies the plugin protocol.""" +class TestAmberImplementation: + """Tests that AmberImplementation satisfies the plugin protocol.""" def setup_method(self): - self.impl = ReproducibilityImplementation() + self.impl = AmberImplementation() def test_name(self) -> None: - assert self.impl.name == "reproducibility" + assert self.impl.name == "amber" def test_display_name(self) -> None: assert len(self.impl.display_name) > 0 @@ -45,12 +45,15 @@ def test_check_handlers_covers_all_controls(self) -> None: get_sieve_handler_registry, reset_sieve_handler_registry, ) + reset_sieve_handler_registry() self.impl.register_sieve_handlers() registry = get_sieve_handler_registry() expected = { - "repro_deps_pinned", "repro_build_env_declared", - "repro_hermetic_build", "repro_provenance_exists", + "repro_deps_pinned", + "repro_build_env_declared", + "repro_hermetic_build", + "repro_provenance_exists", "repro_bit_for_bit", } for name in expected: @@ -61,12 +64,15 @@ def test_all_check_handlers_are_callable(self) -> None: get_sieve_handler_registry, reset_sieve_handler_registry, ) + reset_sieve_handler_registry() self.impl.register_sieve_handlers() registry = get_sieve_handler_registry() for name in [ - "repro_deps_pinned", "repro_build_env_declared", - "repro_hermetic_build", "repro_provenance_exists", + "repro_deps_pinned", + "repro_build_env_declared", + "repro_hermetic_build", + "repro_provenance_exists", "repro_bit_for_bit", ]: info = registry.get(name) diff --git a/tests/darnit_reproducibility/test_repro_corpus.py b/tests/darnit_amber/test_repro_corpus.py similarity index 98% rename from tests/darnit_reproducibility/test_repro_corpus.py rename to tests/darnit_amber/test_repro_corpus.py index 23e061b1..ae620eea 100644 --- a/tests/darnit_reproducibility/test_repro_corpus.py +++ b/tests/darnit_amber/test_repro_corpus.py @@ -18,7 +18,7 @@ from pathlib import Path import pytest -from darnit_reproducibility.handlers import ( +from darnit_amber.handlers import ( repro_bit_for_bit_handler, repro_build_env_declared_handler, repro_deps_pinned_handler, diff --git a/tests/darnit_reproducibility/test_requirements_pins.py b/tests/darnit_amber/test_requirements_pins.py similarity index 99% rename from tests/darnit_reproducibility/test_requirements_pins.py rename to tests/darnit_amber/test_requirements_pins.py index cc8a983f..a38aefeb 100644 --- a/tests/darnit_reproducibility/test_requirements_pins.py +++ b/tests/darnit_amber/test_requirements_pins.py @@ -8,7 +8,7 @@ from __future__ import annotations import pytest -from darnit_reproducibility.requirements_pins import ( +from darnit_amber.requirements_pins import ( FileClassification, PinClassification, classify, diff --git a/tests/darnit_reproducibility/test_requirements_preprocessing.py b/tests/darnit_amber/test_requirements_preprocessing.py similarity index 98% rename from tests/darnit_reproducibility/test_requirements_preprocessing.py rename to tests/darnit_amber/test_requirements_preprocessing.py index 75f3f1cc..9bee36a4 100644 --- a/tests/darnit_reproducibility/test_requirements_preprocessing.py +++ b/tests/darnit_amber/test_requirements_preprocessing.py @@ -8,7 +8,7 @@ from __future__ import annotations import pytest -from darnit_reproducibility.requirements_pins import ( +from darnit_amber.requirements_pins import ( FileClassification, classify, parse, diff --git a/tests/darnit_reproducibility/test_witness_attestation.py b/tests/darnit_amber/test_witness_attestation.py similarity index 98% rename from tests/darnit_reproducibility/test_witness_attestation.py rename to tests/darnit_amber/test_witness_attestation.py index 0fc4cfa3..79437134 100644 --- a/tests/darnit_reproducibility/test_witness_attestation.py +++ b/tests/darnit_amber/test_witness_attestation.py @@ -14,7 +14,7 @@ from typing import Any import pytest -from darnit_reproducibility import witness_attestation as wa +from darnit_amber import witness_attestation as wa from darnit.sieve.handler_registry import HandlerContext @@ -185,7 +185,11 @@ def test_missing_repo_returns_reason(self, tmp_path: Path) -> None: assert "owner/name not available" in reason def test_no_run_found_propagates_reason(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setattr(wa, "_latest_successful_run_id", lambda owner, repo, branch: (None, "no successful CI run found on branch 'main'")) + monkeypatch.setattr( + wa, + "_latest_successful_run_id", + lambda owner, repo, branch: (None, "no successful CI run found on branch 'main'"), + ) files, reason = wa._fetch_candidate_files(make_ctx(), tmp_path) assert files == [] assert "no successful CI run" in reason diff --git a/tests/packaging/test_wheel_install_config.py b/tests/packaging/test_wheel_install_config.py index 8ca32489..99e80016 100644 --- a/tests/packaging/test_wheel_install_config.py +++ b/tests/packaging/test_wheel_install_config.py @@ -1,7 +1,7 @@ """Wheel-install regression test for framework config resolution (feature 021). Every darnit implementation package (darnit-baseline, darnit-gittuf, -darnit-reproducibility) MUST resolve its framework TOML correctly when +darnit-amber) MUST resolve its framework TOML correctly when installed from a built wheel, not just from an editable checkout. This test builds each wheel, installs it into a fresh venv, and asserts: @@ -33,7 +33,7 @@ IMPLEMENTATIONS = [ ("darnit-baseline", "darnit_baseline", "openssf-baseline.toml"), ("darnit-gittuf", "darnit_gittuf", "gittuf.toml"), - ("darnit-reproducibility", "darnit_reproducibility", "reproducibility.toml"), + ("darnit-amber", "darnit_amber", "amber.toml"), ] @@ -172,7 +172,7 @@ def test_framework_config_resolves_under_wheel_install( framework_key = { "darnit-baseline": "openssf-baseline", "darnit-gittuf": "gittuf", - "darnit-reproducibility": "reproducibility", + "darnit-amber": "amber", }[package_name] assert framework_key in combined, ( f"{package_name}: framework key '{framework_key}' not in darnit list output\n" diff --git a/uv.lock b/uv.lock index fb781b55..afce0223 100644 --- a/uv.lock +++ b/uv.lock @@ -8,6 +8,7 @@ resolution-markers = [ [manifest] members = [ + "darnit-amber", "darnit-baseline", "darnit-core", "darnit-csl", @@ -16,7 +17,6 @@ members = [ "darnit-hello", "darnit-mcp", "darnit-plugins", - "darnit-reproducibility", "darnit-testchecks", ] @@ -465,6 +465,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1a/89/843b53614b47f97fe1abc13f9a86efa5ec9e275292c457af1d4a60dc80e0/cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e", size = 3409955, upload-time = "2026-03-25T23:34:48.465Z" }, ] +[[package]] +name = "darnit-amber" +version = "0.1.0" +source = { editable = "packages/darnit-amber" } +dependencies = [ + { name = "darnit-core" }, + { name = "packaging" }, +] + +[package.metadata] +requires-dist = [ + { name = "darnit-core", editable = "packages/darnit" }, + { name = "packaging", specifier = ">=23.0" }, +] + [[package]] name = "darnit-baseline" version = "0.1.0" @@ -572,10 +587,10 @@ name = "darnit-mcp" version = "0.1.0" source = { editable = "." } dependencies = [ + { name = "darnit-amber" }, { name = "darnit-baseline" }, { name = "darnit-core" }, { name = "darnit-gittuf" }, - { name = "darnit-reproducibility" }, ] [package.optional-dependencies] @@ -611,11 +626,11 @@ dev = [ [package.metadata] requires-dist = [ { name = "claude-agent-sdk", marker = "extra == 'parity-tier2'", specifier = ">=0.1.0" }, + { name = "darnit-amber", editable = "packages/darnit-amber" }, { name = "darnit-baseline", editable = "packages/darnit-baseline" }, { name = "darnit-core", editable = "packages/darnit" }, { name = "darnit-core", extras = ["attestation"], marker = "extra == 'attestation'", editable = "packages/darnit" }, { name = "darnit-gittuf", editable = "packages/darnit-gittuf" }, - { name = "darnit-reproducibility", editable = "packages/darnit-reproducibility" }, { name = "openai", marker = "extra == 'parity-tier2'", specifier = ">=1.50" }, { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=4.0.0" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0.0" }, @@ -661,21 +676,6 @@ requires-dist = [ ] provides-extras = ["dev"] -[[package]] -name = "darnit-reproducibility" -version = "0.1.0" -source = { editable = "packages/darnit-reproducibility" } -dependencies = [ - { name = "darnit-core" }, - { name = "packaging" }, -] - -[package.metadata] -requires-dist = [ - { name = "darnit-core", editable = "packages/darnit" }, - { name = "packaging", specifier = ">=23.0" }, -] - [[package]] name = "darnit-testchecks" version = "0.1.0"