test_muse_sync_gate_cycle.py python
100 lines 3.4 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 9 hours ago
1 """E2E: the muse-sync hard gate blocks then clears across review + governance-sync (§KH2.8 e2e tier)."""
2
3 from __future__ import annotations
4
5 import json
6 from pathlib import Path
7
8 from cli.kit_root import kit_root
9 from tests.support import (
10 FIXTURES,
11 ok,
12 make_runner,
13 pass_provider_factory,
14 run_cli,
15 seed_freeze_repo,
16 seed_muse_substrate,
17 )
18
19
20 def _mirror_runner(root: str, *, muse_dirty: bool, git_dirty: bool) -> object:
21 return make_runner(
22 {
23 f"muse -C {root} rev-parse --abbrev-ref HEAD": ok("main"),
24 f"muse -C {root} status --json": ok(json.dumps({"dirty": muse_dirty})),
25 "git rev-parse --abbrev-ref HEAD": ok("main"),
26 "git status --porcelain": ok(" M file" if git_dirty else ""),
27 }
28 )
29
30
31 def test_review_freeze_refuses_then_proceeds_across_a_simulated_muse_commit(tmp_path: Path) -> None:
32 root = str(tmp_path.resolve())
33 artifact = seed_freeze_repo(tmp_path, config_name="config-muse-git-mirror.yaml")
34
35 # Git already committed (clean); Muse has not — the exact failure this phase closes.
36 runner = _mirror_runner(root, muse_dirty=True, git_dirty=False)
37 code = run_cli(
38 ["review", "--freeze", str(artifact.relative_to(tmp_path))],
39 cwd=tmp_path,
40 runner=runner,
41 kit=kit_root(),
42 review_provider_factory=pass_provider_factory(),
43 )
44 assert code == 2
45
46 # Operator runs `muse code add -A && muse commit` — simulate the post-commit state.
47 runner = _mirror_runner(root, muse_dirty=False, git_dirty=False)
48 code = run_cli(
49 ["review", "--freeze", str(artifact.relative_to(tmp_path))],
50 cwd=tmp_path,
51 runner=runner,
52 kit=kit_root(),
53 review_provider_factory=pass_provider_factory(),
54 )
55 assert code == 0
56
57
58 def test_governance_sync_refuses_then_proceeds_across_a_simulated_muse_commit(tmp_path: Path) -> None:
59 root = str(tmp_path.resolve())
60 runner = _mirror_runner(root, muse_dirty=True, git_dirty=False)
61 assert (
62 run_cli(
63 [
64 "init",
65 "--from-config",
66 str(FIXTURES / "config-overseer-kit-dogfood.yaml"),
67 "--non-interactive",
68 ],
69 cwd=tmp_path,
70 runner=runner,
71 )
72 == 0
73 )
74 seed_muse_substrate(tmp_path)
75 (tmp_path / ".muse" / "git-bridge.toml").write_text(
76 '[last_export]\n'
77 'muse_commit_id = "' + ("a" * 40) + '"\n'
78 'git_sha = "' + ("d" * 40) + '"\n'
79 '[last_import]\ngit_sha = "' + ("d" * 40) + '"\n',
80 encoding="utf-8",
81 )
82
83 # Muse still lagging Git — governance-sync must refuse before it does anything else.
84 code = run_cli(["governance-sync", "--dry-run"], cwd=tmp_path, runner=runner)
85 assert code == 2
86
87 # After the catch-up muse commit, Muse and Git agree — governance-sync proceeds.
88 runner = _mirror_runner(root, muse_dirty=False, git_dirty=False)
89 runner.responses.update(
90 {
91 f"muse -C {root} rev-parse main": ok("a" * 40),
92 "git rev-parse origin/main": ok("b" * 40),
93 "git rev-parse origin/muse-mirror": ok("c" * 40),
94 "gh pr list --state merged --limit 5 --json number,title,mergeCommit,mergedAt": ok(
95 json.dumps([])
96 ),
97 }
98 )
99 code = run_cli(["governance-sync", "--dry-run"], cwd=tmp_path, runner=runner)
100 assert code == 0
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 8 hours ago