Files
llm-wiki/harness/tests/test_semantic_certificate.py
T

197 lines
9.2 KiB
Python

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"
"<!-- section-id: branch-contract-packet -->\n## 계약\ncontract assertion\n"
"<!-- section-id: scope -->\n## 범위\nscope assertion\n"
"<!-- section-id: decision-evidence -->\n## 근거\nevidence assertion\n"
"<!-- section-id: implementation -->\n## 구현\nimplementation assertion\n"
"<!-- section-id: edge-failure-dependency -->\n## 실패\nfailure assertion\n"
"<!-- section-id: claims-to-verify -->\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()