generated from coulomb/repo-seed
test(incremental): delta maintenance == rebuild, retraction + split (WP-0011 T2)
Verify change-driven maintenance keeps the equivalence index equal to a from-scratch rebuild under add / edit / remove: an edit into a new bucket retracts the stale edge, an edit into equivalence adds one, and removing a connector node propagates a retraction that splits a chorus. Equality checked against a fresh build() oracle on every operation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
84
tests/test_incremental_maintenance.py
Normal file
84
tests/test_incremental_maintenance.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
"""Incremental maintenance == rebuild, with retraction + propagation (SHARD-WP-0011 T2)."""
|
||||||
|
|
||||||
|
from shard_wiki.incremental import EquivalenceIndex
|
||||||
|
from shard_wiki.model import Identity, Page
|
||||||
|
from shard_wiki.provenance import ProvenanceEnvelope
|
||||||
|
|
||||||
|
|
||||||
|
def _page(shard, key, body):
|
||||||
|
return Page(
|
||||||
|
identity=Identity(shard, key),
|
||||||
|
body=body,
|
||||||
|
envelope=ProvenanceEnvelope(source_shard=shard),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _rebuilt(pages, curator=()):
|
||||||
|
idx = EquivalenceIndex()
|
||||||
|
idx.build(pages, curator)
|
||||||
|
return idx
|
||||||
|
|
||||||
|
|
||||||
|
def _equal(a, b):
|
||||||
|
return a.edges() == b.edges() and set(a.groups()) == set(b.groups())
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_keeps_index_equal_to_rebuild():
|
||||||
|
pages = [_page("A", "Foo", "same content here"), _page("B", "Bar", "same content here")]
|
||||||
|
idx = EquivalenceIndex()
|
||||||
|
for p in pages:
|
||||||
|
idx.add(p)
|
||||||
|
assert _equal(idx, _rebuilt(pages))
|
||||||
|
assert idx.groups() # the two collapse
|
||||||
|
|
||||||
|
|
||||||
|
def test_remove_keeps_index_equal_to_rebuild():
|
||||||
|
pages = [
|
||||||
|
_page("A", "Foo", "same content here"),
|
||||||
|
_page("B", "Bar", "same content here"),
|
||||||
|
_page("C", "Baz", "unrelated isolated material entirely"),
|
||||||
|
]
|
||||||
|
idx = _rebuilt(pages)
|
||||||
|
idx.remove(Identity("B", "Bar"))
|
||||||
|
assert _equal(idx, _rebuilt([pages[0], pages[2]]))
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_into_new_bucket_retracts_stale_edge():
|
||||||
|
a = _page("A", "Foo", "shared identical body text")
|
||||||
|
b = _page("B", "Bar", "shared identical body text")
|
||||||
|
idx = _rebuilt([a, b])
|
||||||
|
assert idx.groups() # A ≡ B initially
|
||||||
|
# Edit B to something completely different: it exits A's buckets, the edge is retracted.
|
||||||
|
b2 = _page("B", "Bar", "now totally divergent unrelated prose about nothing")
|
||||||
|
idx.update(b2)
|
||||||
|
assert idx.groups() == () # stale edge gone
|
||||||
|
assert _equal(idx, _rebuilt([a, b2]))
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_into_equivalence_adds_edge():
|
||||||
|
a = _page("A", "Foo", "target body to converge on later")
|
||||||
|
b = _page("B", "Bar", "initially completely separate writing here")
|
||||||
|
idx = _rebuilt([a, b])
|
||||||
|
assert idx.groups() == ()
|
||||||
|
b2 = _page("B", "Bar", "target body to converge on later") # now identical to A
|
||||||
|
idx.update(b2)
|
||||||
|
assert idx.equivalent_to(Identity("A", "Foo")) == frozenset(
|
||||||
|
{Identity("A", "Foo"), Identity("B", "Bar")}
|
||||||
|
)
|
||||||
|
assert _equal(idx, _rebuilt([a, b2]))
|
||||||
|
|
||||||
|
|
||||||
|
def test_removing_connector_splits_a_chorus():
|
||||||
|
# Curator chain A—B—C (no direct A—C): one group of three.
|
||||||
|
a, b, c = (_page("A", "X", "aaa"), _page("B", "Y", "bbb"), _page("C", "Z", "ccc"))
|
||||||
|
idx = EquivalenceIndex()
|
||||||
|
for p in (a, b, c):
|
||||||
|
idx.add(p)
|
||||||
|
idx.bind(a.identity, b.identity)
|
||||||
|
idx.bind(b.identity, c.identity)
|
||||||
|
assert idx.equivalent_to(a.identity) == {a.identity, b.identity, c.identity}
|
||||||
|
# Removing the connector B retracts/propagates: the chorus splits.
|
||||||
|
idx.remove(b.identity)
|
||||||
|
assert idx.groups() == ()
|
||||||
|
chain = [(a.identity, b.identity), (b.identity, c.identity)]
|
||||||
|
assert _equal(idx, _rebuilt([a, c], curator=chain))
|
||||||
Reference in New Issue
Block a user