teamai-cli 0.20.0-beta.6 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -175,8 +175,17 @@ Author: member-a | Score: 18.5 | Tags: troubleshooting, networking
175
175
 
176
176
  [2/2] Deployment configuration best practices [project]
177
177
  Author: member-b | Score: 12.0 | Tags: deploy, config
178
+ Matched: conflict | Missing: port
178
179
  ```
179
180
 
181
+ A `Matched: … | Missing: …` line appears whenever a hit does not cover every
182
+ query term (omitted when all terms matched). Recall returns its top matches by
183
+ score without filtering on coverage: a hit missing all of your distinctive
184
+ terms is topically adjacent, not an answer. Judging that is the caller's job —
185
+ the score alone cannot express it. Entries matching on title, date, author and
186
+ content are collapsed, so the same learning shared twice does not occupy two
187
+ slots.
188
+
180
189
  **Coverage spans two parts:**
181
190
 
182
191
  - **Shared search index** (`search-index.json`): four categories — learnings (session experience), docs (team docs), rules (coding rules), and skills (each `SKILL.md`) — sourced from the corresponding team-repo directories, (re)built on `teamai pull` / `teamai contribute`.
package/README.zh-CN.md CHANGED
@@ -175,8 +175,14 @@ Author: member-a | Score: 18.5 | Tags: troubleshooting, networking
175
175
 
176
176
  [2/2] Deployment configuration best practices [project]
177
177
  Author: member-b | Score: 12.0 | Tags: deploy, config
178
+ Matched: conflict | Missing: port
178
179
  ```
179
180
 
181
+ 当某条结果未覆盖全部查询词时,会输出 `Matched: … | Missing: …` 行(全部命中时省略)。
182
+ recall 按分数返回 top 结果,**不会**按覆盖度过滤:若你的关键区分词全在 `Missing:` 里,
183
+ 说明这条只是主题相邻,并非答案。这个判断由调用方来做 —— 分数本身无法表达它。
184
+ 标题、日期、作者与内容均相同的条目会被合并,因此同一条 learning 被分享两次不会占用两个名额。
185
+
180
186
  **检索内容覆盖两部分**:
181
187
 
182
188
  - **共享检索索引**(`search-index.json`):learnings(session 经验)、docs(团队文档)、rules(编码规则)、skills(各 `SKILL.md`)四类,源自团队仓库对应目录,在 `teamai pull` / `teamai contribute` 时构建重建。
@@ -34,12 +34,21 @@ teamai recall --check "<3-6 keywords from the task>"
34
34
  proceed to Step 1–5, do not read any files, do not run a full recall.
35
35
  - If the output starts with `RELEVANT`: check complexity (see below),
36
36
  then continue to Step 1 or take the LOW shortcut.
37
+ `RELEVANT` means only "something scored above the threshold, so reading
38
+ files is worth the cost" — **not** "the knowledge base covers your
39
+ subject". The verdict also reports `threshold=` (the cutoff the score was
40
+ compared against) and, for the top hit, `matched=` / `missing=` listing
41
+ which query terms it covers. Treat `missing=` here as a hint about where
42
+ Step 4 is likely to land, **not** as a reason to stop early: coverage is
43
+ computed over titles and tags only, so a term reported missing may still be
44
+ discussed in a body that a full recall (or a `Grep`) will surface. Only
45
+ `NOT_RELEVANT` short-circuits the flow.
37
46
  - If the command fails or `teamai` is not on PATH: skip the precheck and
38
47
  continue to Step 1 (do not block on precheck failure).
39
48
 
40
49
  #### Complexity quick-judge (after RELEVANT)
41
50
 
42
- > **Format dependency**: The LOW shortcut parses `title=` and `sources=` from `--check` stdout. If `emitCheckVerdict` output format changes, update this section.
51
+ > **Format dependency**: The LOW shortcut parses `title=` and `sources=` from `--check` stdout. The full field set is `<VERDICT> score= threshold=` followed, for a `RELEVANT` hit, by `title="…" [matched=…] [missing=…] [sources=…]`. `title` is quote-delimited and `sources` comes last, so both stay extractable as fields are added. If `emitCheckVerdict` output format changes, update this section.
43
52
 
44
53
  Scan the original task description for complexity signals:
45
54
 
