test_gs_paste_cycle.py python
102 lines 3.8 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 9 hours ago
1 """E2E: governance-sync --write regenerates NEXT/paste on git-only (§GSP.10)."""
2
3 from __future__ import annotations
4
5 from datetime import date as real_date
6 from pathlib import Path
7
8 from cli.kit_root import kit_root
9 from tests.support import FIXTURES, make_runner, ok, run_cli, write_config
10 from tools.governance_hygiene.anchors import anchor_close, anchor_open
11
12
13 def _seed(tmp_path: Path) -> None:
14 write_config(tmp_path, "config-git-only.yaml")
15 docs = tmp_path / "docs"
16 docs.mkdir(parents=True, exist_ok=True)
17 (docs / "OVERSEER-HANDOVER.md").write_text(
18 (FIXTURES / "gs-paste-handover.md").read_text(encoding="utf-8"),
19 encoding="utf-8",
20 )
21 (docs / "ROADMAP.md").write_text(
22 (FIXTURES / "gs-paste-roadmap-one-open.md").read_text(encoding="utf-8"),
23 encoding="utf-8",
24 )
25
26
27 def _runner() -> object:
28 return make_runner(
29 {
30 "git rev-parse --abbrev-ref HEAD": ok("main"),
31 "git status --porcelain": ok(""),
32 "git rev-parse origin/main": ok("cafebabe"),
33 "gh pr list --state merged --limit 5 --json number,title,mergeCommit,mergedAt": ok("[]"),
34 "git remote get-url origin": ok("[email protected]:owner/repo.git"),
35 "git checkout -b feat/governance-sync-2026-07-30": ok(""),
36 "git checkout feat/governance-sync-2026-07-30": ok(""),
37 "git add -- docs/OVERSEER-HANDOVER.md docs/ROADMAP.md": ok(""),
38 "git commit -m": ok(""),
39 "git rev-parse HEAD": ok("feedface"),
40 "git push -u origin feat/governance-sync-2026-07-30": ok(""),
41 }
42 )
43
44
45 def test_write_regenerates_anchors_idempotent(tmp_path: Path, monkeypatch) -> None:
46 _seed(tmp_path)
47
48 class FixedDate:
49 @staticmethod
50 def today():
51 return real_date(2026, 7, 30)
52
53 monkeypatch.setattr("tools.governance_hygiene.engine.date", FixedDate)
54 monkeypatch.setattr("tools.governance_hygiene.patch.date", FixedDate)
55
56 handover = tmp_path / "docs" / "OVERSEER-HANDOVER.md"
57 runner = _runner()
58 code = run_cli(
59 ["governance-sync", "--write"],
60 cwd=tmp_path,
61 runner=runner,
62 kit=kit_root(),
63 )
64 assert code == 0
65 text = handover.read_text(encoding="utf-8")
66 assert anchor_open("next-session") in text
67 assert anchor_close("next-session") in text
68 assert anchor_open("paste-ready-prompt") in text
69 assert "| **ID** | **GS-PASTE-b** |" in text
70 assert "Model: Auto" in text
71 assert "Authority: authoritative" in text
72 assert not any(call[0].startswith("git push") and " main" in call[0] for call in runner.calls)
73 push_main = [c for c in runner.calls if "git push" in c[0] and c[0].rstrip().endswith(" main")]
74 assert not push_main
75
76 first_next = text.split(anchor_open("next-session"), 1)[1].split(
77 anchor_close("next-session"), 1
78 )[0]
79 first_paste = text.split(anchor_open("paste-ready-prompt"), 1)[1].split(
80 anchor_close("paste-ready-prompt"), 1
81 )[0]
82
83 # Align D1 so second run still plans if needed; force drift via handover main claim.
84 # Second apply with same queue + sync_date must be byte-identical on NEXT/paste.
85 handover.write_text(text.replace("cafebabe", "deadbeef"), encoding="utf-8")
86 code2 = run_cli(
87 ["governance-sync", "--write"],
88 cwd=tmp_path,
89 runner=runner,
90 kit=kit_root(),
91 )
92 assert code2 == 0
93 text2 = handover.read_text(encoding="utf-8")
94 second_next = text2.split(anchor_open("next-session"), 1)[1].split(
95 anchor_close("next-session"), 1
96 )[0]
97 second_paste = text2.split(anchor_open("paste-ready-prompt"), 1)[1].split(
98 anchor_close("paste-ready-prompt"), 1
99 )[0]
100 assert second_next == first_next
101 assert second_paste == first_paste
102 assert not any("muse" in call[0].lower() for call in runner.calls)
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 8 hours ago