test_governance_freshness_cycle.py python
137 lines 4.3 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 2 days ago
1 """E2E freshness cycle + land-check gate (§GFG.9 e2e)."""
2
3 from __future__ import annotations
4
5 from pathlib import Path
6
7 from adapters.config import load_config
8 from cli.kit_root import kit_root
9 from tests.support import (
10 FIXTURES,
11 git_status_runner,
12 make_runner,
13 ok,
14 run_cli,
15 seed_governance_freshness,
16 write_config,
17 )
18 from tools.close_ritual.land_check import run_land_check
19
20
21 def test_stale_to_fresh_status_cycle(tmp_path: Path) -> None:
22 tip = "cafebabe"
23 runner = git_status_runner(tip=tip)
24 assert (
25 run_cli(
26 ["init", "--from-config", str(FIXTURES / "config-git-only.yaml"), "--non-interactive"],
27 cwd=tmp_path,
28 runner=runner,
29 )
30 == 0
31 )
32 for path in (tmp_path / "docs").glob("*HANDOVER*"):
33 path.write_text("| GitHub `main` | `deadbeef` |\n", encoding="utf-8")
34
35 assert (
36 run_cli(
37 ["status", "--exit-code"],
38 cwd=tmp_path,
39 runner=git_status_runner(tip=tip),
40 )
41 == 2
42 )
43
44 # Align docs + stamp via dry-run when D1/D2 aligned
45 for path in (tmp_path / "docs").glob("*HANDOVER*"):
46 path.write_text(f"| GitHub `main` | `{tip}` |\n", encoding="utf-8")
47 sync_runner = make_runner(
48 {
49 "git rev-parse --abbrev-ref HEAD": ok("main"),
50 "git status --porcelain": ok(""),
51 "git rev-parse origin/main": ok(tip),
52 "gh pr list": ok("[]"),
53 "git remote get-url origin": ok("[email protected]:owner/repo.git"),
54 }
55 )
56 assert (
57 run_cli(
58 ["governance-sync"],
59 cwd=tmp_path,
60 runner=sync_runner,
61 kit=kit_root(),
62 )
63 == 0
64 )
65 assert (tmp_path / ".overseer" / "last_governance_sync").is_file()
66 assert (
67 run_cli(
68 ["status", "--exit-code"],
69 cwd=tmp_path,
70 runner=git_status_runner(tip=tip),
71 )
72 == 0
73 )
74
75
76 def test_land_check_fails_on_freshness_when_enabled(tmp_path: Path) -> None:
77 write_config(tmp_path, "config-git-only.yaml")
78 cfg_path = tmp_path / ".overseer" / "config.yaml"
79 text = cfg_path.read_text(encoding="utf-8")
80 text += (
81 "\nclose_ritual:\n"
82 " enabled: true\n"
83 " mode: verify_landed\n"
84 " require_paths:\n"
85 " - docs/OVERSEER-HANDOVER.md\n"
86 )
87 cfg_path.write_text(text, encoding="utf-8")
88 (tmp_path / ".overseer" / "version.lock").write_text(
89 "lock_version: 1\nkit_version: 0.1.0\nconfig_version: 1\n"
90 "footprint_digest: sha256:" + ("0" * 64) + "\n"
91 "installed_at: \"2026-01-01T00:00:00Z\"\nsynced_at: \"2026-01-01T00:00:00Z\"\n"
92 "footprint: []\n",
93 encoding="utf-8",
94 )
95 docs = tmp_path / "docs"
96 docs.mkdir(parents=True, exist_ok=True)
97 handover = docs / "OVERSEER-HANDOVER.md"
98 handover.write_text("| GitHub `main` | `deadbeef` |\n", encoding="utf-8")
99
100 # Make require_paths "match" main by using a fake git repo without remote —
101 # land-check will fail path match first OR freshness. Seed a matching main
102 # is hard without git; instead use prepare_pr with clean paths after making
103 # a real git repo and committing the file, then still fail on freshness.
104 import subprocess
105
106 subprocess.run(["git", "init", "-b", "main"], cwd=tmp_path, check=True, capture_output=True)
107 subprocess.run(
108 ["git", "config", "user.email", "[email protected]"],
109 cwd=tmp_path,
110 check=True,
111 capture_output=True,
112 )
113 subprocess.run(
114 ["git", "config", "user.name", "t"],
115 cwd=tmp_path,
116 check=True,
117 capture_output=True,
118 )
119 subprocess.run(["git", "add", "docs/OVERSEER-HANDOVER.md"], cwd=tmp_path, check=True, capture_output=True)
120 subprocess.run(
121 ["git", "commit", "-m", "seed"],
122 cwd=tmp_path,
123 check=True,
124 capture_output=True,
125 )
126
127 config = load_config(cfg_path)
128 runner = make_runner(
129 {
130 "git rev-parse --abbrev-ref HEAD": ok("main"),
131 "git status --porcelain": ok(""),
132 "git rev-parse origin/main": ok("cafebabe"),
133 }
134 )
135 result = run_land_check(config, tmp_path, runner=runner)
136 assert result.exit_code == 2
137 assert any("governance_freshness" in m for m in result.messages)
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 2 days ago