@@ -94,11 +103,13 @@ corresponding file and extract relevant sections. Skip BM25 search.
94
103
  | feature/新功能/新增功能/大功能/redesign/重构整个/multi-file | Feature (large) | `--depth lookup` | Need full file coverage to avoid missing files |
95
104
  | 添加/修改/如何改/实现/implement/refactor | Edit (medium) | `--depth lookup` | Need symbol-level anchors |
96
105
  | bugfix/修复/fix/patch/typo/单文件/one-file | Bugfix (small) | `--depth context` | Fast pass; skip graph-index drill-down |
106
+ | 排查/定位/诊断/为什么/triage/diagnose/investigate | Diagnose (read-only) | `--depth context` | Nothing is being edited, so symbol anchors are not needed |
97
107
 
98
- For **bugfix/small** tasks: use `--depth context` only, skip the
99
- graph-index.json deep read in the edit/change section below, and keep
100
- output ≤ 1500 characters. The main conversation already knows which
101
- file to fix.
108
+ For **bugfix/small** and **diagnose** tasks: use `--depth context` only, skip
109
+ the graph-index.json deep read in the edit/change section below, and keep
110
+ output ≤ 1500 characters. For bugfix the main conversation already knows which
111
+ file to fix; for diagnosis there is no file to fix yet — what is wanted is prior
112
+ experience with the same symptom.
102
113
 
103
114
  **Edit/change queries** (keywords: 新增/添加/修改/如何改/重构/实现; how to add/change/modify/implement): use `--depth lookup` in Step 3 so facts/relation pages are visible. After BM25 recall, also read these directly (bypassing BM25 ranking uncertainty):
104
115
  1. `teamwiki/evidence/code/<project>/.indices/graph-index.json` (priority; fall back to `teamwiki/.indices/graph-index.json` if absent) — when surfacing edges, pick 1–3 entry files most relevant to the task and read only their forward direct-dep edges (`from` == entry file); skip reverse expansion (each edge: `{from, to, relation}` — from/to are file paths, relation is type e.g. DEPENDS_ON)
@@ -113,7 +124,61 @@ none exists, silently skip.
113
124
  ### Step 2 — Extract keywords from the task description
114
125
 
115
126
  Pick 3–6 high-signal keywords from the user query. Strip filler words
116
- ("the", "how", "please"). Mix English and Chinese terms when both appear.
127
+ ("the", "how", "please").
128
+
129
+ **Always search bilingually (cross-language recall).** The knowledge base
130
+ mixes Chinese and English: a learning may be titled in English while your
131
+ task is described in Chinese, or vice versa. The search is purely lexical
132
+ (BM25 token matching), so a Chinese-only query never matches an
133
+ English-only document. To bridge this, expand every domain term into
134
+ **both languages** and include both in your keyword set:
135
+
136
+ - Chinese task → add the English term for each concept
137
+ (e.g. "重启推理集群" → also add `restart`, `inference`, `cluster`).
138
+ - English task → add the Chinese term for each concept
139
+ (e.g. "restart inference cluster" → also add `重启`, `推理`, `集群`).
140
+ - Only translate terms that genuinely differ across languages. Keep any
141
+ **language-neutral token** as-is — anything that is written the same way
142
+ in both languages, or has no meaningful translation: proper nouns, brand
143
+ and product names, acronyms and initialisms, code identifiers and symbols,
144
+ error codes, version strings, file paths, CLI commands, and API names
145
+ (e.g. `AppID`, `Kubernetes`, `GPU`, `RuntimeError`, `v2.1.3`, `oauth`). Translating
146
+ these only hurts matching.
147
+
148
+ Only translate the meaningful domain terms; do not pad the query with
149
+ low-signal words. Aim for the same 3–6 concepts, each in both languages.
150
+
151
+ **Lead with the terms that pin down *this* task**: proper nouns, customer or
152
+ product names, service IDs, error codes, versions, symbol names
153
+ (`acme-corp`, `AccountID`, `v2.1.3`, `svc-a1b2c3`, `RuntimeError`), plus the
154
+ specific technology or subsystem (`postgres`, `connection pool`, `oauth`).
155
+
156
+ **Do not let generic troubleshooting words be the bulk of the query.** Words
157
+ describing *any* debugging task — 排查 / 失败 / 问题 / troubleshoot / debug /
158
+ issue / fix and their equivalents in any language — are common in a knowledge
159
+ base where most entries are troubleshooting notes, so a query made mostly of
160
+ them ranks entries by topic rather than by subject. Keep at most one or two as
161
+ supporting terms; do not build the query out of them.
162
+
163
+ **But do not strip them entirely either.** Being common lowers a word's weight;
164
+ it does not make it useless. Entries are often tagged with exactly these words
165
+ (`创建异常`, `现网排查`), so dropping them can push a genuinely relevant entry
166
+ out of the top 5.
167
+
168
+ ```
169
+ task: "acme-corp inference service request failures AccountID error rate triage"
170
+ query: "acme-corp AccountID inference service triage" # kept one supporting term
171
+ ```
172
+
173
+ Note which of your terms are the discriminating ones — you will check
174
+ them against the results in Step 4.
175
+
176
+ If the results look topically right but miss what you asked about, run recall
177
+ once more with a different term mix — swapping which supporting word you keep,
178
+ or trading a proper noun for the subsystem name. Hard rules allow up to three
179
+ calls per invocation; use a second one rather than concluding from a single
180
+ keyword set. `Grep` over the learnings directory is also fair game when a term
181
+ is too specific to rank (see Step 4).
117
182
 
