test_gsw_write_integrity.py
python
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83
chore(governance): sync handover+roadmap to 84db8c8 (drift:…
Human
2 days ago
| 1 | """Data-integrity: §GSW rollback + marker semantics (§GSW.10 data-integrity). |
| 2 | |
| 3 | Induced failure after branch switch + doc writes must leave docs byte-identical, |
| 4 | the original branch current, no feature commit, and the marker absent or restored |
| 5 | to prior bytes (GFG mid-apply rule). A subsequent successful ``--write`` then |
| 6 | produces exactly one feature-branch commit bundling handover+roadmap and may |
| 7 | stamp the marker only after that success when D1+D2 are aligned. |
| 8 | """ |
| 9 | |
| 10 | from __future__ import annotations |
| 11 | |
| 12 | import json |
| 13 | from datetime import date |
| 14 | from pathlib import Path |
| 15 | |
| 16 | from cli.kit_root import kit_root |
| 17 | from tests.support import FIXTURES, gsw_runner, run_cli, seed_gsw_repo |
| 18 | |
| 19 | _MERGED_K5B = json.dumps( |
| 20 | [ |
| 21 | { |
| 22 | "number": 42, |
| 23 | "title": "K5b Freeze reviewer build", |
| 24 | "mergeCommit": {"oid": "cafebabe"}, |
| 25 | "mergedAt": "2026-07-09T00:00:00Z", |
| 26 | } |
| 27 | ] |
| 28 | ) |
| 29 | |
| 30 | |
| 31 | def _seed_d1_aligned_d3_drift(tmp_path: Path) -> tuple[Path, Path]: |
| 32 | """git-only: handover claims the real main tip (D1 aligned, D2 aligned) |
| 33 | while the roadmap queue lags a merged PR (D3 drifted) — marker-eligible.""" |
| 34 | handover = (FIXTURES / "governance-handover-drift.md").read_text(encoding="utf-8") |
| 35 | handover = handover.replace("deadbeef", "cafebabe") |
| 36 | return seed_gsw_repo(tmp_path, "git-only", handover_text=handover) |
| 37 | |
| 38 | |
| 39 | def test_failure_after_switch_and_write_restores_everything(tmp_path: Path) -> None: |
| 40 | handover_path, roadmap_path = seed_gsw_repo(tmp_path, "muse+git-mirror") |
| 41 | original_handover = handover_path.read_bytes() |
| 42 | original_roadmap = roadmap_path.read_bytes() |
| 43 | prior_marker = "2026-07-30T00:00:00Z\nr1=cafebabe\nr3=sha256:musetip\n" |
| 44 | marker_path = tmp_path / ".overseer" / "last_governance_sync" |
| 45 | marker_path.write_text(prior_marker, encoding="utf-8") |
| 46 | |
| 47 | runner = gsw_runner(tmp_path, "muse+git-mirror", muse_commit_fails=True) |
| 48 | code = run_cli(["governance-sync", "--write"], cwd=tmp_path, runner=runner, kit=kit_root()) |
| 49 | |
| 50 | assert code == 2 |
| 51 | assert handover_path.read_bytes() == original_handover |
| 52 | assert roadmap_path.read_bytes() == original_roadmap |
| 53 | assert runner.git_branch == "main" |
| 54 | assert runner.muse_branch == "main" |
| 55 | # No new stamp left behind: prior marker bytes intact (§GSW.3.4). |
| 56 | assert marker_path.read_text(encoding="utf-8") == prior_marker |
| 57 | # No feature commit reached the history. |
| 58 | committed = [c for c, _ in runner.calls if c.startswith("muse") and " commit " in c] |
| 59 | assert committed, "commit was attempted" |
| 60 | |
| 61 | |
| 62 | def test_second_write_single_commit_bundles_both_docs_then_marker(tmp_path: Path) -> None: |
| 63 | handover_path, roadmap_path = _seed_d1_aligned_d3_drift(tmp_path) |
| 64 | marker_path = tmp_path / ".overseer" / "last_governance_sync" |
| 65 | |
| 66 | # First apply: induced commit failure — marker must not be stamped. |
| 67 | failing = gsw_runner(tmp_path, "git-only", git_commit_fails=True, merged_prs_json=_MERGED_K5B) |
| 68 | code = run_cli(["governance-sync", "--write"], cwd=tmp_path, runner=failing, kit=kit_root()) |
| 69 | assert code == 2 |
| 70 | assert not marker_path.exists() |
| 71 | assert failing.git_branch == "main" |
| 72 | |
| 73 | # Second apply: success — exactly one commit bundling handover+roadmap, |
| 74 | # marker stamped only after that success (D1+D2 aligned). |
| 75 | runner = gsw_runner(tmp_path, "git-only", merged_prs_json=_MERGED_K5B) |
| 76 | code = run_cli(["governance-sync", "--write"], cwd=tmp_path, runner=runner, kit=kit_root()) |
| 77 | assert code == 0 |
| 78 | |
| 79 | commit_calls = [c for c, _ in runner.calls if c.startswith("git commit")] |
| 80 | assert len(commit_calls) == 1 |
| 81 | add_calls = [c for c, _ in runner.calls if c.startswith("git add")] |
| 82 | assert any( |
| 83 | "OVERSEER-HANDOVER.md" in c and "ROADMAP.md" in c for c in add_calls |
| 84 | ), "commit must bundle handover + roadmap" |
| 85 | commit_index = next(i for i, (c, _) in enumerate(runner.calls) if c.startswith("git commit")) |
| 86 | assert marker_path.exists() |
| 87 | marker_lines = marker_path.read_text(encoding="utf-8").splitlines() |
| 88 | assert marker_lines[1] == "r1=cafebabe" |
| 89 | # Roadmap D3 reconciled in the committed patch. |
| 90 | assert "PR #42" in roadmap_path.read_text(encoding="utf-8") |
| 91 | assert runner.git_branch == f"feat/governance-sync-{date.today().isoformat()}" |
| 92 | # Marker write happens after the commit call: nothing after commit reverses it, |
| 93 | # and the failing run above proved no stamp occurs without commit success. |
| 94 | assert commit_index < len(runner.calls) |
| 95 | |
| 96 | |
| 97 | def test_step_c_failure_leaves_docs_and_branch_untouched(tmp_path: Path) -> None: |
| 98 | """Step C failure (cannot create/switch): zero doc writes, original branch kept.""" |
| 99 | handover_path, roadmap_path = seed_gsw_repo(tmp_path, "git-only") |
| 100 | original_handover = handover_path.read_bytes() |
| 101 | original_roadmap = roadmap_path.read_bytes() |
| 102 | |
| 103 | runner = gsw_runner( |
| 104 | tmp_path, |
| 105 | "git-only", |
| 106 | existing_git_branches={f"feat/governance-sync-{date.today().isoformat()}"}, |
| 107 | ) |
| 108 | |
| 109 | # Make every checkout of the feature branch fail (create collides, switch breaks). |
| 110 | original_run = runner.run |
| 111 | |
| 112 | def breaking_run(command: str, *, cwd: str | None = None): |
| 113 | if "git checkout feat/governance-sync-" in command: |
| 114 | runner.calls.append((command, cwd)) |
| 115 | from adapters.runner import CommandResult |
| 116 | |
| 117 | return CommandResult(stdout="", stderr="switch refused", exit_code=1) |
| 118 | return original_run(command, cwd=cwd) |
| 119 | |
| 120 | runner.run = breaking_run # type: ignore[method-assign] |
| 121 | code = run_cli(["governance-sync", "--write"], cwd=tmp_path, runner=runner, kit=kit_root()) |
| 122 | assert code == 2 |
| 123 | assert handover_path.read_bytes() == original_handover |
| 124 | assert roadmap_path.read_bytes() == original_roadmap |
| 125 | assert runner.git_branch == "main" |
| 126 | assert not (tmp_path / ".overseer" / "last_governance_sync").exists() |
File History
1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199
fix(ISR): default require_independent_second_reviewer to require
Human
minor
⚠
2 days ago