From 02e0a12252e0805694de341fb1f82de0e4f98075 Mon Sep 17 00:00:00 2001 From: Eureka Date: Fri, 6 Nov 2026 23:21:54 +0100 Subject: [PATCH 1/6] recall.py dispatch: in-force neighbours of the ids a brief cites reach the subagent in its Agent prompt neighbours(text, schemas, excluded, k, left) is the one query helper admit and dispatch share; fan_out and plain_id replace admit's private thread bookkeeping and id test. The fake binding answers view of any id and queries by text with scores. Co-Authored-By: Claude Sonnet 5.5 --- .../context-pack/fake-eureka-state.py | 28 ++- tools/recall.py | 141 +++++++++--- tools/test-tools.sh | 205 ++++++++++++++++++ 3 files changed, 344 insertions(+), 30 deletions(-) diff --git a/tools/fixtures/context-pack/fake-eureka-state.py b/tools/fixtures/context-pack/fake-eureka-state.py index ca7abb6..60ccd63 100644 --- a/tools/fixtures/context-pack/fake-eureka-state.py +++ b/tools/fixtures/context-pack/fake-eureka-state.py @@ -7,7 +7,11 @@ EUREKA_INSTANCE is "t" and HUGINN_ENDPOINT equals FAKE_NEED, else isError Miscon tools/call query (recall.py): FAKE_COUNT gains a "query" line, FAKE_ARGS gains the call's arguments as one JSON line, FAKE_SLEEP seconds pass before the answer (then FAKE_MARK, if set, is written), and the answer is {"items": {"Documents": FAKE_ITEMS}} (a file holding the list); FAKE_MODE unavailable and garbage answer as they do for view; FAKE_MODE=die exits without answering; -FAKE_NOISE writes a non-JSON line, a notification and an id-99 reply before the real one.""" +FAKE_NOISE writes a non-JSON line, a notification and an id-99 reply before the real one. +FAKE_ITEMS holding an object instead of a list answers each query by its semantic text: {text: {"items": [...], "scores": [...]}}, +an unknown text gets nothing; the answer carries "scores" when the entry has them. +FAKE_VIEWS (recall.py dispatch): a file holding {document id: the view answer, null when the mind holds none}; a view call +then gains a "view" line in FAKE_COUNT and its arguments in FAKE_ARGS, and FAKE_MODE unavailable and garbage answer as for query.""" import json, os, sys, time inited = False @@ -44,7 +48,27 @@ for ln in sys.stdin: res = {"content": [{"type": "text", "text": "not json"}]} else: docs = json.load(open(os.environ["FAKE_ITEMS"], encoding="utf-8")) - res = {"content": [{"type": "text", "text": json.dumps({"items": {"Documents": docs}})}]} + body = {"items": {"Documents": docs}} + if isinstance(docs, dict): + hit = docs.get(p["arguments"]["semantic"]["text"], {}) + body = {"items": {"Documents": hit.get("items", [])}, "scores": hit.get("scores", [])} + res = {"content": [{"type": "text", "text": json.dumps(body)}]} + sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": res}) + "\n") + sys.stdout.flush() + continue + if os.environ.get("FAKE_VIEWS") and p.get("name") == "view" and inited and msg["id"] == 2: + with open(os.environ["FAKE_COUNT"], "a") as f: + f.write("view\n") + with open(os.environ["FAKE_ARGS"], "a") as f: + f.write(json.dumps(p.get("arguments")) + "\n") + time.sleep(float(os.environ.get("FAKE_SLEEP", "0"))) + if os.environ.get("FAKE_MODE") == "unavailable": + res = {"isError": True, "content": [{"type": "text", "text": "Unavailable"}]} + elif os.environ.get("FAKE_MODE") == "garbage": + res = {"content": [{"type": "text", "text": "not json"}]} + else: + views = json.load(open(os.environ["FAKE_VIEWS"], encoding="utf-8")) + res = {"content": [{"type": "text", "text": json.dumps(views.get(p["arguments"]["id"]["id"]))}]} sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": res}) + "\n") sys.stdout.flush() continue diff --git a/tools/recall.py b/tools/recall.py index def676b..7af3f2e 100644 --- a/tools/recall.py +++ b/tools/recall.py @@ -3,6 +3,7 @@ Usage: recall.py prompt (a UserPromptSubmit command hook; the hook JSON is on stdin) recall.py admit (a PreToolUse command hook on mcp__eureka-state__admit) + recall.py dispatch (a PreToolUse command hook on Agent|Task) Queries the rulings, questions and follow-ups in force, across every root, ranked by Huginn's embeddings against the prompt, and prints one hook JSON whose @@ -23,12 +24,25 @@ resolutions in the batch. A batch with a neighbour left is denied, the neighbour digest (tool_input plus agent_id) is recorded in the session scratchpad; the identical call sent again passes untouched. It never decides allow or ask. Any failure to check exits 0 with a note naming only the failure kind. Env defaults in this mode: RECALL_TOP_K 3, RECALL_DEADLINE_MS 10000. -Install both hooks as a command that cannot exit 2 (Claude Code runs hook commands through Git Bash on +dispatch appends recall to an Agent or Task brief. It collects the ruling, question and follow_up ids the +prompt cites (::