test_close_ritual_land_check.py python
175 lines 5.6 KB
Raw
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 1 day ago
1 """Unit tests for close_ritual land-check."""
2
3 from __future__ import annotations
4
5 import subprocess
6 import tempfile
7 import unittest
8 from pathlib import Path
9
10 from adapters.config import load_config
11 from tools.close_ritual.land_check import run_land_check
12
13
14 def _minimal_config_yaml(tmp_path: Path, *, close_ritual: str) -> Path:
15 cfg = tmp_path / ".overseer" / "config.yaml"
16 cfg.parent.mkdir(parents=True)
17 cfg.write_text(
18 f"""
19 overseer_config_version: 1
20 repo:
21 name: fixture
22 root_relative_docs: "."
23 vcs:
24 regime: git-only
25 canonical: git
26 git:
27 remote: origin
28 main_branch: main
29 mirror_branch: null
30 feature_branch_pattern: "feat/{{slug}}"
31 muse:
32 staging_remote: null
33 main_branch: null
34 working_dir: null
35 docs:
36 handover: OVERSEER_HANDOVER.md
37 roadmap: ROADMAP.md
38 standing_decisions: ROADMAP.md
39 thresholds:
40 realign_max_commits: 50
41 drift_warn_only: true
42 freeze_contract:
43 enabled: true
44 reviewer:
45 mode: agent
46 model: thinking-high
47 provider: local
48 fallback: human
49 human_escalation: [security]
50 {close_ritual}
51 """,
52 encoding="utf-8",
53 )
54 return cfg
55
56
57 class CloseRitualLandCheckTests(unittest.TestCase):
58 def test_close_ritual_disabled_noop(self) -> None:
59 with tempfile.TemporaryDirectory() as tmp:
60 tmp_path = Path(tmp)
61 cfg_path = _minimal_config_yaml(
62 tmp_path,
63 close_ritual="close_ritual:\n enabled: false\n require_paths: []\n",
64 )
65 config = load_config(cfg_path)
66 result = run_land_check(config, tmp_path)
67 self.assertEqual(result.exit_code, 0)
68 self.assertFalse(result.auto_merge)
69
70 def test_verify_landed_pass_when_matching(self) -> None:
71 with tempfile.TemporaryDirectory() as tmp:
72 tmp_path = Path(tmp)
73 init = subprocess.run(
74 ["git", "init", "-b", "main"], cwd=tmp_path, capture_output=True, text=True
75 )
76 if init.returncode != 0:
77 self.skipTest(f"git init unavailable: {init.stderr}")
78 subprocess.run(
79 ["git", "config", "user.email", "[email protected]"],
80 cwd=tmp_path,
81 check=True,
82 capture_output=True,
83 )
84 subprocess.run(
85 ["git", "config", "user.name", "t"],
86 cwd=tmp_path,
87 check=True,
88 capture_output=True,
89 )
90 doc = tmp_path / "BOARD.json"
91 doc.write_text('{"ok": true}\n', encoding="utf-8")
92 subprocess.run(["git", "add", "-A"], cwd=tmp_path, check=True, capture_output=True)
93 subprocess.run(
94 ["git", "commit", "-m", "init"],
95 cwd=tmp_path,
96 check=True,
97 capture_output=True,
98 )
99
100 cfg_path = _minimal_config_yaml(
101 tmp_path,
102 close_ritual=(
103 "close_ritual:\n"
104 " enabled: true\n"
105 " mode: verify_landed\n"
106 " require_paths:\n"
107 " - BOARD.json\n"
108 ),
109 )
110 config = load_config(cfg_path)
111 from unittest.mock import patch
112
113 from tools.governance_freshness import GovernanceFreshnessReport
114
115 ok_fresh = GovernanceFreshnessReport(
116 state="not_applicable", message="patched", remediation=None
117 )
118 with patch(
119 "tools.close_ritual.land_check.check_governance_freshness",
120 return_value=ok_fresh,
121 ):
122 result = run_land_check(config, tmp_path)
123 self.assertEqual(result.exit_code, 0, msg=result.messages)
124 self.assertTrue(result.landed)
125 self.assertFalse(result.auto_merge)
126
127 def test_verify_landed_fail_on_mismatch(self) -> None:
128 with tempfile.TemporaryDirectory() as tmp:
129 tmp_path = Path(tmp)
130 init = subprocess.run(
131 ["git", "init", "-b", "main"], cwd=tmp_path, capture_output=True, text=True
132 )
133 if init.returncode != 0:
134 self.skipTest(f"git init unavailable: {init.stderr}")
135 subprocess.run(
136 ["git", "config", "user.email", "[email protected]"],
137 cwd=tmp_path,
138 check=True,
139 capture_output=True,
140 )
141 subprocess.run(
142 ["git", "config", "user.name", "t"],
143 cwd=tmp_path,
144 check=True,
145 capture_output=True,
146 )
147 doc = tmp_path / "BOARD.json"
148 doc.write_text('{"ok": true}\n', encoding="utf-8")
149 subprocess.run(["git", "add", "-A"], cwd=tmp_path, check=True, capture_output=True)
150 subprocess.run(
151 ["git", "commit", "-m", "init"],
152 cwd=tmp_path,
153 check=True,
154 capture_output=True,
155 )
156 doc.write_text('{"ok": false}\n', encoding="utf-8")
157
158 cfg_path = _minimal_config_yaml(
159 tmp_path,
160 close_ritual=(
161 "close_ritual:\n"
162 " enabled: true\n"
163 " mode: verify_landed\n"
164 " require_paths:\n"
165 " - BOARD.json\n"
166 ),
167 )
168 config = load_config(cfg_path)
169 result = run_land_check(config, tmp_path)
170 self.assertEqual(result.exit_code, 1)
171 self.assertFalse(result.landed)
172
173
174 if __name__ == "__main__":
175 unittest.main()
File History 1 commit
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 1 day ago