test_lt_e2e.py python
144 lines 4.8 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 1 day ago
1 """E2e tests for LT loop tightening (§LT.10)."""
2
3 from __future__ import annotations
4
5 import json
6 from pathlib import Path
7 from unittest.mock import patch
8
9 from tests.support import FIXTURES, KIT_ROOT, git_status_runner, run_cli
10 from tools.governance_freshness import GovernanceFreshnessReport
11 from tools.honesty.ledger_io import serialize_entry
12 from tools.honesty.genesis import build_genesis_entry
13
14 _OK_FRESHNESS = GovernanceFreshnessReport(
15 state="ok",
16 message="patched",
17 remediation=None,
18 d1="aligned",
19 d2="aligned",
20 marker_present=True,
21 )
22
23
24 def _seed_honesty_repo(tmp_path: Path, *, require: str) -> None:
25 runner = git_status_runner()
26 assert (
27 run_cli(
28 ["init", "--from-config", str(FIXTURES / "config-git-only.yaml"), "--non-interactive"],
29 cwd=tmp_path,
30 runner=runner,
31 )
32 == 0
33 )
34 cfg = tmp_path / ".overseer" / "config.yaml"
35 base = (FIXTURES / "config-git-only.yaml").read_text(encoding="utf-8")
36 cfg.write_text(
37 base
38 + f"""
39 honesty:
40 enabled: true
41 ledger: .overseer/honesty/VERDICT-LEDGER.jsonl
42 require_verification_evidence: {require}
43 """,
44 encoding="utf-8",
45 )
46 ledger_dir = tmp_path / ".overseer" / "honesty"
47 ledger_dir.mkdir(parents=True, exist_ok=True)
48 genesis = serialize_entry(build_genesis_entry("2026-01-01T00:00:00Z"))
49 (ledger_dir / "VERDICT-LEDGER.jsonl").write_text(genesis + "\n", encoding="utf-8")
50 docs = tmp_path / "docs"
51 (docs / "ROADMAP.md").write_text(
52 "| Phase | Model | Status | Deliverable |\n"
53 "| --- | --- | --- | --- |\n"
54 "| **LT-b Loop tightening build** | Auto | **DONE** | "
55 "`docs/archive/phases/PHASE-LT-LOOP-TIGHTENING.md` |\n",
56 encoding="utf-8",
57 )
58 (docs / "OVERSEER-HANDOVER.md").write_text(
59 "## NEXT SESSION — LT-b\n\n| | |\n| **ID** | **LT-b** |\n\n"
60 "Build verified → `pass` (LT-b-BV-r1).\n",
61 encoding="utf-8",
62 )
63
64
65 def test_warn_mode_done_without_ledger_status_exit_0(tmp_path: Path, capsys) -> None:
66 _seed_honesty_repo(tmp_path, require="warn")
67 runner = git_status_runner()
68 capsys.readouterr()
69 with patch("cli.commands.status.check_governance_freshness", return_value=_OK_FRESHNESS):
70 code = run_cli(
71 ["status", "--json", "--exit-code"],
72 cwd=tmp_path,
73 runner=runner,
74 json_mode=True,
75 )
76 assert code == 0
77 payload = json.loads(capsys.readouterr().out)
78 gate = payload.get("verification_evidence_gate")
79 assert gate is not None
80 assert gate["ok"] is True
81 assert gate["mode"] == "warn"
82 assert gate["matched"] is False
83
84
85 def test_require_mode_done_without_ledger_status_exit_2(tmp_path: Path, capsys) -> None:
86 _seed_honesty_repo(tmp_path, require="require")
87 runner = git_status_runner()
88 capsys.readouterr()
89 with patch("cli.commands.status.check_governance_freshness", return_value=_OK_FRESHNESS):
90 code = run_cli(
91 ["status", "--json", "--exit-code"],
92 cwd=tmp_path,
93 runner=runner,
94 json_mode=True,
95 )
96 assert code == 2
97 payload = json.loads(capsys.readouterr().out)
98 gate = payload["verification_evidence_gate"]
99 assert gate["ok"] is False
100 assert gate["token"] == "missing_verification_evidence"
101
102
103 def _inject_change_log_bullets(handover: Path, count: int) -> None:
104 bullets = "\n\n".join(f"- **2026-01-{day:02d}** — entry {day}" for day in range(1, count + 1))
105 text = handover.read_text(encoding="utf-8")
106 if "<!-- overseer:anchor:change-log -->" in text:
107 start = text.index("<!-- overseer:anchor:change-log -->")
108 end = text.index("<!-- /overseer:anchor:change-log -->")
109 handover.write_text(
110 text[: start + len("<!-- overseer:anchor:change-log -->")]
111 + "\n"
112 + bullets
113 + "\n"
114 + text[end:],
115 encoding="utf-8",
116 )
117 else:
118 handover.write_text(
119 text
120 + "\n<!-- overseer:anchor:change-log -->\n"
121 + bullets
122 + "\n<!-- /overseer:anchor:change-log -->\n",
123 encoding="utf-8",
124 )
125
126
127 def test_compact_then_next_same_fence(tmp_path: Path, capsys) -> None:
128 runner = git_status_runner()
129 assert (
130 run_cli(
131 ["init", "--from-config", str(FIXTURES / "config-git-only.yaml"), "--non-interactive"],
132 cwd=tmp_path,
133 runner=runner,
134 )
135 == 0
136 )
137 handover = tmp_path / "docs" / "OVERSEER-HANDOVER.md"
138 _inject_change_log_bullets(handover, 20)
139 assert run_cli(["handover-compact", "--write", "--keep", "15"], cwd=tmp_path, runner=runner) == 0
140 capsys.readouterr()
141 assert run_cli(["next"], cwd=tmp_path, runner=runner) == 0
142 after_next = capsys.readouterr().out
143 assert "```text" in after_next
144 assert "Model:" in after_next
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 1 day ago