Skip to content

Commit 625cf7c

Browse files
Marsu6996codex
andcommitted
Follow up on recall and topology latency
Remove the macOS launchd Background process policy that throttled native cue embedding in the daemon, and reuse the cue embedding already computed by the ANN dispatch path instead of embedding the same cue twice. Also reuse runtime-graph structural results for topology so the synchronous topology surface does not discard cached assignment/rich-club data and fall back toward exact in-parent centrality work. Designed by Marsu — Refined by Codex. Co-Authored-By: Codex <codex@openai.com>
1 parent 62dbd7a commit 625cf7c

13 files changed

Lines changed: 233 additions & 35 deletions

scripts/com.iai-mcp.daemon.plist.template

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@
3333
<key>ThrottleInterval</key>
3434
<integer>5</integer>
3535

36-
<key>ProcessType</key>
37-
<string>Background</string>
38-
3936
<!-- FD floor for a socket-serving daemon. -->
4037
<key>SoftResourceLimits</key>
4138
<dict>

src/iai_mcp/_deploy/launchd/com.iai-mcp.daemon.plist

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@
3434
<key>ThrottleInterval</key>
3535
<integer>5</integer>
3636

37-
<key>ProcessType</key>
38-
<string>Background</string>
39-
4037
<!--
4138
Belt-and-suspenders FD floor for a socket-serving daemon.
4239
The daemon also calls setrlimit(RLIMIT_NOFILE) at boot, but setting

src/iai_mcp/cli/_analytics.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,10 @@ def _render(d: dict) -> None:
300300

301301
try:
302302
store = MemoryStore()
303-
graph, _assignment, _rich_club = build_runtime_graph(store)
304-
snap = compute_topology_snapshot(graph)
303+
graph, assignment, rich_club = build_runtime_graph(store)
304+
snap = compute_topology_snapshot(
305+
graph, assignment=assignment, rich_club=rich_club
306+
)
305307
except HippoLockHeldError:
306308
_render({})
307309
return 0

