test_workspace_integrity.py
python
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83
chore(governance): sync handover+roadmap to 84db8c8 (drift:…
Human
9 hours ago
| 1 | """Data-integrity tests for workspace lanes (§MR.10 data-integrity).""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | import os |
| 6 | from pathlib import Path |
| 7 | |
| 8 | import pytest |
| 9 | import yaml |
| 10 | |
| 11 | from adapters.config import load_config |
| 12 | from tools.workspace.check_next import build_status_report, check_next |
| 13 | from tools.workspace.manifest import discover_manifest, load_manifest_file |
| 14 | from tools.workspace.types import WorkspaceLoadError |
| 15 | from tests.fixtures.workspace import build_two_repo_constellation |
| 16 | |
| 17 | |
| 18 | def test_readonly_commands_do_not_mutate(tmp_path: Path) -> None: |
| 19 | fx = build_two_repo_constellation(tmp_path) |
| 20 | before = { |
| 21 | p: p.read_bytes() |
| 22 | for p in fx["scooling"].rglob("*") |
| 23 | if p.is_file() |
| 24 | } |
| 25 | cfg = load_config(fx["scooling"] / ".overseer" / "config.yaml") |
| 26 | build_status_report(cfg, fx["scooling"]) |
| 27 | manifest = load_manifest_file(fx["manifest"], manifest_source="local_workspace") |
| 28 | check_next(manifest) |
| 29 | after = { |
| 30 | p: p.read_bytes() |
| 31 | for p in fx["scooling"].rglob("*") |
| 32 | if p.is_file() |
| 33 | } |
| 34 | assert before == after |
| 35 | |
| 36 | |
| 37 | def test_twice_run_identical_outputs(tmp_path: Path) -> None: |
| 38 | fx = build_two_repo_constellation(tmp_path) |
| 39 | cfg = load_config(fx["scooling"] / ".overseer" / "config.yaml") |
| 40 | a = build_status_report(cfg, fx["scooling"]).to_json() |
| 41 | b = build_status_report(cfg, fx["scooling"]).to_json() |
| 42 | assert a == b |
| 43 | |
| 44 | |
| 45 | def test_tip_hash_stable(tmp_path: Path) -> None: |
| 46 | fx = build_two_repo_constellation(tmp_path) |
| 47 | manifest = load_manifest_file(fx["manifest"], manifest_source="local_workspace") |
| 48 | r1 = check_next(manifest) |
| 49 | r2 = check_next(manifest) |
| 50 | assert r1.primary is not None and r2.primary is not None |
| 51 | assert r1.primary["tip_hash"] == r2.primary["tip_hash"] == fx["tip_hash"] |
| 52 | |
| 53 | |
| 54 | def test_missing_required_member_fail_closed(tmp_path: Path) -> None: |
| 55 | fx = build_two_repo_constellation(tmp_path) |
| 56 | # Point knowtation root at empty path |
| 57 | text = fx["manifest"].read_text(encoding="utf-8") |
| 58 | data = yaml.safe_load(text) |
| 59 | for m in data["members"]: |
| 60 | if m["id"] == "knowtation": |
| 61 | m["root"] = str(tmp_path / "missing-knowtation") |
| 62 | fx["manifest"].write_text(yaml.safe_dump(data), encoding="utf-8") |
| 63 | manifest = load_manifest_file(fx["manifest"], manifest_source="local_workspace") |
| 64 | result = check_next(manifest) |
| 65 | assert result.exit_code == 35 |
| 66 | assert result.state == "missing_member" |
| 67 | |
| 68 | |
| 69 | def test_override_manifest_id_mismatch(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: |
| 70 | fx = build_two_repo_constellation(tmp_path) |
| 71 | other = tmp_path / "other-manifest.yaml" |
| 72 | data = yaml.safe_load(fx["manifest"].read_text(encoding="utf-8")) |
| 73 | data["id"] = "wrong-id" |
| 74 | other.write_text(yaml.safe_dump(data), encoding="utf-8") |
| 75 | monkeypatch.setenv("OVERSEER_WORKSPACE_MANIFEST", str(other)) |
| 76 | cfg = load_config(fx["scooling"] / ".overseer" / "config.yaml") |
| 77 | with pytest.raises(WorkspaceLoadError): |
| 78 | discover_manifest(cfg, fx["scooling"], environ=dict(os.environ)) |
File History
1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199
fix(ISR): default require_independent_second_reviewer to require
Human
minor
⚠
8 hours ago