diff --git a/agents/teamai-recall.md b/agents/teamai-recall.md index 5cf7d6d..0ee5f3b 100644 --- a/agents/teamai-recall.md +++ b/agents/teamai-recall.md @@ -1,6 +1,6 @@ --- name: teamai-recall -description: Search the team knowledge base (skills + learnings + docs + rules) and return a compact, structured summary with doc_ids — instead of dumping full knowledge content into the main conversation. Invoke this BEFORE any task involving code changes, troubleshooting, or design. +description: Search the team knowledge base (skills + learnings + docs + rules + codebase graph) and return a compact, structured summary with doc_ids — instead of dumping full knowledge content into the main conversation. Invoke this BEFORE any task involving code changes, troubleshooting, or design. tools: Bash, Read, Grep, Glob --- @@ -20,16 +20,23 @@ upstream API"). Treat this as your query. ## What you must do — step by step -### Step 1 — Read the codebase manifest (optional but preferred) +### Step 1 — Read codebase context (optional but preferred) -If `~/.teamai/docs/codebase.md` OR `docs/team-codebase/index.md` (in the -current project) exists, read it first. It lists the team's repositories -and their purposes. Extract a one-sentence repo-list summary to prepend to -your final output. If neither file exists, **silently skip** this step — -never error out. +Check for the team's code knowledge graph in this order: -> Note: `teamai recall` already indexes team-codebase documents -> (repos/*.md), so Step 3 will return codebase knowledge matches directly. +1. `teamwiki/router.md` — if exists, read it to understand available repos +2. `teamwiki/index.md` — global navigation with domain links + +If `teamwiki/` exists, the team has a structured knowledge graph. After +Step 3 returns codebase hits, you can **drill into** module summaries: +- `teamwiki/evidence/code//modules/.md` — module-level overview with dependency direction and top components +- `teamwiki/evidence/code//overview.md` — AI-generated architecture context (why/how, not just what) + +Fallback: if no `teamwiki/`, check `~/.teamai/docs/codebase.md` or +`docs/team-codebase/index.md`. If none exists, silently skip. + +> `teamai recall` automatically searches both flat knowledge (learnings/ +> skills/docs/rules) and codebase graph (teamwiki/) with BM25 + graph-boost. ### Step 2 — Extract keywords from the task description @@ -51,12 +58,21 @@ If the command fails, knowledge base is empty, or returns zero hits, emit a single line `No relevant team knowledge found for: ` and stop. -### Step 4 — Read the top hits +### Step 4 — Read the top hits and drill into codebase For each hit returned by `teamai recall`, read the source file directly -(use `Read`) and condense each into **one or two sentences**. Cap your -total summary at ~1500 characters. Drop hits that on closer inspection -are clearly off-topic. +(use `Read`) and condense each into **one or two sentences**. + +**For codebase hits** (path contains `teamwiki/evidence/`): +- If the hit is a raw facts page (component.md, interface.md), prefer + reading the corresponding **module summary** (`modules/.md`) instead — + it's more concise and shows dependencies. +- If you need architectural context (why a module exists, design decisions), + check `overview.md` in the same project directory. +- If the hit mentions a knowledge gap (from `gaps/detected.md`), relay + it to the user: "This area is not fully documented in the knowledge base." + +Cap your total summary at ~2000 characters. Drop hits that are off-topic. ### Step 5 — Emit a structured response @@ -65,24 +81,43 @@ Return your output in **this exact format** to the main conversation: ``` ## Team Knowledge Recall -> Repos: +> Repos: + +### Relevant knowledge 1. **[] ** — Confidence: -2. **[] ** — - - Confidence: +2. ... + +### Codebase context (if any codebase hits) + +**Module: ** () +- Depends on: +- Depended by: +- Core components: `Foo`, `Bar`, `Baz` (top 5 by reference count) +- Architecture: + +### Gaps (if relevant) -... +⚠️ — do not guess answers for this area. ``` -Where: -- `` is one of `skills` / `learnings` / `docs` / `rules` -- `` is the filename without extension (e.g. `api-timeout-fix`) +**Output structure rules:** + +- `` is one of `skills` / `learnings` / `docs` / `rules` / `codebase` +- `` is the filename without extension (e.g. `api-timeout-fix`). + For codebase hits, use the relative path within teamwiki/ (e.g. `evidence/code/hai_api/modules/business`) +- **Codebase context section**: when a codebase hit is returned, include + the module's dependency direction and top 5 components **inline** — the + main conversation should not need a second Read to understand the module. + Extract this from `modules/.md` which you already read in Step 4. +- **Gaps section**: only include if `gaps/detected.md` was relevant to the + query. This tells the main conversation to stop and ask the user rather + than hallucinating. - The trailing HTML comment **must** list every doc_id you returned — later phases (Phase 3 Stop hook) will parse this from the conversation transcript. @@ -93,5 +128,13 @@ Where: - **Do not** call `teamai recall` more than 3 times in one invocation. - **Do not** invoke other subagents. - If `teamai` CLI is not on PATH, return `teamai CLI not available` and stop. -- Output total ≤ ~2000 characters. The whole point of using a subagent is +- Output total ≤ ~2500 characters. The whole point of using a subagent is to keep the main conversation's context lean. +- For codebase hits, **prefer module summaries over raw facts pages** — + they give better signal-to-noise for the main conversation. +- **Include module dependency + core components inline** so the main + conversation can act without a second retrieval round-trip. +- If `teamwiki/gaps/detected.md` exists and is relevant, include the + Gaps section so the main conversation does not hallucinate. +- When zero hits are found but `teamwiki/` exists, check if the query + relates to a known gap before returning "no knowledge found". diff --git a/src/__tests__/auto-recall.test.ts b/src/__tests__/auto-recall.test.ts index 4ce1cd2..8fdecde 100644 --- a/src/__tests__/auto-recall.test.ts +++ b/src/__tests__/auto-recall.test.ts @@ -28,8 +28,17 @@ function writeSearchIndex(homeDir: string): void { fs.mkdirSync(indexDir, { recursive: true }); const index = { + version: 4, builtAt: new Date().toISOString(), elapsedMs: 10, + df: { + 'title:k8s': 1, 'title:pod': 1, 'title:oomkilled': 1, 'title:排查': 1, 'title:修复': 1, + 'tag:k8s': 1, 'tag:oom': 1, 'tag:troubleshooting': 1, + 'oom': 1, 'killed': 1, 'memory': 1, 'limit': 1, 'container': 1, 'restart': 1, + 'title:modulenotfounderror': 1, 'title:常见': 1, 'title:解决方案': 1, + 'tag:python': 1, 'tag:import': 1, 'tag:modulenotfounderror': 1, + 'module': 1, 'not': 1, 'found': 1, 'import': 1, 'pip': 1, 'install': 1, + }, entries: [ { filename: 'k8s-oom-fix-2026-03-20-abc123.md', @@ -43,6 +52,8 @@ function writeSearchIndex(homeDir: string): void { 'oom', 'killed', 'memory', 'limit', 'container', 'restart', ], votes: 3, + type: 'learnings', + domain: 'technical', }, { filename: 'module-not-found-fix-2026-03-22-def456.md', @@ -56,6 +67,8 @@ function writeSearchIndex(homeDir: string): void { 'module', 'not', 'found', 'import', 'pip', 'install', ], votes: 2, + type: 'learnings', + domain: 'technical', }, ], };