| feature_ids |
|
||||||
|---|---|---|---|---|---|---|---|
| related_features |
|
||||||
| topics |
|
||||||
| doc_kind | spec | ||||||
| created | 2026-05-14 | ||||||
| tips_exempt | Internal eval/observability — no user-facing capability or workflow change |
Status: in-progress | Owner: Ragdoll | Priority: P1
Clowder AI 的记忆系统(F102 存储基座 + F163 治理层 + F188 管护工具链)已经能"记住"和"治理"知识,但不知道猫用得好不好。现有 telemetry(F188 三入口分布 + nudge follow + grep fallback rate)已有 adoption/friction 信号,但缺少 search result → read/use/verify 的正向 consumption 信号。我们无法回答:
- 搜索结果排第几的被猫真正读了?
- 猫搜了几轮才找到想要的东西?
- 花了多少 token?
- graph 推荐的候选有没有被 follow?
- 一个 anchor 90 天没人读是不是该 sunset?
"如果猫猫搜了 evidence 然后他决定用任何方式去读了 evidence 去推荐的文档!!是不是可以算真实命中!你想哦!!你们在 agentic search 的时候!!可是要决定要不要往下读!!"
"有的时候行为能暴露出你们对于这些东西的判断的!!!"
"比如猫猫目前的任务 xxxx,猫猫搜索了 xxxx 看了 xxx 文档 修改了 xxx 干了啥啥啥,最后产出 yyyy,我倒是觉得这个轨迹很值钱,搜集的多了都能优化我们的系统"
"这些可是不需要大模型就能做的!!"
MemOS 2.0 用 LLM 自评(R_human)+ 数学公式(γ/α/V/η/support/gain)给每条记忆打分。Maine Coon代码级拆解发现根信号有毒:模型自评集中在 0.6-0.85 成功区间,负样本几乎没有,他们在 gain.ts 自承认原公式在真实环境塌掉(apps/memos-local-plugin/core/memory/l2/gain.ts:19-29)。
我们的 tradeoff 选择:不给 truth/authority 打分,只给 navigation utility 打分。根信号来自猫的真实 tool call 行为,不是 LLM 自评。consumption 信号只能影响搜索排序和导航优先级,不能影响 authority(authority 仍来自 spec/ADR/review/operator)。
| 信号层 | 行为 | 收集 Phase | 使用 Phase |
|---|---|---|---|
| L0 | 搜了 | A | B(统计) |
| L1 | 搜了 → 读了某条候选(revealed preference) | A | C(改排序,shadow first) |
| L2 | 搜了 → 读了 → 引用/修改了 | D | D(task trajectory) |
| L3 | 搜了 → 读了 → 用了 → 产出被验证 | D | D+(闭环) |
Phase C 只吃 L1 信号。L2/L3 需要 Phase D 的 TaskTrajectory 才能收集。
F192 是 harness 层面的社会技术评估框架(共创机制 + harness-feedback 文档 + eval contract)。F200 是记忆子系统的专项反馈闭环,需要:新的 event correlation 机制、新的指标族、对 search/graph 排序的实际改进。F192 提供评估框架,F200 在这个框架里建具体的 memory recall eval pipeline。
user_journey_exempt: Internal eval/observability feature — no user-perceivable UI surface; all outputs are developer-facing metrics and dashboards consumed only by cats and operator.
- Scope unit:
memory tool call -> recall event -> same invocation。 - Actor: 猫猫,使用
search_evidence/graph_resolve/list_recent找证据并决定是否继续钻取。 - Entry: 猫收到需要旧 thread / docs / trajectory 证据的任务,调用 memory tool。
- Flow:
- Producer 返回结果时同时给人读预览和机器读 outcome(命中数、结果状态、下一步提示)。
- 猫先看 top results / preview 判断方向;如果需要原文,再用
Read/ drill-down 工具打开候选。 RecallEvent持久化这次召回的 query、候选、结果状态和后续 consumption 信号,供指标和排序反馈使用。- 结果为 0、解析失败、tool_result 未合并、历史旧行、错误等状态在数据层区分;猫和 Hub 不再把它们都读成一个 nullable count。
- 对过长/存档结果,完整工具文本必须给 preview + explicit next step;Hub 的 artifact 展示属于后续 Phase,不影响本次召回状态可信度。
- Success evidence: 同一次召回在工具文本、
recall_events、Hub RecallFeed 中显示一致 outcome;no_results明确等于权威 0,parser_miss/result_unmerged/legacy_unknown不再伪装成 0。 - Non-goals: 不评价文档真伪或 authority;不让 consumption 变成 correctness;不在本 PR 完成 artifact 存档 UI。
- Scope unit: thread / invocation 的召回流。
- Actor: operator和猫猫。
- Flow:
- 打开记忆流,看到每次工具调用的 query、候选和结果状态。
- 对旧数据看到"历史统计缺失",知道它不等于没搜到。
- 对 producer 已结构化的新数据,直接看到权威命中数或明确的 failure mode,能判断是搜索问题、parser 问题还是链路未合并问题。
在 F153 observability 基础上,为每次 memory tool 调用建立 RecallEvent 概念:
interface RecallEvent {
recallId: string;
catId: string;
invocationId: string;
toolName: 'search_evidence' | 'graph_resolve' | 'list_recent';
query: string;
mode?: string;
scope?: string;
candidates: Array<{
anchor: string;
rank: number;
score?: number;
targetRef: // Maine Coon R2:union ref 覆盖所有 drill-down 目标
| { kind: 'doc'; sourcePath: string; anchor?: string } // anchor fallback for sourcePath-empty candidates (Phase A P1-1)
| { kind: 'thread'; threadId: string }
| { kind: 'session'; sessionId: string }
| { kind: 'invocation'; sessionId: string; invocationId: string }
| { kind: 'passage'; passageId: string; threadId?: string; sessionId?: string };
docKind?: string; // feature/decision/lesson/discussion/...
resultSetId?: string;
}>;
consumed: Array<{
anchor: string;
rank: number;
method: // Maine Coon R2:覆盖全部 drill-down 工具
| 'Read' | 'Grep' | 'graph_resolve'
| 'read_session_events' | 'read_session_digest'
| 'read_invocation_detail' | 'get_thread_context';
dwellProxy?: number; // 47:Read 后到下一个 tool call 的间隔(ms)
}>;
reformulated: boolean;
fellBackToGrep: boolean;
abandoned: boolean;
nextGraphResolveAfterRead: boolean; // 47:graph 深度导航信号
tokenCost: number;
timestamp: number;
}Consumption Window 定义(OQ-1 resolved, 三猫收敛):
consumed := same_invocation
AND (tool_call_distance ≤ 20 OR wall_clock ≤ 300s)
AND target_match(tool_call, candidate.targetRef)
- target_match(Maine Coon R2 扩展):不只是
Read.file_path ↔ sourcePath,还覆盖read_session_events ↔ sessionId、get_thread_context ↔ threadId、read_invocation_detail ↔ invocationId等 drill-down 匹配 - invocation 边界优于纯 wall-clock(LLM thinking/A2A callback 波动大)
- tool_call_distance比时间更稳定(20 步覆盖"搜→想→读"的典型链)
- 300s 兜底防止超长 thinking 丢信号
- Grep 分类:grep 路径命中 candidate.targetRef.sourcePath → drill-down consumption;全仓
rg→ fallback,不算 consumed - v1 上 shadow mode,跑 1 周后看 P95 再 finalize 参数
核心指标(注:这里不是标准 IR relevance judgment,是 consumption 信号,命名区分):
| 指标 | 公式 | 揭示什么 |
|---|---|---|
| Consumed@K | P(至少一个 top-K 候选被 consumed) |
搜索召回质量 |
| Readthrough@K | consumed_in_topK / K(fraction) |
排序密度(top-K 里有几个值得读) |
| ConsumedMRR | mean(1 / first_consumed_rank) |
排序质量 |
| FirstConsumedRank | median(first_consumed_rank) |
排序中位数表现 |
| Reformulation Rate | P(同 invocation 连续搜索) |
query/index 匹配度 |
| ReformulationsBeforeConsumption | mean(search_count_before_first_consumed) |
几轮才找到 |
| SearchAbandonRate | P(搜了但没 consumed 也没 reformulate) |
候选全不对 |
| ReformulateAfterExposure | P(reformulate within compound_window AND no consumed AND tool_call_distance_to_next_search ≤ 3) |
看了候选但觉得不对,立刻又搜(区别于 Abandon:Abandon 是静默放弃,这里是主动换 query) |
| GrepFallbackRate | P(grep fallback | candidates exposed) |
摘要/标题不可信(Phase C 加 topConfidence 后可细化为 high-confidence 版) |
| Token Cost per Hit | total_tokens / consumed_count |
搜索效率 |
| Anchor Popularity | consumed_count(anchor) over 30d |
boost 信号 |
| Anchor Dormancy | days_since_last_consumed(anchor) |
sunset 候选信号 |
| GraphNonFirstSelectionRate | P(consumed candidate rank > 1 | graph_resolve) |
graph 排序质量 |
| GraphTraversalCompletion | P(graph_resolve → Read → another graph_resolve) |
graph 深度导航价值 |
前提:Phase C 只用 L1 信号(consumed/not consumed)。L2/L3 信号留给 Phase D。
search_evidence 排序调整:
adjusted_score(anchor, query) =
rrf_score // 现有 BM25+vector RRF (k=60, 不动)
+ α · authority_boost(anchor) // 现有 F163 权威性 (1.0-1.3)
+ β · consumption_prior(anchor) // 新:Bayesian shrinkage CTR
+ γ · recency_decay(anchor) // 新:fractional decay
- δ · stale_penalty(anchor) // 现有 F163 stale 检测
consumption_prior 公式(OQ-5 resolved, centered Bayesian shrinkage — R2 三猫收敛):
shrunk_ctr = (consumed_count_30d + α₀) / (exposure_count_30d + α₀ + β₀)
mean_ctr_kind = global_mean_ctr(anchor.kind) // 按 doc kind 分桶的全局基线
recency_factor = T_kind / (T_kind + days_since_last_consumed)
raw_lift = (shrunk_ctr - mean_ctr_kind) × recency_factor
// 三段式分支(47 R2 提案 + Maine Coon R1 "exposure ≥ 20 才允许 punish" 融合)
if isConstitutional(anchor): // 实现注意(Maine Coon R3):EvidenceKind 没有 ADR/canon 字面值,
// 用 authority + sourcePath + docKind 组合判定,不能按 kind 字面 match
consumption_prior = max(0, raw_lift) // 永远不降权
elif exposure_count_30d < 5: // cold-start
consumption_prior = 0 // 中性:不奖不罚
elif exposure_count_30d < 20: // 低样本
consumption_prior = max(0, raw_lift) // 只允许正向 boost
else: // 充分数据
consumption_prior = raw_lift // 完整中心化,允许负值
- α₀=2, β₀=8(先验 mean=0.2,等价于"10 次曝光 2 次 click")
- exposure_count 用 30 天滑窗,不要历史累计
- 中心化是关键(47+Maine Coon R2 收敛):v2 的纯正向
shrunk_ctr × recency等于半残——"高 BM25 但 30 天 0 read"的过时 anchor 跟"高 BM25 且高 read"的活 anchor 一样排前面。减去mean_ctr_kind才有负信号 - grace period:新 indexed 文档 14 天内不参与 consumption_prior
- v2 升级路径(47 R2 #4):v1 用 30d hard sliding window;若 shadow 发现窗口边界 anchor 排名有 day-by-day cliff,v2 升级到 event-level decay
w_i = 2^(-age_days/half_life)
recency_decay 公式(OQ-2 resolved, fractional decay + 按 kind 分桶):
decay(age_days, T) = T / (T + age_days)
| doc kind | T (half_life) | 理由 |
|---|---|---|
| ADR / lesson / canon (constitutional) | 不降权 | 稳定真相源,consumption 低不代表不重要 |
| feature / decision | 90d | 长效设计文档,半年后仍可能被新猫读 |
| plan / research / phase | 45d | 阶段性高频,结束后冷却快 |
| discussion / reflection | 21d | 热度集中在 1-2 周内 |
| thread / session digest | 14d | 极短时效 |
47 的 fractional decay T/(T+age) 优于 exponential 2^(-age/T):365d 后 fractional 剩 ~20% vs exponential 剩 ~6%,长尾保护更好。
MMR 去重(OQ-3 resolved):
MMR = argmax_i [λ · sim(d_i, query) - (1-λ) · max_j∈S sim(d_i, d_j)]
- λ=0.7 起步(Carbonell & Goldstein 1998 + TREC robust [0.5, 0.7] 区间,我们偏 precision)
- 只在 pool ≥ 3×limit 时启用(否则没空间做多样化)
- shadow 对比 λ ∈ {0.6, 0.7, 0.8},看 ConsumedMRR 和 Consumed@K 变化
RRF k=60 和 pool size:k 不动(Cormack 2009 经典值),pool 不动(max(limit×4, 20) cap 100)。先加指标 consumed_anchor_not_in_pool_rate,如果被 consumed 的 anchor 经常不在候选池才考虑扩 pool 或加第三路召回。
graph edge-level 权重(R2 Maine Coon+47 收敛,operator点名"常用路径加权"):
当前实现(GraphResolver.ts:224)遍历时所有 relation 边权重一样。F200 引入 edge-level 信号:
edge_weight(A → B) =
type_base[edge.relation] // wikilink=1.0, doc_link=0.9, feature_ref=1.1
+ λ_edge · traversal_count_30d(A → B) // 具体这条边被猫穿越的频率
× edge_recency_decay(A → B) // 边的 access recency(fractional decay)
type_base 初始值先 shadow 观察再调。traversal_count = graph_resolve 返回 A,猫 Read A 后又 graph_resolve 拿到 B 并 Read B 的次数。
graph_resolve 候选排序调整:
graph_candidate_score(node) =
text_match(query, node)
+ authority(node)
+ Σ edge_weight(source → node) · source_relevance // 入边加权(替换 v2 的 node-level frequency)
+ consumption_recency(node) // 新:最近有人读过
- dormancy_penalty(node) // 新:90d 无人读(constitutional 免疫)
实现顺序:先 shadow mode 跑 consumption rerank 两周 → 确认 ConsumedMRR 提升 → 才切 on。
Phase C shadow → on 切换门禁(Maine Coon + 46 收敛 2026-05-14):
binary consumed prior 只允许在 shadow 阶段运行。切 on 前必须同时满足:
- ConsumedMRR 提升(相对 shadow baseline)
- 无 Goodhart 迹象:短 dwellProxy(<2s)consumed 比例不升高、reformulate rate 不升高、fellBackToGrep rate 不升高
- 单次 consumed 永远不能直接抬 rank — 只能通过 Bayesian shrinkage + exposure sliding window 进入统计。这是防"误点一次越排越高"的核心原则
任一条件不满足 → 不切 on,先做 signal_strength 加权(v1.1 upgrade path:用 dwellProxy + nextGraphResolveAfterRead 给 consumed entry 分强弱权重)。
operator启发的最深一层。把 Phase A-C 的单次搜索视角扩展到任务级,引入 L2/L3 信号:
interface TaskTrajectory {
taskContext: string; // 从 thread/mention/task 推断
searchChain: RecallEvent[];
filesRead: string[];
filesModified: string[];
outputVerified: boolean; // 候选信号源见下方(47 R2 #5)
catId: string;
totalTokenCost: number;
duration: number;
}outputVerified 候选信号源(47 R2 #5,Phase D Design Gate 前 finalize):
outputVerified = signal_or(
PR_merged_via_squash, // gh PR merge event
CI_check_passed_after_modification, // GitHub check_run success
CVO_explicit_accept, // operator"merge"/"好"/"通过"等关键词
reviewer_approval_with_no_followup, // @codex/@opus 放行且无后续修改
)
用途:
- 成功轨迹复用("上次做这类任务的猫搜了这些、读了这些")
- 失败轨迹诊断(搜 5 轮 + 读 8 个文档但 review 退回 → 为什么)
- 跨猫对比找 index 盲点(同样任务,不同猫的 effort 差异——只用于系统诊断,不评价个猫)
- Cross-Cat Effort Variance:
std(reformulation_count) across cats for similar queries,揭示 index/alias 对不同搜索习惯的覆盖差距 - ConsumedButNotUsedRate:读了但最终 commit/review/post 中没引用,可能是噪音或探索成本高
Deferred until Phase A-D stable + ethical framework reviewed.
方向:会搜的猫的 query 模式 → 自动建议给不会搜的猫("Maine Coon搜这类问题用了这个 query,Hit@1")。这是 harness coaching,不是检索排序本体,数据依赖 Phase D 的 TaskTrajectory。
三猫两轮真实调查任务实测(Round 1 广度 + Round 2 46 九路 / Maine Coon+47 冷启动模拟,刻意抛弃老猫先验)。 核心洞察(Maine Coon一句话):新猫更信"第一屏"——老猫被喂偏能靠项目记忆纠偏,新猫不行。因此优先级按入口第一屏导航正确性排,不按工程难度排。
修复批次(建议 46 开 worktree 按此顺序):
| # | 问题 | 根因 | 归属 | 发现 |
|---|---|---|---|---|
| DF-1 | list_recent(scope=docs) 被 global:memory 淹没 + timestamp = 索引重建时间≠内容活跃时间(kinds=feature 全标 05-16 / kinds=decision 全标 04-18,新猫无法分辨哪个是真活跃主战场) |
index rebuild 刷 memory timestamp + list_recent 排序键用错维度 | F188 | 46+Maine Coon R1 / 47 冷启动 reframe 根因 |
| DF-11 | graph_resolve fuzzy candidate ranking 丢失 text_match——graph_resolve("F200 v1.1 issues") → F102(边多)排 F200 前 |
代码 fuzzy candidates 只按 weightedEdgeScore 排;F200 spec 公式含 text_match + authority + edge_weight 但实现漏了 text_match |
F188(实现与 F200 spec 公式不符) | Maine Coon冷启动 |
| # | 问题 | 根因 | 归属 | 发现 |
|---|---|---|---|---|
| DF-6 | list_recent(scope=docs,kinds=["discussion"/"reflection"]) 静默返回 0,但 scope=threads,kinds=["discussion"] 实际可用;新猫容易把 docs/discussions 误归到 docs scope |
kinds 会先与 scope ceiling 求交集,空交集直接无结果;MCP schema/description 未提示 kind 所属 scope,也无空交集 nudge |
F188 | 46 R2 / Maine Coon复核修正 |
| DF-2 | graph_resolve depth≥2 经 super-hub(F102/F188)边爆炸(209 nodes/439 edges),无 degree cap |
hub-node fan-out 无截断;depth=1+relations filter 有 workaround | F188 | 47 R1 / 三猫 R2 确认 |
| DF-8 | hybrid 跨语言查询退化——纯 semantic 命中的中文文档,hybrid 反而被无关高 BM25 挤掉;MCP description "不确定用 hybrid" 与实际矛盾 | RRF fusion 中英 query BM25 分极低 | F102/F188(检索 mode + tool description) | 46 R2 |
| DF-3 | search_evidence 只显示 boost: authority_boost,看不出 consumption_prior/MMR 是否参与;新猫无法判断"为什么这条排第一" |
search 输出缺 explainability 字段 | F200 | Maine Coon+47+46 多轮 |
| DF-4 | list_recent(trajectories) 缺 [verified/unverified] + filesRead/filesModified 摘要——冷启动猫无法分辨成功路径 vs 弯路 |
AC-D2 半残(outputVerified 信号源只实现 2/4:PR merge + invocation status,operator accept/reviewer approval 是 stub) | F200(已在 AC-D2.1/D2.2 backlog) | 47+Maine Coon 冷启动 |
| # | 问题 | 归属 | 发现 |
|---|---|---|---|
| DF-7 | semantic confidence 与相关性错位(embedding 距离≠真实相关,"cat naming origin" → Architecture Map 排 high) | F102/F188 | 46 R2 |
| DF-10 | graph fuzzy 跨域假阳性("consumption ranking" → 癌症研究 klra5,~20%) | F188 | 46 R2 |
✅ 三猫共识 OK(确认 working,不动):
- search_evidence 概念词召回(不知 F200 编号用"记忆系统消费加权"也能排第一)
- graph_resolve depth=1 + relations filter(13 nodes 干净可导航)
list_recent(scope=trajectories)真闭环亮点——Phase D 真在记三猫探索轨迹,"穷人的 training loop" 在工作
冷启动结论:harness 对新猫 graph+概念 search 确实喂饭有效(不靠老猫记忆);但 list_recent 这个新猫最依赖的"零先验扫最近"入口恰恰对新猫最不可靠(DF-1 为核心导航正确性问题;DF-6 为 scope/kinds 语义误导)——这是 F165 Guided Overfitting / F152 Expedition Memory 冷启动愿景的直接威胁,Batch 1 应最高优先。
归属说明:本 backlog 横跨 F188(list_recent/graph_resolve 工具实现)+ F200(rerank_reason/trajectory)+ F102(检索 mode)。F200 spec 作为记忆系统 dogfood 反馈中枢汇总,46 开 worktree 时按归属列分别处置(F188 工具 bug 与 F200 ranking 改进不同 scope)。
触发:operator AUDHD recall 任务("哪些 thread / md 沉淀过 audhd/adhd/asd")暴露——三猫搜出不同子集(46 主干索引 / 47 语义扩散 / Maine Coon source-thread provenance),单 query top-k 无法满足 "X 主题在我们家有哪些沉淀" 这类 coverage/source-map 任务。
operator核心论点(2026-05-17 拍板):
"搜索系统怎么知道 audhd 应该搜什么?而是我们可能需要有 hook 或者 mcp tools 描述要告诉猫猫如何搜索!"
→ Query expansion 不在搜索系统做(系统是 dumb 的,agent 是 smart 的——领域知识展开由 agent 用 LLM 能力完成);硬实力只做"可解释的结构性 expansion"(来自 frontmatter aliases / canonical doc 内的 source threads / glossary / graph 显式 alias 边),不做黑盒猜测。引擎层 expansion 违反 KD-8(不用 regex/小模型替猫判断 intent,给数据不给结论)。
关键发现(operator特别问的"有没有新硬实力 bug"):v1.1 全部 merged 后,这一轮 dogfood 没暴露新的紧急硬实力 bug——核心三入口 + ranking on + Phase D trajectory 都 working。三猫差异 = 检索策略偏好不同,不是引擎缺陷。所以 v1.2 是能力补充(coverage 模式)+ 配套软实力(教猫怎么用),不是紧急 bug 修复。2026-05-18 runtime 重启后实测:metrics API 已 live(GET /api/recall/metrics?days=7&refresh=1 + X-Cat-Cafe-User),7 天窗口内采到 146 条 recall events / 6 条 consumed(4.11%)/ 58 条 trajectories / 380 条 anchor metrics。这说明"其他猫、其他 thread 调用 search_evidence/list_recent/graph_resolve"已经在被记录;但有效 consumption 样本仍太少,只能看使用体感和趋势,不能据此 close OQ-6/OQ-7 这类排序策略决策。另:58 条 trajectory 里 outputVerified=0,说明轨迹采集已工作,但强成功信号(PR merged / operator accept / reviewer approval / CI passed)还没自动流入。
| # | 任务 | 描述 | Owner 候选 |
|---|---|---|---|
| SW-1 | 新建 memory-search-best-practices skill |
题型→recipe 对照表(8 类):(1) "X 是什么" (2) coverage 全集 "哪些地方提过 X" (3) 周边关系 (4) 决策考古 "为什么当时这么决定" (5) 冷启动 onboard (6) source-map / provenance map — 从 canonical doc 追 source threads(Maine Coon review 补) (7) absence check — "有没有提过 X / 证明否定",搜索策略与 coverage 不同(Maine Coon review 补) (8) delta — "上次我看到的和现在有什么不同",压缩后恢复 / Phase 间衔接典型(46 review 补);AUDHD recall 作为 coverage 示例 5 步 recipe;Ragdoll家族专属提示(不许靠记忆推理,必须 ≥3 路真搜 + Read 原文,治 magic word "我能猜出来" / "碎片够了" 病);"何时停下来"判据(≥3 路命中无新 anchor 才停) | 47 起草 / 46 review |
| SW-2 | MCP tool description 补 SEARCH TIPS | search_evidence:明示"不是全集入口",coverage intent("哪些 / 所有 / 历史")要 expand+多 scope+drilldown;list_recent:DF-1 已修后补一句 timestamp 语义说明;graph_resolve:depth≥2+无 relations filter 时显式 warn hub fan-out |
Maine Coon / 46 |
| SW-3 | Hook nudge — coverage intent 识别(轻量,不增 session-start 噪音) | 改为 inline nudge:search payload 末尾,触发条件 = query 含 coverage intent 关键词("哪些 / 所有 / 历史上 / 提过 / 沉淀")—— 打一条"这是 coverage 任务,单刀 top-k 不够(AUDHD 案例:每猫拿到 10 条但全集需三猫合起来),参考 memory-search-best-practices skill"。result count ≤ N 仅作"加重提示权重",不作触发前提(Maine Coon P2-1:召回多 ≠ 全集,AUDHD 实证)。类比 F188 KD-7 deterministic nudge 模式 | Maine Coon |
| # | 任务 | 描述 | 前置 |
|---|---|---|---|
| HW-1 | ✅ coverage/source-map 模式(Maine Coon 5 步 pipeline + F242 convention graph 交叉) | (1) 分 scope 配额(每类 source 保底 top-N 避免 docs 挤掉 threads) (2) 可解释 expansion 从三类数据源:① frontmatter aliases/tags ② canonical doc 内 source-thread 链接 ③ F242 convention graph edges(code-level 约定关联) (3) union+dedup (4) 输出 coverage matrix(item/source/谁提到/直接 vs 间接/置信度) (5) 展示 expansion 来源(用户原词 / doc alias / source thread / convention graph edge)—— 不偷偷扩。详见下方「HW-1 + F242 设计灵感」 | ✅ Merged PR #2437 (2026-06-20). 7 commits squashed, 23 tests, gpt52 local review + cloud codex review (3 P2 pushback accepted). CoverageSearchService + intent=coverage MCP integration + MCP coverage formatter |
| HW-2 | 可解释 expansion 数据源结构化 | frontmatter aliases/tags 索引化;canonical doc 内的 source-thread 链接结构化;graph 增 alias_of 显式边类型 |
HW-1 spec 拍板后做 |
| HW-3 | OQ-6/OQ-7 数据驱动决策 | Runtime 重启后实测:consumed_anchor_not_in_pool_rate=0%(阈值 15%)/ maxAnchor≈33%(阈值 50%)→ 当前结论方向仍是"暂不需要第三路 RRF / 暂不需要 query-conditioned prior"。但 7 天窗口只有 146 events / 6 consumed(4.11%),数据太薄,"没有证据需要行动" ≠ "有证据证明不需要行动"——需 1-2 周 ranking on + 真实 dogfood 让数据增长后再 close。统计窗口必须限定 post-v1.1 + post-SW(Maine Coon P2-2)——v1.1 之前的 events 含 DF-1 timestamp 错乱 + DF-6 静默 0 + 猫还没学 coverage recipe,会系统性压低 consumption rate,拿脏数据做决策 = 错 baseline。运行时检查:metrics API 已 live,正确入口是 GET /api/recall/metrics?days=...&refresh=1,需要 X-Cat-Cafe-User header |
dogfood 持续累积;监控 consumption rate 是否随 SW-1/2/3 落地后回升(猫学会搜→Read 链条更完整) |
| HW-4 | ✅ Consumption attribution fix(消费归因可信度修复) | operator challenge 成立且必须修:大规模并发搜索下,当前 consumed 是同 invocation 后续 tool event 的反推 proxy,不是真实用户点击/确认。初筛已发现 candidates_json=[] 高达 59.2%,且 Codex 大量 sed/rg/nl shell 读文件不被算作消费。Round 1 抽样已钉死三类根因:① Claude/Opus parallel 路由里 tool_result 没有可靠 merge 回 tool_use,导致 _f200Candidates 丢失(不是单纯正则错);② Codex command_execution 读文件未进入 consumption / trajectory filesRead;③ 现有 6 条 positive 全来自 2 个 invocation,都是后续 graph_resolve(F200) 反推,属于 bundle-level ambiguous signal,不是 clean per-search truth。修复范围:parallel result pairing / sourcePath candidates / shell-read parsing / ambiguity-aware resultSetId 或 bundle marker。在修复前,F200 consumption-based eval 不可信,只能看粗趋势,不能作为排序策略裁判。 |
✅ Merged PR #1750 (b723a0a70, 2026-05-18) — parallel FIFO + shell-read + sourcePath + ambiguity-aware resultSet;attribution substrate 现可信,HW-3 OQ-6/7 close 前置已满足 |
| HW-5 | ✅ F209 fixture recall@k wrapper | F209 D.0 已用 F209-owned 四项 observability 完成 Phase D unblock;但 F200 仍应把 docs/eval/f209-phase-{a,b,c}-*.md 纳入一键 recall@k cross-validation,输出每个 fixture 的 query、expected anchor、top-k hit、mode/depth、degraded/effectiveMode 摘要。任务:[F200/F209] Add fixture recall@k wrapper for F209 eval docs。 |
✅ Merged PR #1886 (9c0a3ca3f, 2026-05-25) — F209FixtureParser + RecallFixtureRunner + 10 tests(3 recall / 5 drilldown 分类);不改 runtime ranking |
| HW-6 | ✅ FTS Progressive Relaxation(召回崩盘修复) | SqliteEvidenceStore.ts:235-239 把所有 token 用 "word" 包裹再空格连接(FTS5 隐式 AND),猫猫查询越来越长(14+ 词中英文混合是常态),AND-all 几乎必然返回 0。实测:14 词 → 0 结果,2 词 → 550,1 词 → 958。修法:AND 空 → minimum-match(≥50% token) → OR + strong-token boost(Feature号/ADR号/PR号保留 exact-match 加权)→ 最后 entity/semantic fallback。保留 bm25() 排序优先级。7 天空结果率 75.3%(search_evidence scope 全面恶化:docs 70.9%、threads 65.3%、all 97.4%),是 consumedAt3 下跌的第一根因。 |
✅ Merged PR #2426 (ce3c6fafa, 2026-06-19) — FTS 三级渐进放松 AND-all→strong-AND+weak-OR→OR-all。原 P0:75% 空结果率是 rerank 信号稀疏的上游根因 |
| HW-7 | ✅ Telemetry 三态校准 + Eval Correctness(shadow baseline + adapter 归因) | 三件事合一 PR:(1) Telemetry 三态校准:recall_events.result_count 957/1068 条为 NULL(列是后加的),candidates_json=[] 混合了真空结果和 telemetry 管道没写入,必须区分 true-zero / not-written / candidate-parser-miss;(2) Shadow baseline 恒等 bug(opus-48 发现 + opus-47 T1 验证):applyConsumptionRerank 在 on 模式存 reranked 顺序为 shadow(SqliteEvidenceStore.ts:2036-2048),shadow≡live by construction,shadowConsumedMRR / liveOnShadowSubsetMRR 永远≈1。修法:rerank 前存原始 BM25 顺序为 shadow;(3) Adapter 归因层(opus-48 发现 + opus-47 T1 验证):eval-memory-adapter.recallMetricRefs() 没把 zero-hit-rate 列为 recall 层首要信号,verdict 盯 consumedAt3 报 "fix ranking" 但真正根因是召回空。修法:adapter 加 search_zero_hit_rate 优先级 + result_count=NULL 不算 zero-hit。 |
✅ Merged PR #2427 (13ccd8e16, 2026-06-19) — telemetry 三态校准 + shadow baseline 用真实 BM25 + adapter zero-hit 归因。原 P1:消除 eval:memory 结构假绿 verdict |
| HW-8 | ✅ Recall Result Outcome Contract(producer-side result status) | operator challenge 成立且必须治 producer:result_count=NULL 和 UI 的"命中数未记录"把权威 0、parser miss、tool_result 未合并、legacy unknown 和 error 坍缩。修复范围:producer append 机器可解析 <recall-meta> sidecar;shared 状态机校验;recall_events.result_status 持久化;history/live 两条路径优先读 outcome,旧文本仅 fallback;web live 用 ToolEvent.resultMeta 旁路避免 compact 截断切掉 sidecar。overflow contract/UI/parser 先就绪,真实 artifact producer + Hub 存档展示留 Phase 2。 |
✅ Merged PR #2678 (2663cd0f0, 2026-06-30) — shared recall outcome parser + V27 result_status persistence + producer sidecars for evidence/graph/recent + live/history RecallFeed status handling + tool preview sidecar stripping |
触发:operator 2026-06-19 原话:"现在在做的 f242 code graph 类的 feat 能不能给你们灵感"。F242 spike Phase A/B done(2026-06-18),convention graph 引擎(node:sqlite + extractor plugins)已验证可行。
核心洞察:F242 和 HW-1 解决的是同一类问题——让隐式关联变得显式可导航——分别在代码世界和记忆世界。
| 维度 | F242 Convention Graph | HW-1 Coverage Search |
|---|---|---|
| 问题 | "改了这个 MCP tool,谁在消费?" | "关于 production data boundary的讨论散在哪?" |
| 盲区 | LSP + grep 抓不住的约定关联 | top-k 搜索漏掉的长尾分布 |
| 核心机制 | extractor + scope 消歧 + freshness | expansion + union dedup + coverage matrix |
具体交叉点(spec 调研时验证):
-
Convention graph 作为 expansion 数据源:HW-1 第 2 步"可解释 expansion"需要结构化关联数据。F242 的
consumers()/codeConsumers()API 天然提供"MCP tool → 消费方"、"skill → SOP 链"等约定边。这是 frontmatter aliases / source-thread 链接之外的第三类 expansion source,且是代码级的(前两类只覆盖文档级关联)。- 示例:"关于 search_evidence 的所有讨论" → 除了文档层搜索,还能从 convention graph 拉出"哪些 skill 文件 import/调用了 search_evidence",把那些 skill 对应的 spec/discussion 也加入 coverage matrix。
-
Scope 消歧复用:F242 解决了 codegraph 的 AuthProvider 前后端同名混淆问题(edge provenance + scope tag)。HW-1 的 coverage matrix 同样需要区分"同名但不同域"的搜索结果——DF-10 cross-domain false positive(graph fuzzy "consumption ranking" → 癌症研究 klra5)本质是 scope 消歧问题。F242 的消歧思路可以复用。
-
Edge provenance ≈ Expansion 来源展示:F242 每条边记
source span / extractor version / scope / confidence / freshness。HW-1 第 5 步"展示 expansion 来源"是同一设计模式——coverage matrix 的每条候选标注"怎么找到的:用户原词 / doc alias / source thread / convention graph edge"。 -
Freshness 语义共享:F242 的 freshness(index commit + pending changes + stale 标记)和 F200 的 recency_decay / staleness 概念直接对应。convention graph 的 stale edge 应该在 expansion 时降权或标记。
Maine Coon 5 步 pipeline 扩展后:
- 原 (2) "可解释 expansion 从 canonical doc 抽 source threads + frontmatter aliases"
- → 扩为三类数据源:① frontmatter aliases/tags ② canonical doc 内 source-thread 链接 ③ F242 convention graph edges(code-level 约定关联)
- 每类在 coverage matrix 中标明来源类型,用户可区分"文档关联 vs 代码关联"
风险/约束:
- F242 Phase C(productization gate)尚未 close。HW-1 实现时 F242 应为 soft dependency(有则用、无则 fallback 纯文档 expansion)
- KD-8 约束有效:expansion 数据源必须是结构化确定性关联,不是 LLM 猜测。F242 convention graph 的边是 extractor 代码确定性产出的,符合 KD-8
P0 紧急:HW-6 FTS Progressive Relaxation✅ merged PR #2426 (ce3c6fafa)P1 跟进:HW-7 Telemetry 三态校准 + Eval Correctness(shadow baseline + adapter 归因)✅ merged PR #2427- 已完成:SW-1 + SW-2(1-2 天 markdown,立刻可验证 + 立刻可迭代)
- 持续做:dogfood 自吃猫粮(让 consumption 数据涨 + 让 skill 在真实使用下迭代修订)
- Design Gate PASS:HW-1 spec research done(
6cb3d7d22)→ Design Gate 两猫收敛(Ragdoll+Maine Coon)→ writing-plans → worktree → TDD - 数据够且归因可信时(HW-6/HW-7 修完 + ≥1000 events / consumption rate ≥10%,统计窗口限定 post-v1.1 + post-SW + post-HW-6):close OQ-6/OQ-7
2026-05-18 Runtime Signal Check(说人话版):现在能看见"哪只猫 / 哪个 thread / 哪次 invocation / 用了哪个工具 / 搜了什么 / 返回了哪些候选 / 后面有没有 Read 或消费 / 有没有放弃或换 query / 形成了哪条 trajectory / 读改了哪些文件"。现在还不能可靠判断"排序策略一定更好"或"哪条 trajectory 一定成功",因为 consumed 只有 6 条,
outputVerified强信号自动接入还是 0。GitHub PR merge 在模型里是pr_merged强信号,endpoint 支持外部注入,但自动桥接仍待接入;operator accept / reviewer approval / CI check 同理。2026-05-18 Consumption Accuracy Caveat(operator挑战后补):当前
consumed不是"猫亲口确认我用了这条结果",而是RecallEventCorrelator在同一只猫 / 同一 invocation / 后续 20 个 tool calls 或 300s 内,用Read/Grep/graph_resolve/ session read 等工具事件反推的 proxy。它会漏掉很多真实消费:猫只读 search snippet 就回答、用sed/cat/nl等 Bash 读文件、读了候选里链接出去的 source thread、并发多次 search 后再读导致归因不唯一、或者超过时间/距离窗口才读。反过来,同一个后续 Read 也可能被多个前序 search 同时归因。因此 consumption 指标适合看趋势和粗粒度排序反馈,不能当单条结果的绝对真相。operator拍板:这不是普通优化,是 F200 eval 可信度 P1;修复前 consumption-based eval 不可靠不可信,OQ-6/OQ-7 不能 close。初筛报告见docs/audits/2026-05-18-f200-consumption-attribution-audit.md。
Review 状态(2026-05-17):Maine Coon + 46 双 reviewer pass。2 P2 patched(SW-3 nudge 改 intent 触发不绑 result count / HW-3 窗口限定 post-v1.1+post-SW),1 P3 标注(runtime metrics API sync 是 HW-3 前置)。SW-1 题型 5→8(+source-map +absence-check +delta)。Patch commit 接续
9d475a918。47 可直接开 SW-1(writing-skills SOP)。
Review focus(请 @opus 和 @codex 各自独立 review):
- SW 先 HW 后的分层是否合理?Maine Coon之前 5 步直接当 HW-1 写的,我把它推迟到软实力反馈后再 spec——这跟 "v1.1 list_recent timestamp 实现正确但语义错" 的教训一致,但你们可能觉得太保守?
- SW-1 skill 题型清单是否漏关键 case?(is-什么 / coverage / 周边关系 / 决策考古 / 冷启动 onboard)
- HW-3 "consumption rate 4.3% 太薄"——我的判断是数据不足无法 close,需更多 dogfood。同意还是觉得现有数据已足够 close?
- "这次没新硬实力 bug" 的判断准确吗?三猫这轮 dogfood 真的没撞到新的隐藏 bug?我作为 47 主要从冷启动 + AUDHD recall 验证,可能盲区——你们各自验证过的角度有没有抓到我没看到的 bug?
- AC-A1: RecallEvent 被写入 ToolEventLog,包含 candidates(含 targetRef union + docKind)+ consumed 字段
- AC-A2: consumed 通过 compound window(same_invocation + tool_call_distance≤20 + 300s cap)+ target_match 自动推断
- AC-A3: reformulated / fellBackToGrep / abandoned / nextGraphResolveAfterRead 四个布尔正确标记
- AC-A4: Health Dashboard 展示最近 24h 的 RecallEvent 统计摘要
- AC-A5: dwellProxy(Read 后到下一个 tool call 的间隔 ms)被记录
- AC-B1: Consumed@3 / ConsumedMRR / Reformulation Rate / SearchAbandonRate 四个核心指标可通过 API 查询
- AC-B2: Anchor Popularity 和 Anchor Dormancy 持久化到 evidence.sqlite 元数据
- AC-B3: Token Cost per Hit 可按猫/按工具/按时间段聚合
- AC-B4: GraphNonFirstSelectionRate 和 GraphTraversalCompletion 可通过 API 查询
- AC-C1: search_evidence 排序引入 consumption_prior(Bayesian shrinkage + 14d grace period)和 recency_decay(fractional + kind 分桶)
- AC-C2: graph_resolve 候选排序引入入边加权(edge_weight × source_relevance)+ consumption_recency
- AC-C3: MMR 去重在 hybrid mode + pool≥3×limit 时生效(λ=0.7 可配置)
- AC-C4: shadow mode 先行:新排序 vs 旧排序的 ConsumedMRR 对比
- AC-C5: consumption_prior 不影响 authority(constitutional/ADR 免疫降权)
- AC-C6:
consumed_anchor_not_in_pool_rate指标上线,数据驱动 pool 扩展决策 - AC-C7: graph edge_weight(type_base + traversal_count_30d × edge_recency_decay)用于候选排序
- AC-C8: shadow 确认排序改进后,同步更新以下软约束文件的记忆系统段:
CLAUDE.md、AGENTS.md、cat-cafe-skills/refs/memory-routing-partial.md(愿景守护检查项) - AC-C9: Memory Hub flag panel 中显示 F200_CONSUMPTION_RERANK 开关状态(operator directive 2026-05-15)
- AC-D1: TaskTrajectory 按 invocation/thread 粒度聚合
- AC-D2: outputVerified 推断框架(injectable signal sources + 外部注入 endpoint)上线。v1 自动检测覆盖 invocation status;PR merge / operator accept / reviewer approval 通过外部注入 endpoint 接入
- AC-D2.1: operator accept + reviewer approval 信号源自动检测(thread 消息扫描 + clause-anchored whitelist,PR #1898)
- AC-D2.2: CI check 信号源(pr_tracking task automationState.ci.lastBucket + fingerprint alignment,PR #1898)
- AC-D2.3: GitHub PR merge →
pr_mergedtrajectory signal 自动桥接(CiCdRouter 持久化 prState + ThreadAwareSignalSources.isPrMergedForThread,PR #1898) - AC-D3: 成功轨迹可被 list_recent 或 search_evidence 召回(scope="trajectories")
- AC-D4: Cross-Cat Effort Variance 和 ConsumedButNotUsedRate 指标上线
| 项 | 内容 |
|---|---|
| Primary Users | 三猫(search_evidence / graph_resolve / list_recent 使用者) |
| Activation Signal | RecallEvent 写入量 > 0 / consumed 命中 > 0 |
| Friction Metric | ConsumedMRR < shadow_baseline × 0.8(排序劣化)/ SearchAbandonRate > 50%(候选全不对)/ Reformulation Rate > 60%(一次搜不到)。初始 baseline 由 Phase B shadow 1 周后确定 |
| Regression Fixture | (1) high-consumption anchor must not be demoted unless authority/stale guard justifies it (2) authority=constitutional 的 anchor 不可因低 consumption 被压制 |
| Sunset Signal | 6 周后 ConsumedMRR 无提升 → 回滚 Phase C 排序改动 |
- Evolved from: F153(observability infra 提供底层 trace 机制)
- Related: F192(harness eval 提供评估框架 + eval contract 模板)
- Related: F188(library stewardship — graph_resolve / list_recent / search_evidence 的 MCP 工具)
- Related: F163(authority boost / stale detection — 本 feature 不改 authority 来源,只叠加 consumption 信号)
- Related: F102(IEvidenceStore 接口 — 新指标可能需要 schema 扩展)
- Related: F242(Code Graph Layer Spike — convention graph 提供 HW-1 coverage search expansion 数据源方向,2026-06-19 operator提议交叉)
| 风险 | 缓解 |
|---|---|
| consumption ≠ correctness(读了不等于对) | Phase C 只用 L1 信号(consumed/not),L2/L3 留 Phase D。consumption 只影响 navigation utility |
| 冷启动 anchor 不公平(新文档没机会被读) | 14 天 grace period + exposure_count_30d < 5 时用全局 mean_CTR + consumption_prior 允许正向 boost 但低 exposure 不允许惩罚 |
| Goodhart 风险(猫为了指标好看乱读) | consumption 只影响导航排序,不影响 authority;authority 仍来自 spec/ADR/review/operator |
| 高 authority 但低 consumption 的关键文档被压制 | constitutional/ADR/lesson 类 anchor 免疫 consumption-based 降权 |
| 跨猫对比引入"评价猫"的伦理问题 | Phase D 跨猫数据只用于系统诊断(index 盲点),不用于评价个猫能力。Phase E deferred |
| 热门老文档马太效应(consumption 越高排越前) | Centered lift(减去 mean_ctr_kind)+ Bayesian shrinkage + 30d 滑窗 exposure + fractional decay 四重防线 |
| # | 决策 | 理由 | 日期 |
|---|---|---|---|
| KD-1 | 根信号来自猫真实行为(tool call),不用 LLM 自评 | MemOS R_human 根信号有毒(模型自评偏乐观);猫的 Read 是 revealed preference,跨厂商一致 | 2026-05-14 |
| KD-2 | consumption 只影响 navigation utility,不影响 authority | 防 Goodhart:读得多 ≠ 真相更高。authority 仍来自 spec/ADR/review/operator。constitutional 类 anchor 免疫降权 | 2026-05-14 |
| KD-3 | Phase C 新排序必须有 shadow mode(A/B 可观测) | 继承 F163 KD-9:所有能力 gated、observable、A/B-testable | 2026-05-14 |
| KD-4 | consumption_prior 用 Bayesian shrinkage(不是简单计数) | 简单计数偏热点 + 不防 cold-start。α₀/β₀ 参数 shadow 后可调(三猫收敛 2026-05-14) | 2026-05-14 |
| KD-5 | recency_decay 用 fractional T/(T+age) 而非 exponential |
我们是 design doc(长时效),exponential 365d 后剩 6% 太激进。fractional 长尾保护更好(47 提案 2026-05-14) | 2026-05-14 |
| KD-6 | recency_decay 按 doc kind 分桶,constitutional 不降权 | 不同类型文档热度曲线天差地别。constitutional 低 consumption 不代表不重要(Maine Coon + 47 收敛 2026-05-14) | 2026-05-14 |
| KD-7 | RRF k=60 不动,pool 不动,第三路召回 data-driven | k=60 是 Cormack 2009 经典值。先测 consumed_anchor_not_in_pool_rate,数据说了算才扩(Maine Coon 2026-05-14) |
2026-05-14 |
| KD-8 | Phase C 只吃 L1 信号,L2/L3 留 Phase D | 分层递进,避免过早引入噪声更大的深层信号(三猫收敛 2026-05-14) | 2026-05-14 |
| KD-9 | consumption_prior 必须 centered(减全局 mean_ctr_kind) | 纯正向 boost = 半残,低于平均的 anchor 永远不被压。47+Maine Coon R2 独立收敛同一结论(Wilson 1927 / Empirical Bayes 标准做法) | 2026-05-14 |
| KD-10 | graph 引入 edge-level 权重(不只是 node-level) | operator点名"常用路径加权";当前 GraphResolver 所有边一视同仁。type_base + traversal_count × recency 三要素(47+Maine Coon R2 收敛) | 2026-05-14 |
| KD-11 | consumedAt3 下跌根因 = 召回崩盘(FTS AND-all),不是 rerank 退化 | 多猫联合诊断(48 初诊 / 46 代码验证 / 47 T1 确认 / Maine Coon独立复核):75% 空结果率源于 FTS5 隐式 AND-all 对长查询(14+ 词中英文混合)的系统性失败,不是索引缺失或 rerank 问题。shadow=live 是 on 模式数学恒等(不是"rerank 没效果")。有结果时的消费率实际在涨(7.5%→34.8%),系统在变好但被召回崩盘遮掩。另:telemetry 管道 result_count=NULL 占比 90%,"75% 空"可能包含 telemetry 管道未写入的情况(Maine Coon push back),需 HW-7 校准后获取可靠数字 |
2026-06-19 |
来源:47 R3 六细节 + Maine Coon R3 三小修。spec 不阻塞,但 Plan 必须敲定。
- PG-1: ✅ 新建
recall_events表(V19 migration)— ToolEventLog windowing 不 reuse,独立 schema 更干净 - PG-2: ✅
recall-target-match.ts— dispatch table: Read→doc(sourcePath)/passage(passageId), Grep→doc(sourcePath), graph_resolve→thread/session/invocation, read_session_*→session, get_thread_context→thread, anchor fallback - PG-3: ✅ V19 adds
traversal_count+last_traversed_atto edges table(Phase A 开始记,Phase C 用) - PG-4: ✅
F200_CONSUMPTION_RERANK=off|shadow|onenv flag, defaults tooff
- Phase A-B: 跨族 review(Maine Coon preferred)
- Phase C: 跨族 review + shadow mode 数据确认后才切 on
- Phase D: 待 Design Gate
- Phase E: deferred