test_gfg_d2_realign_plan.py
python
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
1 day ago
| 1 | """Integration: realign plan/verify under Muse content-hash tips (§D2F.9).""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | from pathlib import Path |
| 6 | from unittest.mock import MagicMock |
| 7 | |
| 8 | from adapters.types import AnchorResult, HeadResult, RealignResult |
| 9 | from tools.governance_hygiene.realign import execute_realign_guard, plan_realign |
| 10 | from tools.governance_hygiene.types import DriftReport, VerifiedReads |
| 11 | |
| 12 | |
| 13 | def _config(tmp_path: Path): |
| 14 | from tests.support import load_fixture_config, write_config |
| 15 | |
| 16 | write_config(tmp_path, "config-muse-git-mirror.yaml") |
| 17 | return load_fixture_config(tmp_path, "config-muse-git-mirror.yaml") |
| 18 | |
| 19 | |
| 20 | def _reads(*, r2_muse: str, r1: str = "b" * 40) -> VerifiedReads: |
| 21 | return VerifiedReads( |
| 22 | regime="muse+git-mirror", |
| 23 | r1_github_main_sha=r1, |
| 24 | r1_command="git rev-parse origin/main", |
| 25 | r2_anchor_sha=r2_muse.lower(), |
| 26 | r2_source=".muse/git-bridge.toml:last_export.muse_commit_id", |
| 27 | r3_canonical_main_sha=r2_muse.lower(), |
| 28 | r3_command="muse rev-parse main", |
| 29 | r4_merged_prs=(), |
| 30 | r5_branch="main", |
| 31 | r5_dirty=False, |
| 32 | r5_regime="muse+git-mirror", |
| 33 | ) |
| 34 | |
| 35 | |
| 36 | def test_plan_realign_skips_when_d2_aligned_despite_git_sha_mismatch(tmp_path: Path) -> None: |
| 37 | tip = "sha256:" + ("a" * 64) |
| 38 | git_sha = "1e734a922a8de5dcac248007b8dfb706c4a0f84e" |
| 39 | muse = tmp_path / ".muse" |
| 40 | muse.mkdir() |
| 41 | (muse / "git-bridge.toml").write_text( |
| 42 | f'[last_export]\nmuse_commit_id = "{tip}"\ngit_sha = "{git_sha}"\n', |
| 43 | encoding="utf-8", |
| 44 | ) |
| 45 | assert tip != git_sha |
| 46 | |
| 47 | config = _config(tmp_path) |
| 48 | adapter = MagicMock() |
| 49 | adapter.repo_root = tmp_path |
| 50 | drift = DriftReport( |
| 51 | d1_handover_vs_git="aligned", |
| 52 | d2_anchor_vs_canonical="aligned", |
| 53 | d3_queue_vs_merged="aligned", |
| 54 | ) |
| 55 | should, reason = plan_realign(config, adapter, _reads(r2_muse=tip), drift) |
| 56 | assert should is False |
| 57 | assert "skip" in reason.lower() |
| 58 | adapter.runner.run.assert_not_called() |
| 59 | |
| 60 | |
| 61 | def test_plan_realign_uses_git_sha_for_ancestry_not_muse_id(tmp_path: Path) -> None: |
| 62 | tip = "sha256:" + ("c" * 64) |
| 63 | git_sha = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| 64 | main = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" |
| 65 | muse = tmp_path / ".muse" |
| 66 | muse.mkdir() |
| 67 | (muse / "git-bridge.toml").write_text( |
| 68 | f'[last_export]\nmuse_commit_id = "{tip}"\ngit_sha = "{git_sha}"\n', |
| 69 | encoding="utf-8", |
| 70 | ) |
| 71 | config = _config(tmp_path) |
| 72 | adapter = MagicMock() |
| 73 | adapter.repo_root = tmp_path |
| 74 | runner = MagicMock() |
| 75 | runner.run.return_value = MagicMock(ok=True) |
| 76 | adapter.runner = runner |
| 77 | |
| 78 | drift = DriftReport( |
| 79 | d1_handover_vs_git="aligned", |
| 80 | d2_anchor_vs_canonical="drifted", |
| 81 | d3_queue_vs_merged="aligned", |
| 82 | ) |
| 83 | reads = _reads(r2_muse=tip, r1=main) |
| 84 | # Force r3 differ so D2 drifted context is honest |
| 85 | reads = VerifiedReads( |
| 86 | regime=reads.regime, |
| 87 | r1_github_main_sha=main, |
| 88 | r1_command=reads.r1_command, |
| 89 | r2_anchor_sha=tip.lower(), |
| 90 | r2_source=reads.r2_source, |
| 91 | r3_canonical_main_sha=("sha256:" + ("d" * 64)).lower(), |
| 92 | r3_command=reads.r3_command, |
| 93 | r4_merged_prs=(), |
| 94 | r5_branch="main", |
| 95 | r5_dirty=False, |
| 96 | r5_regime="muse+git-mirror", |
| 97 | ) |
| 98 | should, reason = plan_realign(config, adapter, reads, drift) |
| 99 | assert should is True |
| 100 | assert "superset" in reason |
| 101 | cmd = runner.run.call_args[0][0] |
| 102 | assert git_sha in cmd |
| 103 | assert "sha256:" not in cmd |
| 104 | |
| 105 | |
| 106 | def test_execute_realign_verify_compares_muse_ids(tmp_path: Path) -> None: |
| 107 | tip = "sha256:" + ("e" * 64) |
| 108 | git_sha = "ffffffffffffffffffffffffffffffffffffffff" |
| 109 | muse = tmp_path / ".muse" |
| 110 | muse.mkdir() |
| 111 | (muse / "git-bridge.toml").write_text( |
| 112 | f'[last_export]\nmuse_commit_id = "{tip}"\ngit_sha = "{git_sha}"\n', |
| 113 | encoding="utf-8", |
| 114 | ) |
| 115 | config = _config(tmp_path) |
| 116 | adapter = MagicMock() |
| 117 | adapter.repo_root = tmp_path |
| 118 | runner = MagicMock() |
| 119 | runner.run.return_value = MagicMock(ok=True) |
| 120 | adapter.runner = runner |
| 121 | adapter.realign.return_value = RealignResult( |
| 122 | would_import=2, |
| 123 | applied=True, |
| 124 | from_ref=git_sha, |
| 125 | to_ref="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", |
| 126 | ) |
| 127 | adapter.read_canonical_anchor.return_value = AnchorResult( |
| 128 | anchor_sha=tip, source=".muse/git-bridge.toml:last_export.muse_commit_id" |
| 129 | ) |
| 130 | adapter.read_head.return_value = HeadResult(sha=tip, kind="muse") |
| 131 | |
| 132 | drift = DriftReport( |
| 133 | d1_handover_vs_git="aligned", |
| 134 | d2_anchor_vs_canonical="drifted", |
| 135 | d3_queue_vs_merged="aligned", |
| 136 | ) |
| 137 | reads = VerifiedReads( |
| 138 | regime="muse+git-mirror", |
| 139 | r1_github_main_sha="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", |
| 140 | r1_command="git rev-parse origin/main", |
| 141 | r2_anchor_sha=("sha256:" + ("0" * 64)).lower(), |
| 142 | r2_source=".muse/git-bridge.toml:last_export.muse_commit_id", |
| 143 | r3_canonical_main_sha=tip.lower(), |
| 144 | r3_command="muse rev-parse main", |
| 145 | r4_merged_prs=(), |
| 146 | r5_branch="main", |
| 147 | r5_dirty=False, |
| 148 | r5_regime="muse+git-mirror", |
| 149 | ) |
| 150 | summary, err = execute_realign_guard( |
| 151 | config, adapter, reads, drift, dry_run=False |
| 152 | ) |
| 153 | assert err is None |
| 154 | assert summary is not None |
| 155 | assert "imported" in summary |
| 156 | # Verify path must not require git_sha == tip |
| 157 | assert git_sha != tip |
File History
1 commit
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
1 day ago