diff --git a/depone/verify/engine.py b/depone/verify/engine.py index c2e1bf0..7a75982 100644 --- a/depone/verify/engine.py +++ b/depone/verify/engine.py @@ -223,9 +223,11 @@ def _health_entry_matches_gate( return ( entry.code == "ERR_HEALTH_GATE_VIOLATION" and gate.get("exit_code_path") == entry.evidence_path - and f"gate={gate.get('gate')!r}" in entry.message - and f"tool={gate.get('tool')!r}" in entry.message - and f"enforcement={gate.get('enforcement')!r}" in entry.message + and entry.health_gate == { + "gate": gate.get("gate"), + "tool": gate.get("tool"), + "enforcement": gate.get("enforcement"), + } ) diff --git a/depone/verify/evidence_contract.py b/depone/verify/evidence_contract.py index 732144e..577e062 100644 --- a/depone/verify/evidence_contract.py +++ b/depone/verify/evidence_contract.py @@ -20,6 +20,7 @@ class EvidenceContractEntry: code: str message: str evidence_path: str + health_gate: dict[str, str] | None = None _EVIDENCE_CONTRACT_FILENAME = "evidence-contract.json" @@ -852,6 +853,11 @@ def _validate_code_health( f"expected={expected_exit_code}, got={actual_exit_code}" ), evidence_path=exit_code_path, + health_gate={ + "gate": gate["gate"], + "tool": gate["tool"], + "enforcement": enforcement, + }, ) ) return results diff --git a/pyproject.toml b/pyproject.toml index ff14122..c40ce07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "depone" -version = "0.2.9" +version = "0.2.10" description = "Workflow designer + cross-platform evidence verifier for AI agent orchestration" license = { text = "MIT" } readme = "README.md" diff --git a/tests/test_code_health_contract.py b/tests/test_code_health_contract.py index 16592ce..6cac668 100644 --- a/tests/test_code_health_contract.py +++ b/tests/test_code_health_contract.py @@ -8,8 +8,13 @@ from depone.verify.adapters.base import EvidenceContext, EvidenceFile from depone.verify.adapters.generic import read_evidence -from depone.verify.engine import _health_conformance, run_verification -from depone.verify.evidence_contract import validate_evidence_contract +from depone.verify.engine import ( + _health_conformance, + _health_entry_matches_gate, + _is_advisory_health_entry, + run_verification, +) +from depone.verify.evidence_contract import EvidenceContractEntry, validate_evidence_contract def _sha(text: str) -> str: @@ -94,10 +99,53 @@ def test_advisory_gate_failure_records_health_violation_details(self) -> None: self.assertEqual([entry.code for entry in errors], ["ERR_HEALTH_GATE_VIOLATION"]) self.assertEqual(errors[0].evidence_path, "health/complexity.exit") + self.assertEqual( + errors[0].health_gate, + { + "gate": "complexity", + "tool": "ruff-c901", + "enforcement": "advisory", + }, + ) self.assertIn("gate='complexity'", errors[0].message) self.assertIn("tool='ruff-c901'", errors[0].message) self.assertIn("enforcement='advisory'", errors[0].message) + def test_health_classification_uses_typed_metadata_not_message(self) -> None: + gate = _gate("complexity", "ruff-c901", "advisory") + matching = EvidenceContractEntry( + code="ERR_HEALTH_GATE_VIOLATION", + message="mangled operator message", + evidence_path="health/complexity.exit", + health_gate={ + "gate": "complexity", + "tool": "ruff-c901", + "enforcement": "advisory", + }, + ) + conflicting = EvidenceContractEntry( + code="ERR_HEALTH_GATE_VIOLATION", + message=( + "code health gate exit code mismatch: gate='complexity', " + "tool='ruff-c901', enforcement='advisory'" + ), + evidence_path="health/complexity.exit", + health_gate={ + "gate": "complexity", + "tool": "ruff-c901", + "enforcement": "block", + }, + ) + + self.assertTrue(_health_entry_matches_gate(matching, gate)) + self.assertTrue( + _is_advisory_health_entry({"code_health": {"gates": [gate]}}, matching) + ) + self.assertFalse(_health_entry_matches_gate(conflicting, gate)) + self.assertFalse( + _is_advisory_health_entry({"code_health": {"gates": [gate]}}, conflicting) + ) + def test_block_gate_failure_records_health_violation(self) -> None: errors = validate_evidence_contract( _evidence(