feat: atomic extract-and-connect + stale PR monitor + response audit #4

Merged
m3taversal merged 70 commits from epimetheus/atomic-connect-and-stale-monitor into main 2026-03-30 11:03:35 +00:00
Showing only changes of commit 425e7a1bac - Show all commits

View file

@ -106,78 +106,100 @@ class KBIndex:
time.time() - start, len(self._entities), len(self._claims), len(self._positions)) time.time() - start, len(self._entities), len(self._claims), len(self._positions))
def _index_entities(self): def _index_entities(self):
"""Scan entities/ for all entity files.""" """Scan entities/ and decisions/ for entity and decision files."""
entities_dir = self.repo_dir / "entities" entity_dirs = [
if not entities_dir.exists(): self.repo_dir / "entities",
return self.repo_dir / "decisions",
for md_file in entities_dir.rglob("*.md"): ]
try: for entities_dir in entity_dirs:
fm, body = _parse_frontmatter(md_file) if not entities_dir.exists():
if not fm or fm.get("type") != "entity": continue
continue for md_file in entities_dir.rglob("*.md"):
self._index_single_entity(md_file)
name = fm.get("name", md_file.stem) def _index_single_entity(self, md_file: Path):
handles = fm.get("handles", []) or [] """Index a single entity or decision file."""
tags = fm.get("tags", []) or [] try:
entity_type = fm.get("entity_type", "unknown") fm, body = _parse_frontmatter(md_file)
domain = fm.get("domain", "unknown") if not fm or fm.get("type") not in ("entity", "decision"):
return
# Build aliases from multiple sources name = fm.get("name", md_file.stem)
aliases = set() handles = fm.get("handles", []) or []
aliases.add(name.lower()) tags = fm.get("tags", []) or []
aliases.add(md_file.stem.lower()) # slugified name entity_type = fm.get("entity_type", "unknown")
for h in handles: domain = fm.get("domain", "unknown")
aliases.add(h.lower().lstrip("@"))
for t in tags:
aliases.add(t.lower())
# Mine body for ticker mentions ($XXXX and standalone ALL-CAPS tokens) # For decision records, also index summary and proposer as searchable text
dollar_tickers = re.findall(r"\$([A-Z]{2,10})", body[:2000]) summary = fm.get("summary", "")
for ticker in dollar_tickers: proposer = fm.get("proposer", "")
aliases.add(ticker.lower())
aliases.add(f"${ticker.lower()}")
# Standalone all-caps tokens (likely tickers: OMFG, META, SOL)
caps_tokens = re.findall(r"\b([A-Z]{2,10})\b", body[:2000])
for token in caps_tokens:
# Filter common English words that happen to be short caps
if token not in ("THE", "AND", "FOR", "NOT", "BUT", "HAS", "ARE", "WAS",
"ITS", "ALL", "CAN", "HAD", "HER", "ONE", "OUR", "OUT",
"NEW", "NOW", "OLD", "SEE", "WAY", "MAY", "SAY", "SHE",
"TWO", "HOW", "BOY", "DID", "GET", "PUT", "KEY", "TVL",
"AMM", "CEO", "SDK", "API", "ICO", "APY", "FAQ", "IPO"):
aliases.add(token.lower())
aliases.add(f"${token.lower()}")
# Also add aliases field if it exists (future schema) # Build aliases from multiple sources
for a in (fm.get("aliases", []) or []): aliases = set()
aliases.add(a.lower()) aliases.add(name.lower())
aliases.add(md_file.stem.lower()) # slugified name
for h in handles:
aliases.add(h.lower().lstrip("@"))
for t in tags:
aliases.add(t.lower())
# Add proposer name as alias for decision records
if proposer:
aliases.add(proposer.lower())
# Extract wiki-linked claim references from body # Mine body for ticker mentions ($XXXX and standalone ALL-CAPS tokens)
related_claims = re.findall(r"\[\[([^\]]+)\]\]", body) dollar_tickers = re.findall(r"\$([A-Z]{2,10})", body[:2000])
for ticker in dollar_tickers:
aliases.add(ticker.lower())
aliases.add(f"${ticker.lower()}")
# Standalone all-caps tokens (likely tickers: OMFG, META, SOL)
caps_tokens = re.findall(r"\b([A-Z]{2,10})\b", body[:2000])
for token in caps_tokens:
# Filter common English words that happen to be short caps
if token not in ("THE", "AND", "FOR", "NOT", "BUT", "HAS", "ARE", "WAS",
"ITS", "ALL", "CAN", "HAD", "HER", "ONE", "OUR", "OUT",
"NEW", "NOW", "OLD", "SEE", "WAY", "MAY", "SAY", "SHE",
"TWO", "HOW", "BOY", "DID", "GET", "PUT", "KEY", "TVL",
"AMM", "CEO", "SDK", "API", "ICO", "APY", "FAQ", "IPO"):
aliases.add(token.lower())
aliases.add(f"${token.lower()}")
# Body excerpt for context # Also add aliases field if it exists (future schema)
for a in (fm.get("aliases", []) or []):
aliases.add(a.lower())
# Extract wiki-linked claim references from body
related_claims = re.findall(r"\[\[([^\]]+)\]\]", body)
# Body excerpt — for decisions, lead with summary for better prompt context
if summary:
overview = f"{summary} "
body_lines = [l for l in body.split("\n") if l.strip() and not l.startswith("#")]
remaining = 500 - len(overview)
if remaining > 0:
overview += " ".join(body_lines[:10])[:remaining]
else:
body_lines = [l for l in body.split("\n") if l.strip() and not l.startswith("#")] body_lines = [l for l in body.split("\n") if l.strip() and not l.startswith("#")]
overview = " ".join(body_lines[:10])[:500] overview = " ".join(body_lines[:10])[:500]
idx = len(self._entities) idx = len(self._entities)
self._entities.append({ self._entities.append({
"name": name, "name": name,
"path": str(md_file), "path": str(md_file),
"type": entity_type, "type": entity_type,
"domain": domain, "domain": domain,
"tags": tags, "tags": tags,
"handles": handles, "handles": handles,
"aliases": list(aliases), "aliases": list(aliases),
"overview": overview, "overview": overview,
"related_claims": related_claims, "related_claims": related_claims,
}) })
# Register all aliases in lookup map # Register all aliases in lookup map
for alias in aliases: for alias in aliases:
self._entity_alias_map.setdefault(alias, []).append(idx) self._entity_alias_map.setdefault(alias, []).append(idx)
except Exception as e: except Exception as e:
logger.warning("Failed to index entity %s: %s", md_file, e) logger.warning("Failed to index entity %s: %s", md_file, e)
def _index_claims(self): def _index_claims(self):
"""Scan domains/, core/, and foundations/ for claim files.""" """Scan domains/, core/, and foundations/ for claim files."""
@ -185,7 +207,6 @@ class KBIndex:
self.repo_dir / "domains", self.repo_dir / "domains",
self.repo_dir / "core", self.repo_dir / "core",
self.repo_dir / "foundations", self.repo_dir / "foundations",
self.repo_dir / "decisions",
] ]
for claim_dir in claim_dirs: for claim_dir in claim_dirs:
if not claim_dir.exists(): if not claim_dir.exists():
@ -447,7 +468,7 @@ def _domain_from_path(path: Path, repo_dir: Path) -> str:
"""Infer domain from file path.""" """Infer domain from file path."""
rel = path.relative_to(repo_dir) rel = path.relative_to(repo_dir)
parts = rel.parts parts = rel.parts
if len(parts) >= 2 and parts[0] in ("domains", "entities"): if len(parts) >= 2 and parts[0] in ("domains", "entities", "decisions"):
return parts[1] return parts[1]
if len(parts) >= 1 and parts[0] == "core": if len(parts) >= 1 and parts[0] == "core":
return "core" return "core"