src/iai_mcp/core/__init__.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ def _mark_recall_stage(name: str) -> None:
369369
knobs_applied=knobs_applied,
370370
arousal_state=_arousal_diag,
371371
tv_maps=(_tv_outgoing_l1, _tv_ts_l1) if _tv_ts_l1 else None,
372+
cue_embedding=_cue_vec,
372373
)
373374
_mark_recall_stage("recall_for_response")
374375
resp.ann_path_used = True
@@ -842,8 +843,19 @@ def _mark_recall_stage(name: str) -> None:
842843
}
843844
try:
844845
graph_bundle = retrieve.build_runtime_graph(store)
845-
graph = graph_bundle[0] if isinstance(graph_bundle, tuple) else graph_bundle
846-
return sigma_mod.compute_topology_snapshot(graph)
846+
assignment = None
847+
rich_club = None
848+
if isinstance(graph_bundle, tuple):
849+
graph = graph_bundle[0]
850+
if len(graph_bundle) > 1:
851+
assignment = graph_bundle[1]
852+
if len(graph_bundle) > 2:
853+
rich_club = graph_bundle[2]
854+
else:
855+
graph = graph_bundle
856+
return sigma_mod.compute_topology_snapshot(
857+
graph, assignment=assignment, rich_club=rich_club
858+
)
847859
except Exception as exc:
848860
write_event(
849861
store,

src/iai_mcp/pipeline.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ def _recall_core(
450450
spread_hops: int = 2,
451451
cue_intent: str | None = None,
452452
contradicts_outgoing: dict[str, list[str]] | None = None,
453+
cue_embedding: list[float] | None = None,
453454
) -> _RecallCoreResult:
454455
profile_state = profile_state or {}
455456

@@ -517,20 +518,23 @@ def _recall_core(
517518
budget_used=budget_used_l0,
518519
)
519520

520-
try:
521-
cue_emb = embedder.embed(cue)
522-
except Exception as exc:
523-
write_event(
524-
store,
525-
TELEMETRY_EMBED_NATIVE_FAILURE,
526-
{
527-
"op_type": "recall_cue",
528-
"backend": "rust",
529-
"error_type": type(exc).__name__,
530-
"error": str(exc),
531-
},
532-
)
533-
raise NativeError(f"recall cue encode failed: {exc}") from exc
521+
if cue_embedding is None:
522+
try:
523+
cue_emb = embedder.embed(cue)
524+
except Exception as exc:
525+
write_event(
526+
store,
527+
TELEMETRY_EMBED_NATIVE_FAILURE,
528+
{
529+
"op_type": "recall_cue",
530+
"backend": "rust",
531+
"error_type": type(exc).__name__,
532+
"error": str(exc),
533+
},
534+
)
535+
raise NativeError(f"recall cue encode failed: {exc}") from exc
536+
else:
537+
cue_emb = cue_embedding
534538

535539
records_cache: dict[UUID, "object"] = {}
536540
try:
@@ -1155,6 +1159,7 @@ def recall_for_response(
11551159
knobs_applied: dict | None = None,
11561160
arousal_state: dict | None = None,
11571161
tv_maps: "tuple[dict, dict] | None" = None,
1162+
cue_embedding: list[float] | None = None,
11581163
) -> RecallResponse:
11591164
import time as _time
11601165
global _last_recall_latency_ms
@@ -1193,6 +1198,7 @@ def recall_for_response(
11931198
spread_hops=_s_hops,
11941199
cue_intent=_cue_intent,
11951200
contradicts_outgoing=_tv_outgoing,
1201+
cue_embedding=cue_embedding,
11961202
)
11971203

11981204
derive_temporal_validity(

src/iai_mcp/sigma.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,13 @@ def classify_regime(N: int, sigma: Optional[float]) -> str:
250250
return "healthy"
251251

252252

253-
def compute_topology_snapshot(graph, *, assignment=None) -> dict:
253+
def compute_topology_snapshot(graph, *, assignment=None, rich_club=None) -> dict:
254254
"""Topology metrics for `graph`.
255255
256-
Computes community detection in-process by default. The request-synchronous
257-
callers (the `topology` health surface, used by `iai status` and the
258-
topology tool, plus operator analytics) rely on this near-instant path and
259-
pass no `assignment`. Background callers that have already computed the
260-
community assignment off the interactive path may pass it in to skip the
261-
in-process recompute.
256+
Computes community detection in-process by default only for callers that
257+
have not already built the runtime graph. Request-synchronous callers should
258+
pass the `assignment` and `rich_club` returned by `build_runtime_graph()` so
259+
this health surface does not re-run the expensive structural passes.
262260
"""
263261
from iai_mcp.graph import MemoryGraph
264262

@@ -324,7 +322,16 @@ def compute_topology_snapshot(graph, *, assignment=None) -> dict:
324322
except (RuntimeError, ValueError, TypeError):
325323
community_count = 0
326324
try:
327-
rc = rich_club_nodes(graph, percent=0.10)
325+
if rich_club is None:
326+
centrality = {
327+
node_id: float(graph.get_centrality(node_id))
328+
for node_id in graph.iter_nodes()
329+
}
330+
rc = rich_club_nodes(
331+
graph, percent=0.10, centrality=centrality
332+
)
333+
else:
334+
rc = rich_club
328335
rich_club_ratio = (len(rc) / N) if N > 0 else 0.0
329336
except (RuntimeError, ValueError, TypeError):
330337
rich_club_ratio = 0.0

tests/test_daemon.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ def test_launchd_plist_valid_xml_with_required_keys():
201201
assert "SuccessfulExit" not in keepalive
202202

203203
assert data["ThrottleInterval"] == 5
204+
assert "ProcessType" not in data
204205
assert "StandardOutPath" in data
205206
assert "StandardErrorPath" in data
206207
assert "WorkingDirectory" in data

tests/test_native_fail_loud.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,52 @@ def test_topology_empty_graph_returns_stub_without_raising(tmp_path):
8888
f"legitimate path; got {rows}"
8989
)
9090

91+
def test_topology_passes_cached_structural_results(tmp_path, monkeypatch):
92+
from iai_mcp import core, retrieve, sigma as sigma_mod
93+
94+
store = _make_store(tmp_path)
95+
_seed_one_record(store)
96+
97+
graph = object()
98+
assignment = object()
99+
rich_club = [object()]
100+
captured: dict = {}
101+
102+
monkeypatch.setattr(
103+
retrieve,
104+
"build_runtime_graph",
105+
lambda _store: (graph, assignment, rich_club),
106+
)
107+
108+
def _fake_snapshot(graph_arg, *, assignment=None, rich_club=None):
109+
captured.update(
110+
{
111+
"graph": graph_arg,
112+
"assignment": assignment,
113+
"rich_club": rich_club,
114+
}
115+
)
116+
return {
117+
"N": 1,
118+
"C": 0.0,
119+
"L": 0.0,
120+
"sigma": None,
121+
"community_count": 1,
122+
"rich_club_ratio": 1.0,
123+
"regime": "insufficient_data",
124+
}
125+
126+
monkeypatch.setattr(sigma_mod, "compute_topology_snapshot", _fake_snapshot)
127+
128+
result = core.dispatch(store, "topology", {})
129+
130+
assert result["N"] == 1
131+
assert captured == {
132+
"graph": graph,
133+
"assignment": assignment,
134+
"rich_club": rich_club,
135+
}
136+
91137
def test_recall_cue_encode_failure_emits_store_event_and_raises(
92138
tmp_path, monkeypatch
93139
):

tests/test_plist_template_lint.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,17 @@ def test_template_has_required_keys() -> None:
4343
"<true/>",
4444
"<key>KeepAlive</key>",
4545
"<key>Crashed</key>",
46-
"<key>ProcessType</key>",
4746
"<key>SoftResourceLimits</key>",
4847
"IAI_MCP_LAUNCHD_MANAGED",
4948
]
5049
missing = [m for m in required_markers if m not in text]
5150
assert not missing, f"template missing required markers: {missing}"
5251

