Add scoped Agent-mode pipeline as experimental Classic fork.

Wire specialist waves, Brain consolidation, and Classic-compatible reports so Agent mode can run end-to-end via OpenRouter without changing the default Classic path.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-18 14:31:13 +00:00
co-authored by Cursor
parent e30522af9a
commit 82a48d99cf
24 changed files with 1522 additions and 22 deletions
+193
View File
@@ -0,0 +1,193 @@
"""Bounded semantic linkers that build coordination clusters."""
import json
import re
from collections import defaultdict
from typing import Dict, Iterable, List, Tuple
from backend import config
from backend.agents.base import AgentResult, AgentScope, AgentUsage, failure
from backend.llm import call_json
from backend.pipeline.clusterer import cluster_by_location
from backend.pipeline.llm_clusterer import _location
from backend.prompts import CLUSTER_SYSTEM_PROMPT, CLUSTER_USER_INSTRUCTION
def _family(assertion: Dict) -> str:
location = assertion.get("location_key") or {}
if location.get("room"):
return "room"
if location.get("grid"):
return "grid"
if location.get("detail_reference"):
return "detail"
tag = str(location.get("tag") or "")
match = re.match(r"[A-Za-z]+", tag)
return (
(match.group(0).lower() if match else "")
or (assertion.get("object_type") or "").lower()
or "general"
)
def build_link_scopes(sheets: List[Dict]) -> List[AgentScope]:
"""Partition facts by level and object/tag family, then enforce a hard cap."""
buckets: Dict[Tuple[str, str], List[Dict]] = defaultdict(list)
for sheet in sheets:
for assertion in sheet.get("assertions", []):
enriched = {
**assertion,
"discipline": sheet.get("discipline") or "Unknown",
"sheet_number": sheet.get("sheet_number"),
"page_number": sheet.get("page_number"),
}
level = str((assertion.get("location_key") or {}).get("level")
or sheet.get("level") or "unknown").lower()
buckets[(level, _family(assertion))].append(enriched)
scopes: List[AgentScope] = []
cap = max(2, config.AGENT_LINK_MAX_ASSERTIONS)
for (level, family), assertions in sorted(buckets.items()):
for offset in range(0, len(assertions), cap):
chunk = assertions[offset:offset + cap]
if len(chunk) < 2:
continue
scopes.append(AgentScope(
scope_id=f"{level}:{family}:{offset // cap + 1}",
payload={"assertions": chunk, "level": level, "family": family},
))
return scopes
def _payload(assertions: Iterable[Dict]) -> List[Dict]:
return [{
"assertion_id": item.get("id"),
"discipline": item.get("discipline"),
"sheet_number": item.get("sheet_number"),
"attribute": item.get("attribute"),
"value": item.get("value"),
"location_key": item.get("location_key"),
"source_text": item.get("source_text"),
} for item in assertions]
def _fallback(assertions: List[Dict]) -> List[Dict]:
"""Use the deterministic linker within this scope when semantic linking fails."""
by_sheet: Dict[Tuple, Dict] = {}
for item in assertions:
key = (item.get("sheet_number"), item.get("page_number"))
sheet = by_sheet.setdefault(key, {
"sheet_number": item.get("sheet_number"),
"page_number": item.get("page_number"),
"discipline": item.get("discipline"),
"assertions": [],
})
sheet["assertions"].append(item)
return cluster_by_location(list(by_sheet.values()))
class LinkerAgent:
name = "linker"
def __init__(self, usage: AgentUsage) -> None:
self.usage = usage
def run(self, scope: AgentScope) -> AgentResult:
try:
assertions = scope.payload.get("assertions") or []
by_id = {item.get("id"): item for item in assertions if item.get("id")}
instruction = CLUSTER_USER_INSTRUCTION.replace(
"{normalized_assertions}",
json.dumps(_payload(assertions), ensure_ascii=True),
)
parsed = call_json(
system_prompt=CLUSTER_SYSTEM_PROMPT,
user_text=instruction,
max_tokens=config.CLUSTER_MAX_TOKENS,
model=config.AGENT_LINKER_MODEL,
usage_tracker=self.usage,
usage_stage="agent.link",
)
raw = parsed if isinstance(parsed, list) else (
parsed.get("clusters") if isinstance(parsed, dict) else []
)
clusters: List[Dict] = []
for candidate in raw or []:
if not isinstance(candidate, dict):
continue
members = [
by_id[item_id]
for item_id in candidate.get("assertion_ids") or []
if item_id in by_id
]
if len(members) < 2:
continue
allowed_sheets = []
for member in members:
sheet = member.get("sheet_number")
if sheet not in allowed_sheets:
allowed_sheets.append(sheet)
allowed_sheets = allowed_sheets[:config.AGENT_CONFLICT_MAX_IMAGES]
members = [
member for member in members
if member.get("sheet_number") in allowed_sheets
][:config.AGENT_CLUSTER_MAX_ASSERTIONS]
primary = candidate.get("primary_location_key") or {}
clusters.append({
"key": f"{scope.scope_id}:{candidate.get('cluster_id') or len(clusters) + 1}",
"location": _location(primary),
"disciplines": sorted({
member.get("discipline") or "Unknown" for member in members
}),
"page_numbers": sorted({
member["page_number"] for member in members
if member.get("page_number")
}),
"sheets": sorted({
member["sheet_number"] for member in members
if member.get("sheet_number")
}),
"assertions": members,
"kind": "agent_semantic",
"scope_id": scope.scope_id,
})
if not clusters:
clusters = _fallback(assertions)
for cluster in clusters:
cluster["scope_id"] = scope.scope_id
cluster["kind"] = "agent_deterministic"
return AgentResult(scope_id=scope.scope_id, artifacts=clusters)
except Exception as exc:
return failure(scope, exc)
def build_object_graph(clusters: List[Dict]) -> Dict:
"""Build a deterministic graph view from linker output."""
nodes = []
edges = []
seen = set()
for cluster in clusters:
cluster_id = cluster.get("key")
nodes.append({
"id": cluster_id,
"type": "cluster",
"location": cluster.get("location"),
"sheets": cluster.get("sheets") or [],
})
for assertion in cluster.get("assertions") or []:
assertion_id = assertion.get("id")
if not assertion_id:
continue
if assertion_id not in seen:
seen.add(assertion_id)
nodes.append({
"id": assertion_id,
"type": assertion.get("object_type") or "assertion",
"sheet": assertion.get("sheet_number"),
})
edges.append({
"source": assertion_id,
"target": cluster_id,
"relationship": "member_of",
})
return {"nodes": nodes, "edges": edges}