from __future__ import annotations import hashlib import io import json from pathlib import Path import shutil import sys import tempfile import unittest from contextlib import redirect_stdout RUNTIME = Path(__file__).resolve().parents[1] / "runtime" if str(RUNTIME) not in sys.path: sys.path.insert(0, str(RUNTIME)) import semantic_audit # noqa: E402 import semantic_candidate_builder as builder # noqa: E402 import semantic_certificate as certificate # noqa: E402 import semantic_surface_extractor as extractor # noqa: E402 REPO_ROOT = Path(__file__).resolve().parents[2] class SemanticCertificateTest(unittest.TestCase): def setUp(self) -> None: self.tempdir = tempfile.TemporaryDirectory() self.root = Path(self.tempdir.name) for relative in ( "harness/source/typed-contracts.json", str(builder.DEFAULT_ONTOLOGY), str(extractor.DEFAULT_POLICY), str(certificate.DEFAULT_AGENT_METADATA), str(certificate.DEFAULT_AGENT_BODY), "harness/source/execution-profiles.json", ): target = self.root / relative target.parent.mkdir(parents=True, exist_ok=True) shutil.copyfile(REPO_ROOT / relative, target) (self.root / "raw/branch-notes").mkdir(parents=True) (self.root / "raw/project-notes").mkdir(parents=True) self.path = self.root / "raw/branch-notes/feature-certificate.md" self.path.write_text( "---\n" "title: certificate fixture\n" "source_type: branch-note\n" "status: verified\n" "---\n\n" "\n## 계약\ncontract assertion\n" "\n## 범위\nscope assertion\n" "\n## 근거\nevidence assertion\n" "\n## 구현\nimplementation assertion\n" "\n## 실패\nfailure assertion\n" "\n## 주장\nclaims assertion\n", encoding="utf-8", ) policy = extractor.load_policy(self.root) extraction = extractor.extract_document(self.root, self.path, policy) lines = self.path.read_text(encoding="utf-8").splitlines() assertions = [] for index, surface in enumerate(extraction["surfaces"]): line = surface["line_start"] + 1 quote = lines[line - 1] assertions.append({ "assertion_id": f"A{index + 1}", "source_surface": surface["surface_id"], "subject": f"subject-{index}", "predicate": "other", "object": f"object-{index}", "condition": f"condition-{index}", "modality": "observed", "scope": "branch", "quote": quote, "line_start": line, "line_end": line, }) assertion_result = { "schema_version": builder.ASSERTION_SCHEMA, "subject": extraction["path"], "mode": "local", "surface_manifest_sha256": hashlib.sha256(extractor.canonical_json_bytes(extraction)).hexdigest(), "assertions": assertions, } candidate_result = builder.build(self.root, extraction, assertion_result) self.assertEqual(candidate_result["candidates"], []) self.audit_request = semantic_audit.build_verdict_request(candidate_result) self.audit_result = { "schema_version": semantic_audit.AUDIT_RESULT_SCHEMA, "request_sha256": hashlib.sha256(semantic_audit.canonical_json_bytes(self.audit_request)).hexdigest(), "subject": self.audit_request["subject"], "mode": self.audit_request["mode"], "auditor": {"contract_version": "semantic-coherence/v1", "model_id": "test-model", "run_id": "run-1"}, "verdicts": [], } self.validated = semantic_audit.validate_result(self.root, self.audit_request, self.audit_result) def tearDown(self) -> None: self.tempdir.cleanup() def _write_certificate(self) -> Path: path, content, _document = certificate.prepare_certificate( self.root, self.validated, audit_request=self.audit_request, audit_result=self.audit_result, ) path.parent.mkdir(parents=True, exist_ok=True) path.write_bytes(content) return path def test_path_is_hash_of_canonical_subject_and_current_certificate_passes(self) -> None: path = self._write_certificate() expected_id = hashlib.sha256("raw/branch-notes/feature-certificate.md".encode("utf-8")).hexdigest() self.assertEqual(path.parent.name, expected_id) validated = certificate.validate_certificate(self.root, path) self.assertEqual(validated["verdict"], "PASS") self.assertNotIn("issued_at", validated) result = certificate.check(self.root, mode="local") self.assertEqual(result["status"], "PASS") self.assertEqual(result["coverage"], {"required": 1, "current": 1, "missing_or_stale": 0}) self.assertEqual(certificate.check(self.root, mode="hub")["status"], "PASS") output = io.StringIO() with redirect_stdout(output): code = certificate.main([ "--root", str(self.root), "--check", "--mode", "local", "--path", "raw/branch-notes/feature-certificate.md", ]) self.assertEqual(code, 0, output.getvalue()) self.assertEqual(json.loads(output.getvalue())["required_documents"], 1) def test_document_policy_graph_and_auditor_bytes_make_certificate_stale(self) -> None: path = self._write_certificate() self.path.write_text(self.path.read_text(encoding="utf-8") + "changed\n", encoding="utf-8") with self.assertRaises(certificate.SemanticCertificateError) as raised: certificate.validate_certificate(self.root, path) self.assertEqual(raised.exception.code, "SEMANTIC_CERTIFICATE_STALE") self.path.write_text(self.path.read_text(encoding="utf-8").removesuffix("changed\n"), encoding="utf-8") (self.root / certificate.DEFAULT_AGENT_BODY).write_text("changed contract\n", encoding="utf-8") with self.assertRaises(certificate.SemanticCertificateError) as raised: certificate.validate_certificate(self.root, path) self.assertEqual(raised.exception.code, "SEMANTIC_CERTIFICATE_STALE") def test_missing_certificate_fails_required_document(self) -> None: result = certificate.check(self.root) self.assertEqual(result["status"], "FAIL") self.assertEqual(result["findings"][0]["code"], "SEMANTIC_CERTIFICATE_MISSING") def test_embedded_audit_artifact_tampering_invalidates_certificate(self) -> None: path = self._write_certificate() document = json.loads(path.read_text(encoding="utf-8")) document["audit_result"]["auditor"]["run_id"] = "tampered-run" path.write_text(json.dumps(document), encoding="utf-8") with self.assertRaises(certificate.SemanticCertificateError) as raised: certificate.validate_certificate(self.root, path) self.assertEqual(raised.exception.code, "SEMANTIC_CERTIFICATE_STALE") def test_canonical_layout_requires_certificate_for_vault_subject_not_legacy_stub(self) -> None: layout = self.root / "harness/source/vault-layout.json" layout.write_text(json.dumps({"schema_version": "vault-layout/v1", "mode": "canonical", "vault_root": "vault"}), encoding="utf-8") canonical = self.root / "vault/10-projects/sample/branch-notes/feature-certificate.md" canonical.parent.mkdir(parents=True) canonical.write_bytes(self.path.read_bytes()) result = certificate.check(self.root, mode="local") self.assertEqual(result["status"], "FAIL") self.assertEqual(result["required_documents"], 1) self.assertEqual(result["findings"][0]["path"], "vault/10-projects/sample/branch-notes/feature-certificate.md") def test_canonical_mapping_keeps_stable_logical_subject(self) -> None: canonical = self.root / "vault/10-projects/sample/branch-notes/feature-certificate.md" canonical.parent.mkdir(parents=True) canonical.write_bytes(self.path.read_bytes()) layout = self.root / "harness/source/vault-layout.json" layout.write_text(json.dumps({ "schema_version": "vault-layout/v1", "mode": "canonical", "migration_manifest": { "schema_version": "vault-migration/v1", "entries": [{ "legacy_path": "raw/branch-notes/feature-certificate.md", "canonical_path": "vault/10-projects/sample/branch-notes/feature-certificate.md", "sha256": hashlib.sha256(canonical.read_bytes()).hexdigest(), }], }, }), encoding="utf-8") self.assertEqual( certificate.logical_subject(self.root, canonical), "raw/branch-notes/feature-certificate.md", ) if __name__ == "__main__": unittest.main()