52+
def test_template_does_not_run_under_background_policy() -> None:
53+
text = TEMPLATE.read_text()
54+
assert "<key>ProcessType</key>" not in text
55+
assert "<string>Background</string>" not in text
56+
5357
def test_template_has_RunAtLoad_true() -> None:
5458
text = TEMPLATE.read_text()
5559
match = re.search(r"<key>RunAtLoad</key>\s*<true/>", text)

tests/test_recall_cue_router.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,39 @@ def fake_recall_for_response(**kwargs):
424424
assert response["cue_mode"] == "verbatim"
425425

426426

427+
def test_dispatch_passes_cue_embedding_to_recall_for_response(tmp_path, monkeypatch):
428+
from iai_mcp import core
429+
from iai_mcp import embed as _embed_mod
430+
from iai_mcp import pipeline as _pipeline_mod
431+
from iai_mcp.types import RecallResponse
432+
433+
store, embedder, _cue, _rec = _seed_populated_store(tmp_path)
434+
monkeypatch.setattr(_embed_mod, "embedder_for_store", lambda _store: embedder)
435+
436+
captured: dict = {}
437+
438+
def fake_recall_for_response(**kwargs):
439+
captured.update(kwargs)
440+
return RecallResponse(
441+
hits=[], anti_hits=[], activation_trace=[], budget_used=0,
442+
cue_mode=kwargs.get("mode", "concept"),
443+
patterns_observed=[],
444+
)
445+
446+
monkeypatch.setattr(_pipeline_mod, "recall_for_response", fake_recall_for_response)
447+
448+
cue = "verbatim recall this exact quote"
449+
expected_vec = embedder.embed(cue)
450+
embedder.set_fixed(cue, expected_vec)
451+
452+
core.dispatch(
453+
store, "memory_recall",
454+
{"cue": cue, "session_id": "cue_embedding_capture"},
455+
)
456+
457+
assert captured["cue_embedding"] == expected_vec
458+
459+
427460
def test_dispatch_passes_mode_kwarg_to_retrieve_recall(tmp_path, monkeypatch):
428461
from iai_mcp import core
429462
from iai_mcp import retrieve as _retrieve_mod

0 commit comments

Comments
 (0)