generated from coulomb/repo-seed
session-memory Phase 2: versioned Pattern Catalog store (T02)
Files-first catalog (one JSON per pattern, id = source-key). Single idempotent upsert path: added / unchanged / updated (status-only, no bump) / versioned (content change bumps semver + archives prior to <id>.history.jsonl). Dedup is structural on pattern id. 5 new tests; suite 52/52 green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
86
tests/test_curate_catalog.py
Normal file
86
tests/test_curate_catalog.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""Versioned Pattern Catalog tests (T02): round-trip, dedup, idempotent upsert."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from session_memory.curate.catalog import ( # noqa: E402
|
||||
ADDED,
|
||||
UNCHANGED,
|
||||
UPDATED,
|
||||
VERSIONED,
|
||||
Catalog,
|
||||
)
|
||||
from session_memory.curate.schema import ( # noqa: E402
|
||||
Provenance,
|
||||
Resolution,
|
||||
Scope,
|
||||
SolutionPattern,
|
||||
)
|
||||
|
||||
|
||||
def _pattern(src="success:clean_pass:outcome", problem="ran tests, clean finish"):
|
||||
return SolutionPattern(
|
||||
id=SolutionPattern.make_id(src),
|
||||
name="Run tests before declaring success",
|
||||
version="1.0.0",
|
||||
polarity="success",
|
||||
problem=problem,
|
||||
resolutions=[Resolution(summary="run the suite")],
|
||||
scope=Scope(flavors=["claude", "grok"]),
|
||||
provenance=Provenance(source_key=src, evidence={"frequency": 18}),
|
||||
)
|
||||
|
||||
|
||||
def test_add_then_load_round_trips(tmp_path):
|
||||
cat = Catalog(str(tmp_path))
|
||||
assert cat.upsert(_pattern()) == ADDED
|
||||
loaded = cat.load(SolutionPattern.make_id("success:clean_pass:outcome"))
|
||||
assert loaded is not None
|
||||
assert loaded.problem == "ran tests, clean finish"
|
||||
assert loaded.created_at and loaded.updated_at
|
||||
assert [p.id for p in cat.list()] == [loaded.id]
|
||||
|
||||
|
||||
def test_resave_identical_is_noop(tmp_path):
|
||||
cat = Catalog(str(tmp_path))
|
||||
cat.upsert(_pattern())
|
||||
assert cat.upsert(_pattern()) == UNCHANGED
|
||||
# version not bumped, no history written
|
||||
assert cat.load(_pattern().id).version == "1.0.0"
|
||||
assert cat.history(_pattern().id) == []
|
||||
|
||||
|
||||
def test_dedup_on_source_key(tmp_path):
|
||||
cat = Catalog(str(tmp_path))
|
||||
cat.upsert(_pattern())
|
||||
cat.upsert(_pattern()) # same source key -> same id -> one file
|
||||
assert len(cat.list()) == 1
|
||||
|
||||
|
||||
def test_content_change_bumps_version_and_archives(tmp_path):
|
||||
cat = Catalog(str(tmp_path))
|
||||
cat.upsert(_pattern())
|
||||
assert cat.upsert(_pattern(problem="now with more nuance")) == VERSIONED
|
||||
current = cat.load(_pattern().id)
|
||||
assert current.version == "1.0.1"
|
||||
assert current.problem == "now with more nuance"
|
||||
hist = cat.history(_pattern().id)
|
||||
assert len(hist) == 1
|
||||
assert hist[0]["version"] == "1.0.0"
|
||||
assert hist[0]["status"] == "superseded"
|
||||
|
||||
|
||||
def test_status_only_change_updates_without_bump(tmp_path):
|
||||
cat = Catalog(str(tmp_path))
|
||||
cat.upsert(_pattern())
|
||||
p = _pattern()
|
||||
p.status = "approved"
|
||||
p.distribution_ready = True
|
||||
assert cat.upsert(p) == UPDATED
|
||||
current = cat.load(p.id)
|
||||
assert current.status == "approved"
|
||||
assert current.distribution_ready is True
|
||||
assert current.version == "1.0.0" # metadata change, no bump
|
||||
assert cat.history(p.id) == []
|
||||
Reference in New Issue
Block a user