"""TDD — bundle._reachable_from must use ancestor_ids, not inline deque BFS. B1 Structural — _reachable_from contains no inline deque/seen BFS B2 Behavioural — returns all commit IDs reachable from tip_ids """ from __future__ import annotations import datetime import inspect import json import pathlib import pytest from muse._version import __version__ from muse.core.object_store import write_object from muse.core.ids import hash_commit, hash_snapshot from muse.core.commits import ( CommitRecord, write_commit, ) from muse.core.snapshots import ( SnapshotRecord, write_snapshot, ) from muse.core.types import blob_id from muse.core.paths import muse_dir def _repo(tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch) -> pathlib.Path: dot_muse = muse_dir(tmp_path) for d in ("commits", "snapshots", "objects", "refs/heads", "remotes"): (dot_muse / d).mkdir(parents=True, exist_ok=True) (dot_muse / "HEAD").write_text("ref: refs/heads/main\n") (dot_muse / "repo.json").write_text( json.dumps({"repo_id": "test-repo", "schema_version": __version__, "domain": "code"}) ) monkeypatch.setenv("MUSE_REPO_ROOT", str(tmp_path)) monkeypatch.chdir(tmp_path) return tmp_path def _make_commit( root: pathlib.Path, parent_id: str | None = None, *, message: str = "test", ) -> CommitRecord: oid = blob_id(b"data-" + message.encode()) write_object(root, oid, b"data-" + message.encode()) manifest = {"f.py": oid} snap_id = hash_snapshot(manifest) write_snapshot(root, SnapshotRecord(snapshot_id=snap_id, manifest=manifest)) ts = datetime.datetime(2026, 1, 1, tzinfo=datetime.timezone.utc) cid = hash_commit( parent_ids=[parent_id] if parent_id else [], snapshot_id=snap_id, message=message, committed_at_iso=ts.isoformat(), ) rec = CommitRecord( commit_id=cid, branch="main", snapshot_id=snap_id, message=message, committed_at=ts, parent_commit_id=parent_id, ) write_commit(root, rec) return rec # --------------------------------------------------------------------------- # B1 Structural # --------------------------------------------------------------------------- def test_b1_reachable_from_uses_ancestor_ids() -> None: """_reachable_from must not contain an inline deque BFS.""" from muse.cli.commands import bundle as bundle_mod src = inspect.getsource(bundle_mod._reachable_from) # type: ignore[attr-defined] assert "ancestor_ids" in src, ( "_reachable_from must delegate to ancestor_ids. " "Replace the inline deque BFS." ) assert "deque" not in src, ( "_reachable_from still uses an inline deque. Replace with ancestor_ids." ) # --------------------------------------------------------------------------- # B2 Behavioural # --------------------------------------------------------------------------- def test_b2_reachable_from_returns_all_reachable( tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch, ) -> None: """_reachable_from returns every commit ID reachable from the tips. Chain: C1 → C2 → C3. Starting from C3, all three must be returned. """ from muse.cli.commands.bundle import _reachable_from # type: ignore[attr-defined] root = _repo(tmp_path, monkeypatch) c1 = _make_commit(root, message="c1") c2 = _make_commit(root, c1.commit_id, message="c2") c3 = _make_commit(root, c2.commit_id, message="c3") result = _reachable_from(root, [c3.commit_id]) assert c1.commit_id in result assert c2.commit_id in result assert c3.commit_id in result