test_isr_integration.py python
254 lines 8.1 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 23 hours ago
1 """Integration tests for ISR ledger append and Mode D honesty-status (§ISR.11)."""
2
3 from __future__ import annotations
4
5 from pathlib import Path
6 from unittest.mock import patch
7
8 import yaml
9
10 from tests.fixtures.isr import load_isr_entry, seed_isr_repo
11 from tests.support import FIXTURES, git_status_runner, run_cli
12 from tools.governance_freshness import GovernanceFreshnessReport
13 from tools.honesty.ledger import append_entry, verify_ledger_file
14 from tools.honesty.status import (
15 EXIT_MISSING_INDEPENDENT_SECOND_REVIEW,
16 HonestyStatusOptions,
17 run_honesty_status,
18 )
19 from tools.honesty.types import LedgerAppendOptions
20
21 _OK_FRESHNESS = GovernanceFreshnessReport(
22 state="ok",
23 message="patched",
24 remediation=None,
25 d1="aligned",
26 d2="aligned",
27 marker_present=True,
28 )
29
30
31 def test_append_isr_writes_chain(repo_root) -> None:
32 config = seed_isr_repo(repo_root)
33 body = load_isr_entry("isr-pass.json")
34 assert (
35 append_entry(
36 config=config,
37 repo_root=repo_root,
38 options=LedgerAppendOptions(kind="independent_second_review", body=body),
39 ).exit_code
40 == 0
41 )
42 assert verify_ledger_file(config=config, repo_root=repo_root).exit_code == 0
43
44
45 def test_mode_d_require_missing_exit_38(repo_root) -> None:
46 config = seed_isr_repo(repo_root, require_independent_second_reviewer="require")
47 result = run_honesty_status(
48 config=config,
49 repo_root=repo_root,
50 options=HonestyStatusOptions(
51 hook=None,
52 artifact=None,
53 independent_second_review="ISR-b",
54 ),
55 )
56 assert result.exit_code == EXIT_MISSING_INDEPENDENT_SECOND_REVIEW
57 assert result.json_payload.error == "missing_independent_second_review"
58 assert result.json_payload.independent_second_review is not None
59
60
61 def test_mode_d_matching_pass_exit_0(repo_root) -> None:
62 config = seed_isr_repo(repo_root, require_independent_second_reviewer="require")
63 body = load_isr_entry("isr-pass.json")
64 append_entry(
65 config=config,
66 repo_root=repo_root,
67 options=LedgerAppendOptions(kind="independent_second_review", body=body),
68 )
69 result = run_honesty_status(
70 config=config,
71 repo_root=repo_root,
72 options=HonestyStatusOptions(
73 hook=None,
74 artifact=None,
75 independent_second_review="ISR-b",
76 frozen_spec="docs/archive/phases/PHASE-ISR-INDEPENDENT-SECOND-REVIEWER.md",
77 producer_session="builder-chat-1",
78 ),
79 )
80 assert result.exit_code == 0
81 assert result.json_payload.independent_second_review["matched_entry_hash"] is not None
82
83
84 def test_mode_d_warn_missing_exit_0_with_warning(repo_root) -> None:
85 config = seed_isr_repo(repo_root, require_independent_second_reviewer="warn")
86 result = run_honesty_status(
87 config=config,
88 repo_root=repo_root,
89 options=HonestyStatusOptions(
90 hook=None,
91 artifact=None,
92 independent_second_review="ISR-b",
93 ),
94 )
95 assert result.exit_code == 0
96 assert "warning:" in result.stderr_extra
97
98
99 def test_mode_d_off_not_enforced(repo_root) -> None:
100 config = seed_isr_repo(repo_root, require_independent_second_reviewer="off")
101 result = run_honesty_status(
102 config=config,
103 repo_root=repo_root,
104 options=HonestyStatusOptions(
105 hook=None,
106 artifact=None,
107 independent_second_review="ISR-b",
108 ),
109 )
110 assert result.exit_code == 0
111 assert result.json_payload.independent_second_review["matched_entry_hash"] is None
112
113
114 def test_mode_d_plus_mode_b_exit_1(repo_root) -> None:
115 config = seed_isr_repo(repo_root)
116 result = run_honesty_status(
117 config=config,
118 repo_root=repo_root,
119 options=HonestyStatusOptions(
120 hook=None,
121 artifact=None,
122 independent_second_review="ISR-b",
123 verification_evidence="phase",
124 ),
125 )
126 assert result.exit_code == 1
127
128
129 def test_mode_d_plus_hook_exit_1(repo_root) -> None:
130 config = seed_isr_repo(repo_root)
131 result = run_honesty_status(
132 config=config,
133 repo_root=repo_root,
134 options=HonestyStatusOptions(
135 hook="board_done",
136 artifact=None,
137 independent_second_review="ISR-b",
138 ),
139 )
140 assert result.exit_code == 1
141
142
143 def test_mode_a_without_mode_d_unchanged(repo_root) -> None:
144 config = seed_isr_repo(repo_root)
145 result = run_honesty_status(
146 config=config,
147 repo_root=repo_root,
148 options=HonestyStatusOptions(
149 hook="board_done",
150 artifact="missing.txt",
151 ),
152 )
153 # Module on but artifact missing → refused 4 (pre-ISR Mode A path)
154 assert result.exit_code == 4
155 assert result.json_payload.independent_second_review is None
156
157
158 def test_honesty_disabled_exit_4(repo_root) -> None:
159 config = seed_isr_repo(repo_root, honesty_enabled=False)
160 result = run_honesty_status(
161 config=config,
162 repo_root=repo_root,
163 options=HonestyStatusOptions(
164 hook=None,
165 artifact=None,
166 independent_second_review="ISR-b",
167 ),
168 )
169 assert result.exit_code == 4
170
171
172 def _seed_status_fixture(tmp_path: Path, *, require: str) -> None:
173 runner = git_status_runner()
174 assert (
175 run_cli(
176 ["init", "--from-config", str(FIXTURES / "config-git-only.yaml"), "--non-interactive"],
177 cwd=tmp_path,
178 runner=runner,
179 )
180 == 0
181 )
182 cfg = tmp_path / ".overseer" / "config.yaml"
183 base = (FIXTURES / "config-git-only.yaml").read_text(encoding="utf-8")
184 cfg.write_text(
185 base
186 + f"""
187 honesty:
188 enabled: true
189 ledger: .overseer/honesty/VERDICT-LEDGER.jsonl
190 require_independent_second_reviewer: {require}
191 """,
192 encoding="utf-8",
193 )
194 from tools.honesty.genesis import build_genesis_entry
195 from tools.honesty.ledger_io import serialize_entry
196
197 ledger_dir = tmp_path / ".overseer" / "honesty"
198 ledger_dir.mkdir(parents=True, exist_ok=True)
199 genesis = serialize_entry(build_genesis_entry("2026-01-01T00:00:00Z"))
200 (ledger_dir / "VERDICT-LEDGER.jsonl").write_text(genesis + "\n", encoding="utf-8")
201 docs = tmp_path / "docs"
202 (docs / "ROADMAP.md").write_text(
203 "| Phase | Model | Status | Deliverable |\n"
204 "| --- | --- | --- | --- |\n"
205 "| **ISR-b Independent second reviewer build** | Auto | **DONE** | "
206 "`docs/archive/phases/PHASE-ISR-INDEPENDENT-SECOND-REVIEWER.md` |\n",
207 encoding="utf-8",
208 )
209 (docs / "OVERSEER-HANDOVER.md").write_text(
210 "## NEXT SESSION — ISR-b\n\n| | |\n| **ID** | **ISR-b** |\n\n"
211 "Build verified → `pass` (ISR-b-BV-r1).\n",
212 encoding="utf-8",
213 )
214
215
216 def test_status_require_done_without_isr_exit_2(tmp_path: Path, capsys) -> None:
217 import json
218
219 _seed_status_fixture(tmp_path, require="require")
220 runner = git_status_runner()
221 capsys.readouterr()
222 with patch("cli.commands.status.check_governance_freshness", return_value=_OK_FRESHNESS):
223 code = run_cli(
224 ["status", "--json", "--exit-code"],
225 cwd=tmp_path,
226 runner=runner,
227 json_mode=True,
228 )
229 assert code == 2
230 payload = json.loads(capsys.readouterr().out)
231 gate = payload["independent_second_reviewer_gate"]
232 assert gate["ok"] is False
233 assert gate["token"] == "missing_independent_second_review"
234
235
236 def test_status_require_after_append_not_forced_2(tmp_path: Path) -> None:
237 _seed_status_fixture(tmp_path, require="require")
238 cfg_path = tmp_path / ".overseer" / "config.yaml"
239 config = __import__("adapters.config", fromlist=["load_config"]).load_config(cfg_path)
240 body = load_isr_entry("isr-pass.json")
241 append_entry(
242 config=config,
243 repo_root=tmp_path,
244 options=LedgerAppendOptions(kind="independent_second_review", body=body),
245 )
246 runner = git_status_runner()
247 with patch("cli.commands.status.check_governance_freshness", return_value=_OK_FRESHNESS):
248 code = run_cli(
249 ["status", "--json", "--exit-code"],
250 cwd=tmp_path,
251 runner=runner,
252 json_mode=True,
253 )
254 assert code == 0
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 22 hours ago