test_honesty_cycle.py python
139 lines 4.5 KB
Raw
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 13 hours ago
1 """End-to-end honesty CLI tests."""
2
3 from __future__ import annotations
4
5 import json
6 from pathlib import Path
7
8 import yaml
9
10 from cli.kit_root import kit_root
11 from tests.support import git_status_runner, honesty_artifact_hash, load_honesty_entry, run_cli, seed_honesty_repo
12
13
14 def _append_verdict(tmp_path: Path, body_name: str = "verdict-pass.json") -> int:
15 artifact_hash = honesty_artifact_hash(tmp_path)
16 entry_path = tmp_path / "entries" / body_name
17 text = entry_path.read_text(encoding="utf-8").replace("PLACEHOLDER", artifact_hash)
18 payload_path = tmp_path / "payload.json"
19 payload_path.write_text(text, encoding="utf-8")
20 return run_cli(
21 ["ledger", "append", "--kind", "verdict", "--file", "payload.json"],
22 cwd=tmp_path,
23 runner=git_status_runner(),
24 kit=kit_root(),
25 )
26
27
28 def test_cli_producer_cannot_append_verdict(tmp_path: Path) -> None:
29 seed_honesty_repo(tmp_path)
30 code = _append_verdict(tmp_path, "verdict-producer.json")
31 assert code == 23
32
33
34 def test_cli_missing_verdict_exit_20(tmp_path: Path) -> None:
35 seed_honesty_repo(tmp_path)
36 code = run_cli(
37 ["honesty-status", "--hook", "board_done", "--artifact", "artifacts/sample.txt", "--json"],
38 cwd=tmp_path,
39 runner=git_status_runner(),
40 kit=kit_root(),
41 json_mode=True,
42 )
43 assert code == 20
44
45
46 def test_cli_tampered_line_exit_22(tmp_path: Path) -> None:
47 seed_honesty_repo(tmp_path)
48 assert _append_verdict(tmp_path) == 0
49 ledger = tmp_path / ".overseer" / "honesty" / "VERDICT-LEDGER.jsonl"
50 text = ledger.read_text(encoding="utf-8")
51 ledger.write_text(text.replace("verdict", "verdictx", 1), encoding="utf-8")
52 code = run_cli(
53 ["ledger", "verify"],
54 cwd=tmp_path,
55 runner=git_status_runner(),
56 kit=kit_root(),
57 )
58 assert code == 22
59
60
61 def test_cli_empty_evidence_exit_24(tmp_path: Path) -> None:
62 seed_honesty_repo(tmp_path)
63 code = _append_verdict(tmp_path, "verdict-empty-evidence.json")
64 assert code == 24
65
66
67 def test_cli_producer_session_rejects_same_session(tmp_path: Path) -> None:
68 seed_honesty_repo(tmp_path)
69 assert _append_verdict(tmp_path, "verdict-same-session.json") == 0
70 code = run_cli(
71 [
72 "honesty-status",
73 "--hook",
74 "board_done",
75 "--artifact",
76 "artifacts/sample.txt",
77 "--producer-session",
78 "producer-session-1",
79 "--json",
80 ],
81 cwd=tmp_path,
82 runner=git_status_runner(),
83 kit=kit_root(),
84 json_mode=True,
85 )
86 assert code == 20
87
88
89 def test_cli_last_verdict_wins(tmp_path: Path, capsys) -> None:
90 seed_honesty_repo(tmp_path)
91 assert _append_verdict(tmp_path) == 0
92 body = load_honesty_entry(tmp_path, "verdict-pass.json")
93 body["actor_session_id"] = "verifier-session-2"
94 second = tmp_path / "second.json"
95 second.write_text(json.dumps(body), encoding="utf-8")
96 assert run_cli(
97 ["ledger", "append", "--kind", "verdict", "--file", "second.json"],
98 cwd=tmp_path,
99 runner=git_status_runner(),
100 kit=kit_root(),
101 ) == 0
102 code = run_cli(
103 ["honesty-status", "--hook", "board_done", "--artifact", "artifacts/sample.txt", "--json"],
104 cwd=tmp_path,
105 runner=git_status_runner(),
106 kit=kit_root(),
107 json_mode=True,
108 )
109 assert code == 0
110 payload = json.loads(capsys.readouterr().out)
111 ledger = (tmp_path / ".overseer" / "honesty" / "VERDICT-LEDGER.jsonl").read_text(encoding="utf-8")
112 last_line = json.loads(ledger.strip().splitlines()[-1])
113 assert payload["matched_verdict_hash"] == last_line["entry_hash"]
114
115
116 def test_cli_unknown_hook_exit_1(tmp_path: Path) -> None:
117 seed_honesty_repo(tmp_path)
118 code = run_cli(
119 ["honesty-status", "--hook", "nope", "--artifact", "artifacts/sample.txt"],
120 cwd=tmp_path,
121 runner=git_status_runner(),
122 kit=kit_root(),
123 )
124 assert code == 1
125
126
127 def test_cli_subset_require_verdict_on_refuses(tmp_path: Path) -> None:
128 seed_honesty_repo(tmp_path)
129 cfg = tmp_path / ".overseer" / "config.yaml"
130 data = yaml.safe_load(cfg.read_text(encoding="utf-8"))
131 data["honesty"]["require_verdict_on"] = ["handoff"]
132 cfg.write_text(yaml.safe_dump(data), encoding="utf-8")
133 code = run_cli(
134 ["honesty-status", "--hook", "board_done", "--artifact", "artifacts/sample.txt"],
135 cwd=tmp_path,
136 runner=git_status_runner(),
137 kit=kit_root(),
138 )
139 assert code == 4
File History 2 commits
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 13 hours ago
sha256:4671b7f787ddbe63ced31c895b688c77ab495653b65a730b423329f26b3c1439 feat: K1-P1 complete — agent provenance, build-verification… Sonnet 4.6 patch 52 days ago