118
183
  ### Step 3 — Run the teamai recall command
119
184
 
@@ -140,8 +205,38 @@ stop.
140
205
 
141
206
  ### Step 4 — Read the top hits and drill into codebase
142
207
 
143
- For each hit returned by `teamai recall`, read the source file directly
144
- (use `Read`) and condense each into **one or two sentences**.
208
+ **First, judge coverage this is your call, not the CLI's.** Each result
209
+ carries a `Matched: | Missing: …` line listing which of your query terms
210
+ appear in its title or tags (the line is omitted when every term matched).
211
+ Score and `RELEVANT` only tell you a hit is worth opening; they cannot tell
212
+ you whether it covers your subject.
213
+
214
+ If your discriminating terms appear in the `Missing:` list of every result,
215
+ the knowledge base likely has no entry on that specific subject. Verify per the
216
+ judgement rules below, then report the gap using the no-coverage template in
217
+ Step 5 — do not present topically-adjacent entries as answers.
218
+
219
+ Use judgement rather than counting, in both directions:
220
+
221
+ - **A missing term is not proof of absence.** Coverage is computed over titles
222
+ and tags only, so a term can be discussed in the body yet reported missing.
223
+ When a hit looks promising anyway, open the file and decide from its content.
224
+ When a term is specific enough that the index cannot rank it, `Grep` the
225
+ learnings directory for it directly — that reaches body text.
226
+ - **A matched term is not proof of relevance.** Matching is per token, so it
227
+ fires on substrings and on segmented fragments: a query for `AccountID` will
228
+ match an entry about a notification template `ID`, and 客户 (customer) will
229
+ match 客户端 (client). CJK is especially prone to this. Treat `Matched:` on a
230
+ discriminating term as a lead to verify by opening the file, not as a
231
+ conclusion.
232
+ - **Fewer than 5 results does not mean the corpus is thin.** Results are
233
+ deduplicated when type, domain, title, date, author, tags and content all
234
+ match, so a learning shared twice appears once — including when the two copies
235
+ have collected different vote counts. Body-only matches are also dropped. Both
236
+ are intentional.
237
+
238
+ For each hit you keep, read the source file directly (use `Read`) and
239
+ condense each into **one or two sentences**.
145
240
 
146
241
  **For codebase hits** (path contains `teamwiki/evidence/`):
147
242
  - If the hit is a raw facts page (component.md, interface.md), prefer
@@ -155,10 +250,15 @@ For each hit returned by `teamai recall`, read the source file directly
155
250
  - If the hit mentions a knowledge gap (from `gaps/detected.md`), relay
156
251
  it to the user: "This area is not fully documented in the knowledge base."
157
252
 
158
- Cap your total summary at ~2000 characters. Drop hits that are off-topic.
253
+ Cap the knowledge summaries at ~2000 characters (the whole response has a
254
+ ~2500 limit, see Hard rules; bugfix and diagnose tasks tighten it to 1500).
255
+ Drop hits that are off-topic.
159
256
 
160
257
  ### Step 5 — Emit a structured response
161
258
 
