generated from coulomb/repo-seed
python -m session_memory.distribute: reads approved catalog patterns, builds targets from repo->domain map x flavors, renders scoped per-flavor proposals (HITL) + active registry. Live verify against the real catalog: 12 renders across 5 repos, idempotent, provisional skipped. proposals/ gitignored (regenerated); active_patterns.json committed. README documents detect->curate-> distribute. Phase 3 finished; suite 126/126. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
77 lines
3.2 KiB
Python
77 lines
3.2 KiB
Python
"""Distribute entrypoint tests (WP-0007 T05)."""
|
|
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from session_memory.curate.catalog import Catalog # noqa: E402
|
|
from session_memory.curate.schema import Resolution, Scope, SolutionPattern # noqa: E402
|
|
from session_memory.distribute.__main__ import build_targets, main, run_distribute # noqa: E402
|
|
|
|
|
|
def _pattern(pid, repos, flavors, status="approved", ready=True):
|
|
return SolutionPattern(
|
|
id=pid, name=pid, version="1.0.0", polarity="problem", problem="p",
|
|
resolutions=[Resolution(summary="do x")],
|
|
scope=Scope(repos=repos, flavors=flavors), status=status, distribution_ready=ready,
|
|
)
|
|
|
|
|
|
def _config(tmp_path):
|
|
return {
|
|
"repo_domain_map": {"agentic-resources": "helix_forge", "state-hub": "custodian"},
|
|
"curate": {"catalog_dir": str(tmp_path / "catalog")},
|
|
"distribute": {"proposals_dir": str(tmp_path / "proposals"),
|
|
"active_registry": str(tmp_path / "active.json")},
|
|
}
|
|
|
|
|
|
def test_build_targets_crosses_repos_and_flavors():
|
|
cfg = {"repo_domain_map": {"r1": "d1", "r2": "d2"}}
|
|
targets = build_targets(cfg)
|
|
assert len(targets) == 2 * 3 # 2 repos x 3 flavors
|
|
assert build_targets(cfg, repo_filter="r1") and all(t.repo == "r1"
|
|
for t in build_targets(cfg, repo_filter="r1"))
|
|
assert all(t.flavor == "claude" for t in build_targets(cfg, flavor_filter="claude"))
|
|
|
|
|
|
def test_run_distribute_scopes_to_catalog(tmp_path):
|
|
cfg = _config(tmp_path)
|
|
cat = Catalog(cfg["curate"]["catalog_dir"])
|
|
# in-scope for agentic-resources/claude only
|
|
cat.upsert(_pattern("sp-a", ["agentic-resources"], ["claude"]))
|
|
# provisional -> must be skipped
|
|
cat.upsert(_pattern("sp-prov", [], [], status="provisional", ready=False))
|
|
res = run_distribute(cfg)
|
|
rendered = {pid for _, _, pid, _ in res.proposals}
|
|
assert "sp-a" in rendered
|
|
assert "sp-prov" not in rendered
|
|
assert "sp-prov" in res.skipped_not_distributable
|
|
# landed only in the agentic-resources/CLAUDE.md proposal
|
|
p = os.path.join(cfg["distribute"]["proposals_dir"], "agentic-resources", "CLAUDE.md")
|
|
assert os.path.exists(p)
|
|
assert not os.path.exists(
|
|
os.path.join(cfg["distribute"]["proposals_dir"], "state-hub", "CLAUDE.md"))
|
|
|
|
|
|
def test_main_runs_json(tmp_path, capsys):
|
|
cfg = _config(tmp_path)
|
|
cat = Catalog(cfg["curate"]["catalog_dir"])
|
|
cat.upsert(_pattern("sp-a", [], ["claude"])) # unrestricted repos
|
|
# write a config file
|
|
import json as _json
|
|
cfg_path = tmp_path / "c.json"
|
|
# main() loads TOML; emulate by calling run_distribute path via a tiny toml
|
|
toml = tmp_path / "config.toml"
|
|
toml.write_text(
|
|
f'[repo_domain_map]\nagentic-resources = "helix_forge"\n'
|
|
f'[curate]\ncatalog_dir = "{cfg["curate"]["catalog_dir"]}"\n'
|
|
f'[distribute]\nproposals_dir = "{cfg["distribute"]["proposals_dir"]}"\n'
|
|
f'active_registry = "{cfg["distribute"]["active_registry"]}"\n')
|
|
rc = main(["--config", str(toml), "--json"])
|
|
assert rc == 0
|
|
out = capsys.readouterr().out
|
|
assert "sp-a" in out
|
|
_json.loads(out) # valid JSON
|