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:
42
session_memory/distribute/claude.py
Normal file
42
session_memory/distribute/claude.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""Claude distributor (PRD §6.4 FR-X1; T02).
|
||||
|
||||
Renders an approved Solution Pattern into a ``CLAUDE.md`` snippet block. Most logic
|
||||
is inherited from :class:`BaseDistributor`; the Claude-specific touch is an
|
||||
optional **skill** rendering mode (``rendering_hints["claude"]["as"] == "skill"``)
|
||||
that emits a skill-style stub instead of a plain instruction snippet — Claude's
|
||||
native distribution targets are CLAUDE.md snippets, skills, or hooks.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ..curate.schema import SolutionPattern
|
||||
from .base import BaseDistributor, hint, render_markdown_body
|
||||
|
||||
|
||||
class ClaudeDistributor(BaseDistributor):
|
||||
flavor = "claude"
|
||||
target_path = "CLAUDE.md"
|
||||
|
||||
def body(self, pattern: SolutionPattern) -> str:
|
||||
override = hint(pattern, self.flavor, "body")
|
||||
if override:
|
||||
return override
|
||||
if hint(pattern, self.flavor, "as") == "skill":
|
||||
return self._skill_stub(pattern)
|
||||
return render_markdown_body(pattern)
|
||||
|
||||
@staticmethod
|
||||
def _skill_stub(pattern: SolutionPattern) -> str:
|
||||
trigger = "avoid" if pattern.polarity == "problem" else "apply"
|
||||
lines = [
|
||||
f"## Skill: {pattern.name}",
|
||||
"",
|
||||
f"**When:** situations where you would {trigger} — {pattern.problem.strip()}",
|
||||
"",
|
||||
"**Steps:**",
|
||||
]
|
||||
for r in pattern.resolutions:
|
||||
lines.append(f"- {r.summary}" + (f" — {r.detail}" if r.detail else ""))
|
||||
for step in r.steps:
|
||||
lines.append(f" - {step}")
|
||||
return "\n".join(lines).strip()
|
||||
15
session_memory/distribute/codex.py
Normal file
15
session_memory/distribute/codex.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""Codex distributor (PRD §6.4 FR-X1; T03).
|
||||
|
||||
Renders an approved Solution Pattern into an ``AGENTS.md`` snippet — Codex's native
|
||||
repo-convention surface. Identical agnostic body to the other flavors (FR-A3: one
|
||||
pattern, expressible everywhere); only the target file differs.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .base import BaseDistributor
|
||||
|
||||
|
||||
class CodexDistributor(BaseDistributor):
|
||||
flavor = "codex"
|
||||
target_path = "AGENTS.md"
|
||||
15
session_memory/distribute/grok.py
Normal file
15
session_memory/distribute/grok.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""Grok distributor (PRD §6.4 FR-X1; T03).
|
||||
|
||||
Renders an approved Solution Pattern into Grok's native instruction format. Defaults
|
||||
to a ``.grok/instructions.md`` snippet; the same agnostic body as the other flavors
|
||||
(FR-A3), overridable via ``rendering_hints["grok"]``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .base import BaseDistributor
|
||||
|
||||
|
||||
class GrokDistributor(BaseDistributor):
|
||||
flavor = "grok"
|
||||
target_path = ".grok/instructions.md"
|
||||
26
session_memory/distribute/registry.py
Normal file
26
session_memory/distribute/registry.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""Distributor registry (T03) — flavor -> distributor, the one place that knows
|
||||
about all flavor edges. Adding a flavor = one entry here + one adapter module.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from .base import BaseDistributor
|
||||
from .claude import ClaudeDistributor
|
||||
from .codex import CodexDistributor
|
||||
from .grok import GrokDistributor
|
||||
|
||||
_REGISTRY: dict[str, BaseDistributor] = {
|
||||
"claude": ClaudeDistributor(),
|
||||
"codex": CodexDistributor(),
|
||||
"grok": GrokDistributor(),
|
||||
}
|
||||
|
||||
|
||||
def get_distributor(flavor: str) -> Optional[BaseDistributor]:
|
||||
return _REGISTRY.get(flavor)
|
||||
|
||||
|
||||
def all_flavors() -> list[str]:
|
||||
return list(_REGISTRY)
|
||||
Reference in New Issue
Block a user