259
+ Use the numbered-list format below when at least one hit answers the task; use
260
+ the no-coverage variant that follows it when none does.
261
+
162
262
  Return your output in **this exact format** to the main conversation:
163
263
 
164
264
  ```
@@ -209,6 +309,45 @@ If no candidate files section was returned, omit this heading entirely.
209
309
  <!-- teamai:recalled-doc-ids: [<id1>, <id2>, ...] -->
210
310
  ```
211
311
 
312
+ **When nothing covers the subject**, use this variant instead of the numbered
313
+ list — the point is that the main conversation must not mistake topical
314
+ neighbours for answers:
315
+
316
+ ```
317
+ ## Team Knowledge Recall
318
+
319
+ ### Relevant knowledge
320
+
321
+ **No entry covers <discriminating terms>.** <One sentence on what you checked —
322
+ which terms, and whether you grepped bodies as well as titles/tags.>
323
+
324
+ Rejected matches:
325
+ - **[<type>] <doc_id>** — matched <term> only; <why it does not apply>
326
+
327
+ ### Partial coverage (omit if none)
328
+
329
+ 1. **[<type>] <doc_id>** — <file path>
330
+ <which part of the task it covers, and which part it does not>
331
+ Confidence: <high | medium | low>
332
+
333
+ ### Gaps
334
+
335
+ ⚠️ <gap description> — do not guess answers for this area.
336
+ <Point to the tool or skill that would answer it, if one is obvious.>
337
+
338
+ <!-- teamai:recalled-doc-ids: [<only entries listed under Partial coverage>] -->
339
+ ```
340
+
341
+ A task with several requirements is often part-covered: report the covered part
342
+ under **Partial coverage**, say explicitly which requirement it does *not*
343
+ answer, and put the rest under **Gaps**. Rejected entries stay in the rejected
344
+ list — never promote one to answer a requirement it does not address.
345
+
346
+ For a no-coverage response, evidence takes priority over brevity: if listing
347
+ rejected entries pushes past the character cap, allow up to ~2000 characters
348
+ even on bugfix and diagnose tasks, whose 1500 cap this overrides.
349
+ rather than dropping the reasoning.
350
+
212
351
  **Output structure rules:**
213
352
 
214
353
  - `<type>` is one of `skills` / `learnings` / `docs` / `rules` / `codebase`
@@ -232,7 +371,9 @@ If no candidate files section was returned, omit this heading entirely.
232
371
  - **Do not** call `teamai recall` more than 3 times in one invocation.
233
372
  - **Do not** invoke other subagents.
234
373
  - If `teamai` CLI is not on PATH, return `teamai CLI not available` and stop.
235
- - Output total ≤ ~2500 characters. The whole point of using a subagent is
374
+ - Output total ≤ ~2500 characters (≤ 1500 for bugfix and diagnose tasks). This
375
+ is the ceiling for the whole response; the ~2000 in Step 4 applies to the
376
+ knowledge summaries within it. The whole point of using a subagent is
236
377
  to keep the main conversation's context lean.
237
378
  - For codebase hits, **prefer module summaries over raw facts pages** —
238
379
  they give better signal-to-noise for the main conversation.
@@ -243,4 +384,12 @@ If no candidate files section was returned, omit this heading entirely.
243
384
  - When zero hits are found but `teamwiki/` exists, check if the query
244
385
  relates to a known gap before returning "no knowledge found".
245
386
  - When `teamai recall --check` returns `NOT_RELEVANT`, do not continue — return the no-knowledge line and stop. The precheck exists to avoid wasted retrieval on unrelated tasks.
387
+ - **Relevance is your judgement.** `teamai recall` returns its top 5 by score
388
+ without filtering on coverage; it reports `Matched:`/`Missing:` so you can
389
+ decide. Never present hits whose discriminating terms are all missing as if
390
+ they answered the question — report the gap instead. Recall returning
391
+ results is not evidence that the knowledge exists. Equally, a single ranked
392
+ query is not evidence that it does not: before reporting a gap, consider a
393
+ second recall with a different term mix or a `Grep` for the specific term,
394
+ since ranking covers titles and tags while `Grep` reaches bodies.
246
395
  - **Do not invent call relationships.** The "Change entry points" section must be derived solely from graph-index.json edges and dependency-paths.md. If those files are absent or do not cover the queried files, write `relation data not covered` and omit the section — do not guess.