generated from coulomb/repo-seed
InformationSpace ties the slice together: conformance-gated attach → resolve → read, with alias() recording coordination decisions in the log. Exposed from the package root. End-to-end integration test (two folder shards → union read with layered provenance + chorus + alias redirect + red-link + nonconformant-rejected). pyflakes clean, 39 tests green. Flips WP-0007 done. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
81 lines
2.8 KiB
Python
81 lines
2.8 KiB
Python
"""End-to-end slice test (SHARD-WP-0007 T7): attach folder shards → resolve → read union."""
|
|
|
|
import shard_wiki
|
|
from shard_wiki import InformationSpace
|
|
from shard_wiki.adapters import ConformanceError, FolderAdapter, ShardAdapter
|
|
from shard_wiki.model import CapabilityProfile, Identity, Page
|
|
from shard_wiki.provenance import ProvenanceEnvelope, Staleness
|
|
from shard_wiki.union import ResolutionKind
|
|
|
|
|
|
def _folder(tmp_path, name, files):
|
|
root = tmp_path / name
|
|
for rel, text in files.items():
|
|
p = root / rel
|
|
p.parent.mkdir(parents=True, exist_ok=True)
|
|
p.write_text(text, encoding="utf-8")
|
|
return FolderAdapter(name, root)
|
|
|
|
|
|
def test_public_api_surface():
|
|
assert isinstance(shard_wiki.__version__, str) and shard_wiki.__version__
|
|
assert shard_wiki.InformationSpace is InformationSpace
|
|
|
|
|
|
def test_attach_resolve_read_union_with_provenance_and_chorus(tmp_path):
|
|
space = InformationSpace("team")
|
|
space.attach(_folder(tmp_path, "wikiA", {"Home.md": "A home", "OnlyA.md": "a"}))
|
|
space.attach(_folder(tmp_path, "wikiB", {"Home.md": "B home", "OnlyB.md": "b"}))
|
|
|
|
# unique page → single, with provenance attributing the source shard
|
|
only_a = space.read("OnlyA")
|
|
assert only_a.body == "a"
|
|
assert only_a.envelope.source_shard == "wikiA"
|
|
assert only_a.envelope.staleness is Staleness.FRESH
|
|
assert only_a.envelope.observed_at is not None
|
|
|
|
# same name in both shards → chorus, divergence recorded both ways (union without erasure)
|
|
res = space.resolve("Home")
|
|
assert res.kind is ResolutionKind.CHORUS
|
|
assert {p.envelope.source_shard for p in res.pages} == {"wikiA", "wikiB"}
|
|
for p in res.pages:
|
|
assert len(p.envelope.divergence) == 1
|
|
|
|
# missing → red-link
|
|
assert space.resolve("Ghost").is_red_link
|
|
|
|
|
|
def test_alias_redirects_across_the_union(tmp_path):
|
|
space = InformationSpace("team")
|
|
space.attach(_folder(tmp_path, "wikiA", {"Index.md": "the index"}))
|
|
space.alias("Start", "wikiA:Index")
|
|
assert space.read("Start").body == "the index"
|
|
|
|
|
|
class _LyingShard(ShardAdapter):
|
|
def __init__(self, profile: CapabilityProfile) -> None:
|
|
self._p = profile
|
|
|
|
@property
|
|
def shard_id(self) -> str:
|
|
return "liar"
|
|
|
|
def profile(self) -> CapabilityProfile:
|
|
return self._p
|
|
|
|
def keys(self):
|
|
return ["X"]
|
|
|
|
def read(self, key: str) -> Page:
|
|
return Page(Identity("not-liar", key), "x", ProvenanceEnvelope(source_shard="x"))
|
|
|
|
|
|
def test_attach_rejects_nonconformant_shard(tmp_path):
|
|
good_profile = _folder(tmp_path, "wikiA", {"Home.md": "x"}).profile()
|
|
space = InformationSpace("team")
|
|
try:
|
|
space.attach(_LyingShard(good_profile))
|
|
raise AssertionError("expected ConformanceError")
|
|
except ConformanceError:
|
|
pass
|