"""Cross-process read-your-writes over the git log + fold parity (SHARD-WP-0009 T3). The git backend's value over the in-memory double is that the totally ordered log is durable and shared: a write by one process/handle is immediately visible to another opening the same ref, and the derived fold is identical to the in-memory fold of the same event sequence (derived = f(log)). """ import os import subprocess import sys import textwrap from pathlib import Path from shard_wiki.coordination import ( DecisionLog, EventType, GitEventStore, InMemoryEventStore, ) _SRC = str(Path(__file__).resolve().parents[1] / "src") def test_new_handle_sees_prior_writes(tmp_path): repo = tmp_path / "coord" writer = DecisionLog(GitEventStore(repo)) writer.append("s", EventType.ALIAS_SET, {"alias": "Home", "target": "shardA:Index"}) writer.append("s", EventType.BINDING_MADE, {"members": ["a", "b"]}) # A second, independent handle on the same repo — read-your-writes across handles. reader = DecisionLog(GitEventStore(repo)) assert [e.seq for e in reader.events("s")] == [0, 1] assert reader.fold("s").resolve_alias("Home") == "shardA:Index" def test_append_in_separate_process_is_visible(tmp_path): repo = tmp_path / "coord" # Seed from this process so the repo exists. DecisionLog(GitEventStore(repo)).append( "s", EventType.ALIAS_SET, {"alias": "A", "target": "x:1"} ) child = textwrap.dedent( f""" from shard_wiki.coordination import DecisionLog, EventType, GitEventStore log = DecisionLog(GitEventStore({str(repo)!r})) log.append("s", EventType.ALIAS_SET, {{"alias": "B", "target": "x:2"}}) """ ) result = subprocess.run( [sys.executable, "-c", child], capture_output=True, text=True, env={"PYTHONPATH": _SRC, "PATH": os.environ.get("PATH", "")}, ) assert result.returncode == 0, result.stderr # This process, with a fresh handle, sees the child's append in order. reader = DecisionLog(GitEventStore(repo)) assert [e.payload["alias"] for e in reader.events("s")] == ["A", "B"] assert [e.seq for e in reader.events("s")] == [0, 1] def test_cross_process_fold_equals_in_memory_fold(tmp_path): sequence = [ (EventType.ALIAS_SET, {"alias": "Home", "target": "shardA:Index"}), (EventType.BINDING_MADE, {"members": ["a", "b"]}), (EventType.BINDING_MADE, {"members": ["b", "c"]}), (EventType.PAGE_FORKED, {"source": "p", "fork": "q"}), (EventType.ALIAS_SET, {"alias": "Home", "target": "shardB:Main"}), ] mem = DecisionLog(InMemoryEventStore()) for typ, payload in sequence: mem.append("s", typ, payload) repo = tmp_path / "coord" DecisionLog(GitEventStore(repo)) # init repo for typ, payload in sequence: # Each append from a fresh handle to simulate distinct writers over time. DecisionLog(GitEventStore(repo)).append("s", typ, payload) git_state = DecisionLog(GitEventStore(repo)).fold("s") mem_state = mem.fold("s") assert git_state.aliases == mem_state.aliases assert git_state.equivalence_groups == mem_state.equivalence_groups assert git_state.equivalent_to("a") == frozenset({"a", "b", "c"})