init: document-haness 하네스 설계

This commit is contained in:
DongHyeonka
2026-07-24 13:58:08 +09:00
parent d6f78f92a0
commit c39406bbdd
219 changed files with 7010 additions and 20052 deletions
+86
View File
@@ -0,0 +1,86 @@
from __future__ import annotations
import hashlib
import json
import tempfile
import unittest
from pathlib import Path
from claridoc.models import PipelineConfig
from claridoc.pipeline import _mock_provider_warning, run_pipeline
from claridoc.templates import mock_pipeline_config
from tests.helpers import make_brief, make_sources
class PipelineTests(unittest.TestCase):
def test_mixed_mock_pipeline_is_explicitly_flagged(self) -> None:
config_data = mock_pipeline_config()
config_data["writer"] = {"provider": "claude"}
warning = _mock_provider_warning(PipelineConfig.from_dict(config_data))
self.assertIn("mixes external providers", warning)
self.assertIn("synthetic", warning)
def test_end_to_end_mock_run_creates_auditable_artifacts(self) -> None:
with tempfile.TemporaryDirectory() as temp:
output = Path(temp) / "run"
result = run_pipeline(
make_brief(),
make_sources(),
PipelineConfig.from_dict(mock_pipeline_config()),
output,
)
self.assertTrue(result.passed)
self.assertTrue(result.final_path.is_file())
self.assertTrue(result.report_path.is_file())
self.assertTrue(result.manifest_path.is_file())
run_data = json.loads((output / "run.json").read_text(encoding="utf-8"))
self.assertTrue(run_data["passed"])
self.assertTrue(any("deterministic mocks" in warning for warning in result.warnings))
report_text = result.report_path.read_text(encoding="utf-8")
self.assertIn("Provider topology", report_text)
self.assertIn("synthetic", report_text)
manifest = json.loads(result.manifest_path.read_text(encoding="utf-8"))
paths = {item["path"] for item in manifest["files"]}
self.assertIn("final/document.md", paths)
self.assertIn("provider-events.jsonl", paths)
self.assertNotIn("manifest.json", paths)
for item in manifest["files"]:
artifact = output / item["path"]
self.assertEqual(artifact.stat().st_size, item["bytes"])
self.assertEqual(hashlib.sha256(artifact.read_bytes()).hexdigest(), item["sha256"])
def test_revision_limit_is_enforced_when_gate_cannot_pass(self) -> None:
with tempfile.TemporaryDirectory() as temp:
output = Path(temp) / "run"
config_data = mock_pipeline_config()
config_data["quality_gate"]["minimum_score"] = 99
config_data["quality_gate"]["max_revisions"] = 1
result = run_pipeline(
make_brief(),
make_sources(),
PipelineConfig.from_dict(config_data),
output,
)
self.assertFalse(result.passed)
self.assertEqual(len(result.rounds), 2)
self.assertTrue((output / "rounds" / "round-01" / "revision.raw.txt").is_file())
def test_reviewer_role_cannot_escape_artifact_directory(self) -> None:
with tempfile.TemporaryDirectory() as temp:
root = Path(temp)
output = root / "run"
config_data = mock_pipeline_config()
config_data["reviewers"] = [{"role": "../../logic reviewer", "provider": "mock"}]
run_pipeline(
make_brief(),
make_sources(),
PipelineConfig.from_dict(config_data),
output,
)
review_files = list((output / "rounds" / "round-01").glob("review-*"))
self.assertTrue(any(path.name.endswith("logic-reviewer.json") for path in review_files))
self.assertEqual(list(root.glob("logic*")), [])
if __name__ == "__main__":
unittest.main()