recall · diff

git:20261011.21178a6 to git:20261011.09c62d2

86 added, 47 removed. Audit A to A.

---
name: recall
description: >
- Search Wenlan's local memory from Codex by query. Targeted lookup, not
- session orientation. Invoked as /recall <query>.
+ Search Wenlan's local memory by query. Targeted lookup, not orientation.
+ Invoked as `/recall <query>`. Use when the user asks "do you
+ remember", "what do you know about", "look up".
argument-hint: "<query>"
allowed-tools: ["Bash", "mcp__wenlan__recall", "mcp__wenlan__get_memory_revisions"]
user-invocable: true
---
# /recall
- Search Wenlan memory by natural-language query. Use `/brief` for broad session
- orientation and `/recall` for a specific fact, decision, lesson, or preference.
+ Search Wenlan's memory by natural-language query. Returns matching memories
+ ranked by hybrid vector + FTS search, then re-ordered by the agent if it
+ helps.
## Resolve the active space
- Accept one optional inline token of the form `space:<name>` anywhere in the
- argument string. The Codex resolver strips it and returns the rest as the
- query. It prints the resolved Space line itself:
+ The `/recall` skill accepts one optional inline token of the form
+ `space:<name>` anywhere in the argument string. The bundled resolver strips it
+ and returns the rest as the query. It prints the resolved Space line itself:
```bash
raw_args="<the full argument string passed to /recall>"
# The resolver ships inside the installed plugin; the relative path only
# exists in a wenlan checkout.
resolver="$(find "$HOME/.codex/plugins/cache" -path '*/wenlan/*/bin/resolve-space.sh' 2>/dev/null | head -1)"
resolved="$("${resolver:-plugin-codex/bin/resolve-space.sh}" --cwd "$PWD" --args "$raw_args")"
space="$(printf '%s\n' "$resolved" | cut -f1)"
source_layer="$(printf '%s\n' "$resolved" | cut -f2)"
query="$(printf '%s\n' "$resolved" | cut -f3-)"
```
- If `query` is empty, ask the user what they want to search for.
+ If `query` is empty, ask the user what they want to search for. Pass
+ `space="$space"` to the `recall` MCP tool only when `space` is non-empty;
+ otherwise omit the space filter.
- Pass `space="<resolved>"` to `mcp__wenlan__recall` only when `space` is
- non-empty. Do not substitute `personal` for an unscoped result.
+ ## Two phases
- ## Expand once, then call recall
+ When a local model or API key is configured, the daemon can rerank and
+ expand server-side. In local memory mode it cannot. The skill always does
+ **agent-side expansion and rerank** itself — cheap, makes results good in
+ both modes.
- Rewrite the query only enough to improve retrieval:
+ ### Phase 1 — expand the query (agent-side)
- - Replace pronouns with the referent from the current thread.
- - Expand an abbreviation when the embedder may miss it.
- - Add one obvious synonym when the user's wording is too narrow.
+ Before calling `recall`, rewrite the user's query into a more
+ search-friendly form:
- Do not issue multiple recall calls. Use one call:
+ - Replace pronouns with the referent ("it" → the actual thing).
+ - Expand abbreviations the embedder is unlikely to know.
+ - Add the obvious synonym when the original term is too narrow (e.g.
+ "auth" → "auth OR authentication").
- ```text
- mcp__wenlan__recall(
- query="<expanded query>",
- space="<resolved if non-empty>",
- memory_type="<only if the query names a type>"
- )
+ Don't over-expand. If the query is already specific, leave it alone.
+ One recall call per `/recall` invocation — duplicate calls double
+ embedding load and the merge step is rarely worth it. The daemon's
+ own `search_memory_expanded` exists for the multi-query case; if it
+ matters, use that endpoint instead of issuing parallel calls here.
+
+ ### Phase 2 — call the MCP tool
+
```
+ recall(query="<expanded query>", space=<resolved if non-empty>, memory_type=<inferred>)
+ ```
- Infer `memory_type` only when the user names a type, such as "decision on X",
- "lesson about Y", or "preference for Z". Otherwise omit it.
+ Inferences (do not ask the user):
- ## Rerank and render
+ - `space`: current working directory (e.g. `~/Repos/wenlan/...` → `"wenlan"`),
+ the topic being discussed, or whatever space was mentioned in recent turns.
+ Pass only when scope is known; omit when uncertain or unscoped.
+ - `memory_type`: only when the query itself names a type ("decision on X",
+ "lesson about Y", "preference for Z"). Otherwise omit and let hybrid
+ search rank.
+ - `limit`: default 10. Use 3-5 for quick lookups, 10-20 for exploration.
- Rerank the returned memories against the user's original query:
+ ### Phase 3 — rerank (agent-side)
- - Promote direct answers.
- - Demote keyword overlaps that do not answer the question.
- - Show the top 3-5 hits unless the user asked for a deeper audit.
+ The daemon returns hits ranked by hybrid search. That ranking is good but
+ not perfect — it doesn't know the user's exact intent.
- Render revision context only when it matters:
+ Re-read the returned memories against the *original* query. Promote the
+ ones that directly answer the question; demote ones that just share
+ keywords.
- ```text
- <id> v<N> (merged <K> memories)
- <id> v<N>, pending revision against <id>
- <id> v<N> - <last_delta_summary>
- <id> v<N>
- ```
+ Show the user the top 3-5 reranked hits. Surface the rest only if asked.
- Skip that tag line when the memory is a fresh v1 with no merge or pending
- revision fields.
+ If the user explicitly asks how one returned memory changed, for its full
+ history, or whether a correction was recorded, call
+ `get_memory_revisions(memory_id="<source_id>")`. Do not fetch revision chains
+ for ordinary recall results.
- Only when the user explicitly asks for one memory's history or evolution, or
- whether a correction was recorded, call:
+ ### Phase 4 — render revision context (per result)
- ```text
- mcp__wenlan__get_memory_revisions(memory_id="<source_id>")
+ Each memory may carry revision fields: `version`, `pending_revision`,
+ `merged_from`, `last_delta_summary`. Most memories are fresh (v1, none
+ set) — render nothing extra for those. Only add a tag line when
+ something meaningful is present.
+
+ **Condition:** emit the tag line when any of these holds:
+ - `version > 1`
+ - `merged_from` is non-empty
+ - `pending_revision == true`
+
+ **Format** — one compact line above the memory body:
+
```
+ <id> v<N> (merged <K> memories) ← merged_from has K entries
+ <id> v<N>, pending revision against <id> ← pending_revision true
+ <id> v<N> — <last_delta_summary> ← version > 1, delta populated
+ <id> v<N> ← version > 1, no delta
+ ```
- Do not fetch revision chains for ordinary recall results.
+ Rules:
+ - Merged takes precedence over pending_revision in the label.
+ - Omit `— <delta>` when `last_delta_summary` is empty or null.
+ - Skip the tag line entirely when version == 1 (or null) and no other
+ flag is set. Preserves current output for fresh memories.
## When to use
- "What did I say about X?"
- "Do you remember the decision on Y?"
- - "Look up my preference for Z."
+ - Need a specific fact before continuing.
- ## When not to use
+ ## When NOT to use
- - Session start context: use `/brief`.
- - Storing a new memory: use `/capture`.
+ - Broad session orientation → use `/brief` instead.
+ - Storing a new memory → use `/capture`.
+
+ ## Hint: write specific queries
+
+ "Alice database preference" finds more than "database stuff". The semantic
+ matcher rewards specificity. If too many results return, add filters rather
+ than making the query longer.