chore: 移出本地工具配置 .pi-lens.json

它是 pi-lens 的**仓库级 ignore 配置**,随每个人的工具版本与偏好变化,
对 CI 和其他贡献者毫无意义,还会成为 merge 噪音。
⇒ 移出仓库并加进 .gitignore,各人在本机放自己的一份。

★ 但它注释里的**根因分析要留在仓库**(配置外置、结论内留)——
runbook §6.1/6.2 已写得更全(runner 不按目录语言选+
failed-first 让误报永不自愈),故补 §6.3 说明「为什么仓库里没这个文件」,
原§6.3/6.4 顺延为 §6.4/6.5。

这个上游缺陷不知道哪年修:修之前每个新 clone 的人都会再踩一遍,
所以结论必须内留而配置必须外置。
This commit is contained in:
pi
2026-10-05 13:28:01 +08:00
parent 5250ca35ea
commit 7e4f1058ea
8 changed files with 643 additions and 93 deletions

View File

@ -235,29 +235,43 @@ func (h *Handler) handleMemoryGraphPulse(w http.ResponseWriter, r *http.Request)
return
}
out := graphDataForVisual(data)
// 过滤出窗口内变动过的节点。GraphData 的 nodes 是 []graphEntity(私有类型),
// 这里用重新序列化的方式裁剪:字段少、无向量、且不依赖私有类型断言。
// 成本是「再序列化一次节点」,但相比把 400KB 发出去仍然划算得多。
rawNodes, _ := json.Marshal(out["nodes"])
var nodes []struct {
ID int64 `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
MentionCount int `json:"mention_count"`
UpdatedAt time.Time `json:"updated_at"`
}
_ = json.Unmarshal(rawNodes, &nodes)
// 过滤出窗口内变动过的节点。
//
// ★★★ 必须按 **memory_blocks** 过滤(2026-10-05 修)
//
// 原实现取 `out["nodes"]`,而 GraphData 的 nodes 是从**旧表 entities** 读的
// (memory/graph.go:1445 `SELECT ... FROM entities ORDER BY mention_count DESC`)——
// 旧表在停双写后不再增长,生产里最后更新停在 2026-10-03。
// 而 pulse 的窗口默认 900s(15 分钟)⇒ **1294 个节点永远落在窗口之外**
// ⇒ 恒返回 {"nodes":[]}。
//
// ★ 症状形态与本仓那批「静默失效」完全一致:200 + success:true,
// 无任何报错,前端只是「星图不跟着 agent 动」。
//
// 为什么该按块过滤:星图渲染用的就是 memory_blocks
// (graphDataForVisual 返回的 memory_blocks 是节点来源),
// 且块表是活的(生产最新写入 = 当天)。
//
// 用块做过滤后仍保持**轻量**响应:不返回整个图谱,只回窗口内变动的块。
rawBlocks, _ := json.Marshal(out["memory_blocks"])
var blocks []graphBlockView
_ = json.Unmarshal(rawBlocks, &blocks)
pulse := make([]map[string]interface{}, 0, 8)
for _, n := range nodes {
if n.UpdatedAt.Before(since) {
for _, b := range blocks {
if b.UpdatedAt.Before(since) && b.CreatedAt.Before(since) {
continue
}
pulse = append(pulse, map[string]interface{}{
"id": n.ID,
"name": n.Name,
"type": n.Type,
"mention_count": n.MentionCount,
"updated_at": n.UpdatedAt,
"id": b.ID,
"name": b.Text,
"modality": b.Modality,
"payload_digest": b.PayloadDigest,
"mime": b.MIME,
"tool": b.Tool,
"scene": b.Scene,
"source": b.Source,
"updated_at": b.UpdatedAt,
"created_at": b.CreatedAt,
})
}
writeJSON(w, http.StatusOK, map[string]interface{}{