generated from coulomb/repo-seed
session-memory: Claude + Codex + Grok distributors + registry (WP-0007 T02/T03)
Thin per-flavor distributors over the shared base: Claude (CLAUDE.md, optional skill-stub mode), Codex (AGENTS.md), Grok (.grok/instructions.md). registry maps flavor->distributor — adding a flavor is one entry + one module. Same agnostic body renders to distinct per-flavor targets (FR-A3). 7 new tests; suite 117/117. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
40
tests/test_distribute_claude.py
Normal file
40
tests/test_distribute_claude.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""Claude distributor tests (WP-0007 T02)."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from session_memory.curate.schema import Resolution, SolutionPattern # noqa: E402
|
||||
from session_memory.distribute.claude import ClaudeDistributor # noqa: E402
|
||||
|
||||
|
||||
def _pattern(hints=None):
|
||||
return SolutionPattern(
|
||||
id="sp-read-before-edit", name="Read before edit", version="1.0.0",
|
||||
polarity="problem", problem="Agents edit files they have not read.",
|
||||
resolutions=[Resolution(summary="Read the file first", steps=["Read", "Edit"])],
|
||||
rendering_hints=hints or {"claude": {}},
|
||||
)
|
||||
|
||||
|
||||
def test_default_targets_claude_md():
|
||||
art = ClaudeDistributor().render(_pattern())
|
||||
assert art.flavor == "claude"
|
||||
assert art.target_path == "CLAUDE.md"
|
||||
assert "BEGIN helix-forge pattern:sp-read-before-edit" in art.content
|
||||
assert "### Read before edit" in art.content
|
||||
|
||||
|
||||
def test_skill_mode_emits_skill_stub():
|
||||
art = ClaudeDistributor().render(_pattern({"claude": {"as": "skill"}}))
|
||||
assert "## Skill: Read before edit" in art.content
|
||||
assert "**When:**" in art.content
|
||||
assert " - Read" in art.content
|
||||
|
||||
|
||||
def test_idempotent_marker_present_for_reupsert():
|
||||
art = ClaudeDistributor().render(_pattern())
|
||||
# same id in both renders -> caller can upsert in place
|
||||
art2 = ClaudeDistributor().render(_pattern())
|
||||
assert art.pattern_id == art2.pattern_id == "sp-read-before-edit"
|
||||
49
tests/test_distribute_codex_grok.py
Normal file
49
tests/test_distribute_codex_grok.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""Codex + Grok distributor + registry tests (WP-0007 T03)."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from session_memory.curate.schema import Resolution, SolutionPattern # noqa: E402
|
||||
from session_memory.distribute.codex import CodexDistributor # noqa: E402
|
||||
from session_memory.distribute.grok import GrokDistributor # noqa: E402
|
||||
from session_memory.distribute.registry import all_flavors, get_distributor # noqa: E402
|
||||
|
||||
|
||||
def _pattern():
|
||||
return SolutionPattern(
|
||||
id="sp-x", name="Read before edit", version="1.0.0", polarity="problem",
|
||||
problem="Agents edit files they have not read.",
|
||||
resolutions=[Resolution(summary="Read the file first")],
|
||||
)
|
||||
|
||||
|
||||
def test_codex_targets_agents_md():
|
||||
art = CodexDistributor().render(_pattern())
|
||||
assert art.flavor == "codex" and art.target_path == "AGENTS.md"
|
||||
assert "Read before edit" in art.content
|
||||
|
||||
|
||||
def test_grok_targets_native_instructions():
|
||||
art = GrokDistributor().render(_pattern())
|
||||
assert art.flavor == "grok" and art.target_path == ".grok/instructions.md"
|
||||
|
||||
|
||||
def test_same_pattern_expressible_for_all_flavors():
|
||||
# FR-A3: one pattern, rendered for every flavor (same body, different targets)
|
||||
p = _pattern()
|
||||
bodies = {}
|
||||
for f in all_flavors():
|
||||
art = get_distributor(f).render(p)
|
||||
# strip markers -> compare agnostic body
|
||||
inner = art.content.split("\n", 1)[1].rsplit("\n", 1)[0]
|
||||
bodies[f] = inner
|
||||
targets = {get_distributor(f).render(p).target_path for f in all_flavors()}
|
||||
assert len(targets) == 3 # distinct per-flavor targets
|
||||
assert len(set(bodies.values())) == 1 # identical agnostic body
|
||||
|
||||
|
||||
def test_registry_unknown_flavor():
|
||||
assert get_distributor("gpt") is None
|
||||
assert set(all_flavors()) == {"claude", "codex", "grok"}
|
||||
Reference in New Issue
Block a user