SignalMesh / core /relationship_graph.py
acecalisto3's picture
feat: relationship_graph.py — memory architecture update
419f579 verified
Raw
History Blame Contribute Delete
3.85 kB
"""
core/relationship_graph.py — Role-Scoped Context Delivery
Instead of broadcasting everything to everyone, the relationship graph
pre-filters what each role receives. Prevents token explosion, accidental
consensus loops, and scope creep.
Default roles ship pre-configured. Add/update at runtime via the API.
"""
from __future__ import annotations
from typing import Dict, List, Optional, Set
# ── Default role → frequency patterns ────────────────────────────────────────
# Values are prefix/substring patterns matched against frequency names.
# Historian receives everything — it's the only role that does.
_DEFAULT_ROLES: Dict[str, List[str]] = {
"CodeAgent": ["architecture", "api", "backend", "test_fail", "commit",
"router", "service", "database", "schema"],
"FrontendAgent": ["ui", "frontend", "component", "design", "css",
"ux", "layout", "visual"],
"QAAgent": ["test", "commit", "fail", "coverage", "regression",
"bug", "error", "assert"],
"ResearchAgent": ["requirement", "spec", "open_question", "rfc",
"external", "arxiv", "paper", "research"],
"SecurityAgent": ["security", "auth", "secret", "key", "credential",
"vuln", "cve", "owasp"],
"InfraAgent": ["infra", "deploy", "docker", "k8s", "ci", "cd",
"pipeline", "release"],
"DataAgent": ["data", "schema", "migration", "etl", "pipeline",
"warehouse", "feed", "rss"],
"Historian": ["*"], # receives everything
}
class RelationshipGraph:
"""
Role → frequency filter. tune_in(role=) uses this to scope context delivery.
Dumb and fast — no LLM, no scoring, just pattern matching.
"""
def __init__(self):
self._roles: Dict[str, List[str]] = dict(_DEFAULT_ROLES)
# ── Filtering ─────────────────────────────────────────────────────────────
def allowed_frequencies(self, role: str, available: List[str]) -> List[str]:
"""Return which frequencies from `available` this role may receive."""
patterns = self._roles.get(role, [])
if not patterns:
return []
if "*" in patterns:
return available
result: List[str] = []
for freq in available:
fl = freq.lower()
if any(p.lower() in fl for p in patterns):
result.append(freq)
return result
def filter_signals(self, role: str, signals: List[dict]) -> List[dict]:
"""Filter a list of already-tuned signals to those allowed for role."""
if not role:
return signals
patterns = self._roles.get(role, [])
if not patterns:
return []
if "*" in patterns:
return signals
return [
s for s in signals
if any(p.lower() in s.get("name", "").lower() for p in patterns)
]
# ── Management ────────────────────────────────────────────────────────────
def set_role(self, role: str, patterns: List[str]):
self._roles[role] = patterns
def get_role(self, role: str) -> Optional[List[str]]:
return self._roles.get(role)
def all_roles(self) -> Dict[str, List[str]]:
return dict(self._roles)
def remove_role(self, role: str) -> bool:
if role in self._roles:
del self._roles[role]
return True
return False
relationship_graph = RelationshipGraph()