Commit c7f16ba1efd8dd488c70cb19a7ad95c107142cfc

Authored by yibo
1 parent daa45829

docs(lifelog): 转向纯端上 App,废弃 lemonPCRM + 端上 CRM 补齐 TODO

- 主线改为 lifelog-recorder(纯端上 Personal CRM),lemonPCRM(server/frontend/packages) 标已废弃,
  删掉 CLAUDE.md 里所有服务端章节(ACP/Master-Sub-Agent/GraphStore/server 微信链路)
- 加「App 即 Personal CRM:与旧 lemonPCRM 能力对比」+ 6 项差距 + 「Transcript→内部 Person」方向
- HANDOFF §五:存储 TTL/设置页标✅;「回链 lemonPCRM」→「内部 Transcript→Person」;
  新增「端上 CRM 补齐 TODO」P0–P3 清单

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CLAUDE.md
@@ -4,164 +4,35 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co @@ -4,164 +4,35 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
4 4
5 ## 项目概述 5 ## 项目概述
6 6
7 -本仓库(`aipcrm/`)现在托管 **3 个互相关联但独立的子项目**: 7 +本仓库(`aipcrm/`)的**主线 = `lifelog-recorder/`** —— Pixel 8 Pro 上一个**完全端上、零云端**的 Local-First 个人记忆 + 人脉管理(Personal CRM)原生应用:24/7 录音 + 本地中文 ASR + 声纹/人脸识别 + 端上 LLM 纪要/对话 + 以「人」为中心的联系人档案 + 全相册语义索引。所有能力跑在设备上,**不依赖任何 Mac/PC 服务**。
8 8
9 | 子项目 | 路径 | 形态 | 状态 | 9 | 子项目 | 路径 | 形态 | 状态 |
10 |---|---|---|---| 10 |---|---|---|---|
11 -| **lemonPCRM** | `server/` + `frontend/` + `packages/` | Node.js + Express 后端 + 静态前端 | 主线 |  
12 -| **wechat_plain** | `wechat_plain/` | Android Xposed/A11y 模块 + Pixel 部署脚本 | 主线 |  
13 -| **lifelog-recorder** | `lifelog-recorder/` | Pixel 原生 Android 应用(Kotlin + Compose) | v0.8 (2026-06) | 11 +| **lifelog-recorder** | `lifelog-recorder/` | Pixel 原生 Android 应用(Kotlin + Compose) | **主线 v0.8** |
  12 +| **wechat_plain** | `wechat_plain/` | Pixel 上微信 bot 的 Xposed/A11y 模块(端上) | 辅助 |
  13 +| **lemonPCRM** | `server/` + `frontend/` + `packages/` | Node.js + Express 后端 + 静态前端 | **已废弃** |
14 14
15 -**lemonPCRM** — lemonAI 出品的 Local-First AI 个人人脉管理系统(Personal CRM)。以人为中心、以对话为链接,通过知识图谱管理微信、LinkedIn、X 等多平台社交关系,将每个联系人与其社媒动态、会议纪要、文件、照片全面关联。 15 +> [!IMPORTANT] 方向已转向纯端上 App
  16 +> 早期主线是 **lemonPCRM**(Mac 上 Node/Express + 知识图谱 + ACP 驱动 Claude CLI 的服务端 CRM)。
  17 +> 现已**废弃**:其 Personal CRM 能力已在 `lifelog-recorder` 里**原生端上重实现**(联系人档案、人脸/声纹识别、
  18 +> AI 印象、RAG 对话、照片语义检索),不再依赖 Mac。`server/` `frontend/` `packages/` 代码仅作历史留仓,
  19 +> **新功能不要往里加,也不要把 app 回链到它**。App 与旧 lemonPCRM 的能力对比 / 仍存差距见下文
  20 +> §lifelog-recorder「App 即 Personal CRM:与旧 lemonPCRM 的能力对比」。
16 21
17 -AI 对话与编排层基于 ACP 协议驱动本地 Claude CLI 进程,提供单 Agent 执行和 Master → Sub-Agent 多轮编排能力。Node.js + Express,无数据库依赖(使用 Node 22.5+ 内置 `node:sqlite`),数据完全本地化。 22 +### wechat_plain(端上微信 bot,辅助)
18 23
19 -**wechat_plain** — Pixel 上微信 bot 的 Xposed/A11y 落地(A11y UI 自动化是当前唯一能真把消息推进 message 表的发送链路;详见下文 §微信集成架构)。 24 +Pixel 上微信发送/跟踪的落地,纯设备内运行(不依赖 Mac):
20 25
21 -**lifelog-recorder** — Pixel 8 Pro 上的 24/7 录音 + 本地中文 ASR + 时间轴 lifelog 应用(2026-06 新增,详见下文 §lifelog-recorder)。  
22 -  
23 -## 常用命令  
24 -  
25 -```bash  
26 -npm run setup # 首次初始化:cp .env.example .env + pnpm install  
27 -npm start # 生产模式(node server/index.js)  
28 -npm run dev # 开发模式(node --watch server/index.js,热重载)  
29 -./dev.sh # 杀掉端口占用进程 + npm run dev(推荐开发用)  
30 -```  
31 -  
32 -无测试框架,无 lint 脚本。使用 pnpm workspaces(`packageManager: pnpm@10.28.1`)。  
33 -  
34 -## 架构  
35 -  
36 -### 技术栈  
37 -- **后端**:Node.js (≥18) + Express,pnpm workspace monorepo  
38 -- **数据库**:Node 22.5+ 内置 `node:sqlite`(`DatabaseSync`),位于 `server/db/lemon_crm.db`  
39 -- **AI**:Claude CLI(本地子进程,`--dangerously-skip-permissions` 自动批准)  
40 -- **文件解析**:mammoth(.docx)、pdf-parse(.pdf)  
41 -  
42 -### 目录速查  
43 -  
44 -| 目录 | 说明 |  
45 -|------|------|  
46 -| `packages/acp-core/` | ACP 协议层:Protocol / Transport / Launcher 三层抽象 + ClaudeCliProtocol / AcpProtocol |  
47 -| `packages/agent-core/` | Agent 运行时(ESM):目录驱动的 Agent、AgentBus、AgentRegistry、AgentScaffold |  
48 -| `server/index.js` | Express 入口(路由 + 静态前端) |  
49 -| `server/src/core/` | 编排引擎:orchestrator、master-session、agent-manager、session-pool、stream-executor、prompt-builder、parser、runtime-resolver |  
50 -| `server/src/engine/` | 进程层:run-registry、command-queue、process-guard、idle-timer、failover-error |  
51 -| `server/src/tools/` | Master 工具:call-agent-tool、tool-registry、graph/(图谱 MCP 工具集) |  
52 -| `server/src/standalone-entry.js` | 编程 API:`runMasterSession` / `runOrchestration` / `runSingleAgent` |  
53 -| `server/routes/` | API 路由:master-chat、config、graph、wechat、import、analysis、photo |  
54 -| `server/services/` | conversation-logger、file-parser、memory-service、claude-chat-service、wechat/、linkedin/、meeting/、photo/、x/ |  
55 -| `server/db/GraphStore.js` | 本地知识图谱存储层(SQLite):Person / Organization / Project / Event / Asset 节点 + KNOWS / BELONGS_TO / PARTICIPATED 等边 |  
56 -| `frontend/` | 静态前端(单 HTML 文件,由 server/index.js 托管) |  
57 -| `server/config/backends.json` | ACP Launcher / Client 定义 |  
58 -| `server/config/agents.json` | 静态 Agent 注册表(可选,也可由 `system/agents/` 目录发现) |  
59 -  
60 -### API 路由  
61 -  
62 -| 路径 | 说明 |  
63 -|------|------|  
64 -| `POST /api/master/chat` | Master Agent 多轮对话(SSE) |  
65 -| `POST /api/master/upload` | 文件上传注入对话 |  
66 -| `GET /api/master/sessions` | 列出活跃 session |  
67 -| `DELETE /api/master/sessions/:id` | 关闭 session |  
68 -| `GET/PUT /api/config/items/:key` | 读写配置文件 |  
69 -| `GET /api/health` | 健康检查 |  
70 -| `GET /api/graph/nodes` | 列出图谱节点(?type=Person&limit=100) |  
71 -| `GET /api/graph/nodes/:id` | 查询单个节点(含边) |  
72 -| `POST /api/graph/nodes` | 创建/更新节点 |  
73 -| `GET /api/graph/search?q=关键词` | 全文搜索 |  
74 -| `POST /api/graph/edges` | 创建关系边 |  
75 -| `GET /api/graph/path?from=id&to=id` | 查询关系路径 |  
76 -| `POST /api/wechat/import-contacts` | 导入微信联系人到图谱 |  
77 -| `POST /api/wechat/import-chat` | 导入微信聊天记录 |  
78 -| `GET /api/wechat/contacts?q=搜索` | 查询微信联系人 |  
79 -| `GET /api/wechat/sessions` | 最近会话列表 |  
80 -| `POST /api/import/...` | 多平台数据导入 |  
81 -| `POST /api/analysis/...` | 图谱分析(关系链路、聚类等) |  
82 -| `POST /api/photo/...` | 照片服务(人脸聚类、向量检索) |  
83 -  
84 -### 配置文件  
85 -  
86 -| 文件 | 说明 |  
87 -|------|------|  
88 -| `.env` | PORT(默认 3010)、HOST、CORS_ORIGINS 等 |  
89 -| `server/config.js` | 端口、CORS、目录路径的运行时配置对象 |  
90 -| `server/config/backends.json` | ACP Launcher 定义(command、args、protocol) |  
91 -| `server/config/agents.json` | 静态 Agent 注册(可选) |  
92 -  
93 -## 关键架构模式  
94 -  
95 -### ACP 协议四层结构  
96 -  
97 -```  
98 -Application (AgentManager)  
99 - ↓  
100 -Protocol (ClaudeCliProtocol 直接 spawn / AcpProtocol JSON-RPC)  
101 - ↓  
102 -Transport (ProcessTransport stdio / PipeTransport / WebSocketTransport)  
103 - ↓  
104 -Launcher (ProcessLauncher spawn / NoneLauncher 无操作)  
105 -```  
106 -  
107 -`runtime-resolver.js` 根据 `backends.json` + `agents.json` 配置自动推断使用哪一层。  
108 -  
109 -**ClaudeCliProtocol 调用方式**:  
110 -- 生成命令:`claude --input-format stream-json --output-format stream-json --verbose --include-partial-messages --dangerously-skip-permissions`  
111 -- 输入格式:`{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]}}`  
112 -- 输出:NDJSON 事件流  
113 -- 单进程跨多轮复用(session reuse)  
114 -  
115 -**Mock 模式**:设置 `LEMONBOSS_CLAUDE_MODE=mock` 可读取 fixture 文件而不启动真实进程,用于调试。  
116 -  
117 -### Master → Sub-Agent 调度流程  
118 -  
119 -1. 用户消息 → `MasterSession.handleMessage()`  
120 -2. `PromptBuilder` 组装系统提示(含工具描述 + 可用 Agent 列表)  
121 -3. Claude 响应中的工具调用用 `[TOOL_CALL: tool_name] {...json...} [/TOOL_CALL]` 格式标记  
122 -4. `ToolRegistry.parseToolCalls()` 解析后交给 `AgentManager.callAgent()`  
123 -5. `SessionPool` 按 `agentName:client:deploy:workDir[:scope]` 为 key 复用已有 session  
124 -6. 工具结果注回对话,最多循环 10 轮(`SAFETY_MAX_LOOPS=15`)  
125 -  
126 -**Orchestrator** 额外提供格式自动修正(`MAX_REPAIRS=5`)与结果验证(`ResultTracker`)。  
127 -  
128 -### Agent 发现与记忆  
129 -  
130 -- Agent 优先从 `system/agents/` 目录发现(目录驱动),`agents.json` 作为静态补充  
131 -- 每个 Agent 的记忆存储在其目录下的 `memory/` 子目录,纯文件系统  
132 -- `AgentScaffold` 用于创建新 Agent 目录结构  
133 -  
134 -### 知识图谱(GraphStore)  
135 -  
136 -`server/db/GraphStore.js` 使用 `node:sqlite`(Node 22.5+ `DatabaseSync`),无需额外依赖。  
137 -  
138 -- **节点类型**:Person、Organization、Project、Event、Asset  
139 -- **边类型**:KNOWS、BELONGS_TO、PARTICIPATED、CONTAINS、MENTIONED_IN、ASSOCIATED  
140 -- **分析状态**:`analysis_status` 字段跟踪节点是否已被 AI 分析(none / pending / done)  
141 -- **Master 工具**:`server/src/tools/graph/` 提供 `create_person`、`get_person`、`link_persons`、`search_graph`、`get_relationship_path` 等工具供 AI 调用  
142 -  
143 -### 微信集成架构  
144 -  
145 -`server/services/wechat/` 提供从 Mac 和 Pixel 双端点与微信交互的能力:  
146 -  
147 -- **发送消息(实际工作链路)**:`am broadcast com.hermes.wechat.SEND_MSG` → **`HermesAccessibilityService`**(lsposed-wechat-sendmsg 模块内)→ 启动微信 LauncherUI → 点搜索按钮 → 搜索 `toUserDisplayName`(**必须传 nickname**,如"火星人")→ 点搜索结果 → 找 `bkk` 容器内的 EditText 输入文本 → 点 `bql` 发送按钮。纯 UI 自动化,绕开所有反射 / hook 失败。  
148 -- **消息跟踪**:`android-wechat-tracker-sqlcipher.js` 直接轮询解密后的 `EnMicroMsg.db`(SQLCipher)  
149 -- **自动回复**:`auto-reply.js` 结合 tracker + broadcast,在 Pixel 上独立运行  
150 -- **数据导入**:`wechat-importer.js` / `wechat-reader.js` 将联系人和聊天记录导入知识图谱  
151 -  
152 -> [!WARNING] 关于其他两条已废弃的发送路径  
153 -> - **LSPosed 反射 API**(`HermesWeChatModule.sendTextMessageDirect`):监听同一广播但走 `u01.r1.a → m1.a()`。`Send result: true` 是**误报**——`builder.a()` 后主线程异步提交触发 null 异常被 swallow,消息不进 `message` 表。  
154 -> - **Frida daemon 队列**(`android-wechat-sender-frida.js` + `wechat_plain/scripts/frida-daemon/frida_daemon.js`):Frida 17 + 微信 8.0.72 注入大体积 bundle 触发反调试,微信进程崩溃,已废弃。  
155 -> 这两条路径的命名让人误解;真正能把消息推进 message 表的只有 A11y service。 26 +- **发送消息(唯一可用链路)**:`am broadcast com.hermes.wechat.SEND_MSG` → **`HermesAccessibilityService`**(lsposed-wechat-sendmsg 模块内)→ 启动微信 LauncherUI → 点搜索按钮 → 搜索 nickname(如"火星人")→ 点结果 → `bkk` 容器内 EditText 输入文本 → 点 `bql` 发送按钮。纯 A11y UI 自动化,绕开所有反射 / hook 失败。
  27 +- **已废弃的两条发送路径(命名误导,勿用)**:LSPosed 反射 API(`HermesWeChatModule.sendTextMessageDirect`,`Send result: true` 是误报,消息不进 `message` 表);Frida daemon(Frida 17 + 微信 8.0.72 注入大 bundle 触发反调试崩溃)。真正能推进 message 表的只有 A11y service。
156 28
157 > [!IMPORTANT] A11y service 启用方式 29 > [!IMPORTANT] A11y service 启用方式
158 -> `enabled_accessibility_services` 系统设置易被关闭。检查与重新启用: 30 +> `enabled_accessibility_services` 系统设置易被关掉,重启:
159 > ```bash 31 > ```bash
160 -> adb shell "settings get secure enabled_accessibility_services"  
161 > adb shell "su -c 'settings put secure enabled_accessibility_services com.hermes.wechat.xposed/com.hermes.wechat.xposed.accessibility.HermesAccessibilityService; settings put secure accessibility_enabled 1'" 32 > adb shell "su -c 'settings put secure enabled_accessibility_services com.hermes.wechat.xposed/com.hermes.wechat.xposed.accessibility.HermesAccessibilityService; settings put secure accessibility_enabled 1'"
162 > ``` 33 > ```
163 34
164 -详见 `server/services/wechat/README.md`。 35 +详见 `wechat_plain/` 内文档。
165 36
166 ## lifelog-recorder(Pixel 8 Pro 24/7 录音 + 本地中文 ASR + 本地 LLM,v0.8) 37 ## lifelog-recorder(Pixel 8 Pro 24/7 录音 + 本地中文 ASR + 本地 LLM,v0.8)
167 38
@@ -169,7 +40,7 @@ Launcher (ProcessLauncher spawn / NoneLauncher 无操作) @@ -169,7 +40,7 @@ Launcher (ProcessLauncher spawn / NoneLauncher 无操作)
169 40
170 ### 项目目标 41 ### 项目目标
171 42
172 -把 Pixel 8 Pro 当成**永远开机的麦克风**:7×24 后台录音 → VAD 切段 → 中文 ASR 转文字 → 入库 → 按时间轴显示和搜索 → LLM 总结成纪要。最终目的是把所有「我说过 / 别人对我说过」的内容沉淀成可搜索、可回放的个人记忆库,下接 lemonPCRM 的人脉图谱(某段语音 → 某联系人 → 某项目)。 43 +把 Pixel 8 Pro 当成**永远开机的麦克风**:7×24 后台录音 → VAD 切段 → 中文 ASR 转文字 → 入库 → 按时间轴显示和搜索 → LLM 总结成纪要。最终目的是把所有「我说过 / 别人对我说过」的内容沉淀成可搜索、可回放的个人记忆库,并在 **app 内自成端上 Personal CRM**(photolog):某段语音 → 声纹 → 联系人档案,照片 → 人脸 → 同一联系人。**整套 CRM 跑在设备上,已取代旧的 Mac 端 lemonPCRM**。
173 44
174 约束:**完全本地 / 零云端依赖 / 月成本 0 元 / 隐私走 0 网络**。 45 约束:**完全本地 / 零云端依赖 / 月成本 0 元 / 隐私走 0 网络**。
175 46
@@ -273,19 +144,43 @@ Foreground Service (foregroundServiceType=microphone, WAKE_LOCK partial) @@ -273,19 +144,43 @@ Foreground Service (foregroundServiceType=microphone, WAKE_LOCK partial)
273 144
274 剩余摘要: 145 剩余摘要:
275 - ⭐ **语义搜图落地**(v0.8 已接 `EmbedClient`,但需在 Pixel llama-swap 配 `embed` 模型才生效;中文 embedding GGUF) 146 - ⭐ **语义搜图落地**(v0.8 已接 `EmbedClient`,但需在 Pixel llama-swap 配 `embed` 模型才生效;中文 embedding GGUF)
276 -- ⭐ **回链 lemonPCRM**(Transcript / 照片 caption 实体 → GraphStore `MENTIONED_IN`,v2) 147 +- ⭐ **内部 Transcript 实体 → Person 表**(端上 NER + 共现,取代旧「回链 lemonPCRM」;见下文 §下一步)
  148 +- ⭐ **微信抽取端上化**(消除 photolog 仅剩的 Mac 依赖;见下文差距分析 #6)
  149 +
  150 +### App 即 Personal CRM:与旧 lemonPCRM 的能力对比
  151 +
  152 +App(photolog)已覆盖、并在「联系人」维度超过旧 lemonPCRM 的核心:
  153 +
  154 +| 能力 | 旧 lemonPCRM(Mac/server) | 现 app(端上) |
  155 +|---|---|---|
  156 +| 联系人实体 | `Person` 图节点 | `Person`(融合 **声纹/人脸/微信/手机** 四模态,更丰富) |
  157 +| 多源导入 | 微信 / LinkedIn / X / 会议 / 照片 | 微信 + 手机通讯录 + 手动 + **24/7 录音(独有)** |
  158 +| 每人聚合视图 | 社媒动态 / 纪要 / 文件 / 照片 | 聊天 / 朋友圈 / 照片 / **录音** / AI 印象 / 简历(`PersonProfileScreen` 四 tab) |
  159 +| AI | Master Agent over 图谱(工具编排) | RAG 对话 over 转写/纪要(`LifelogRetriever`)+ AI 印象 |
  160 +| 照片 | 人脸聚类 + CLIP 检索 | 人脸聚类 + 语义检索(端上 ML Kit + ArcFace + Qwen-VL + embed) |
  161 +| 部署 | Mac Node 服务(依赖 Claude CLI) | **纯端上**(更隐私 / 零成本 / 零网络) |
  162 +
  163 +**仍存差距**(旧 lemonPCRM 有、app 还没有):
  164 +
  165 +1. **人↔人关系图**:app 只有 *人↔模态*(声纹/人脸/微信/手机)链接,**没有 person↔person 边**(KNOWS / 同事 / 同项目)。app 现在是「带富资料的扁平联系人表」,不是知识图谱。
  166 +2. **Organization / Project / Event 实体**:app 只有 `Person`/`Photo`/`Face`,没有组织/项目/事件节点。
  167 +3. **关系分析**:旧有 关系路径(`path`) / 社群发现(`communities`) / 待跟进(`followups`);app 三者皆无。
  168 +4. **AI agent / 工具编排**:app 是**纯 RAG 对话**,AI 不能对数据做动作(建人 / 连边);旧有 Master→Sub-Agent + 图谱工具(`create_person`/`link_persons` 等)。
  169 +5. **Transcript 内容 → 实体**:app 只按**声纹**把录音连到 `Person`(谁说的),**没有从转写文本抽人名/项目**做关联(旧 lemonPCRM 的 `MENTIONED_IN`)——这正是下一步要补的。
  170 +6. **微信抽取端上化**:微信联系人/头像/聊天/朋友圈仍由 **Mac 一次性抽取**(解密 `EnMicroMsg.db` + 抠头像)推到 `filesDir/wx_enroll/`,再由 `WeChatEnrollWorker` 端上入库。手机系统通讯录已完全端上;微信抽取是「纯 App」最后一块拼图。
  171 +
  172 +### 下一步:Transcript 实体 → 内部 Person 表(取代旧「回链 lemonPCRM」)
277 173
278 -### 与 lemonPCRM 的关系 174 +**不再回链外部 server**,改在 **app 内部**打通:从 `Transcript.text` / `Summary` 抽实体(人名/项目/地点,端上 LLM 或规则 NER)→ 与本地 `Person` 表匹配 → 建一张「提及」关系(新表 `mentions(segmentId, personId, ...)` 或 Person↔Segment 边)。让 `PersonProfileScreen` 除了现有「TA 自己说的」(声纹匹配段)之外,还能显示「**TA 被哪些录音提到、说了什么**」。这直接补差距 #5;同段被同时提到的人 → 共现边,又为差距 #1(人↔人关系图)打基础。
279 175
280 -目前**完全独立**——lifelog-recorder 的 Room DB 跟 lemonPCRM 的 GraphStore 没打通。未来计划:把 Transcript / Summary 表里的实体(人名 / 地名 / 项目)抽到 GraphStore 当 `MENTIONED_IN` 边,让你的「某次会议说了什么」可以从图谱里反查。这是 v2 范畴。 176 +> 上面 6 项差距的**可执行 TODO 清单(带优先级 P0–P3 + 做法)**见 `lifelog-recorder/HANDOFF.md` §「端上 CRM 补齐 — TODO」。路线:P0 #5 → P1 #1 → P2 #6。
281 177
282 ## 注意事项 178 ## 注意事项
283 179
284 -- `server/src/standalone-entry.js` 的 `loadConfig()` 优先读 `backends.json` + `agents.json`,无需数据库。  
285 -- `prompt-builder.js` 的 `getSystemStateXML()` 只返回时间戳(公司/OKR 层已移除)。  
286 -- Agent 目录内放 `SKILL.md` 文件会绕过协议封装,直接作为系统提示使用。  
287 -- `server/index.js` 包含控制字符净化中间件:Agent 通过 curl 发送的 JSON body 可能含原始换行符,若解析失败会自动清理 `\x00-\x1F` 控制字符后重试。 180 +- **构建**:`cd lifelog-recorder && JAVA_HOME=/opt/homebrew/opt/openjdk@17 ./gradlew :app:assembleDebug`,`adb install -r ...`。无测试框架。改 Room schema **必须写 Migration**(`AppDatabase` 已去 destructive 改 fail-loud;24/7 录音库静默清掉是大事故,见 memory `lifelog-room-migration-wipe.md`)。
  181 +- **改完即真机验证**:app 是 24/7 录音的命脉,改 `RecorderService` / 管线后务必装机看 logcat(`reconcile →` / `pipeline running` / `BlockProcessor`)确认录音没断。
  182 +- **`keys.properties` / `local.properties` gitignored**:讯飞凭证 + Hermes 端点 → `BuildConfig`;`sdk.dir` 换机要改。模板见 `keys.properties.example`。
  183 +- **`server/` `frontend/` `packages/`(旧 lemonPCRM)已废弃**:不再维护、不要往里加功能、不要让 app 依赖它。
288 184
289 -> [!WARNING] (Agentic Self-Correction Loop Prevention)  
290 -> **Master Agent 必读**:在 `Bash` tool 中使用含多重双引号的复杂命令(如 `curl -d '{"id":"lemonv"}'`)时,JSON 转义容易崩溃并陷入死循环。  
291 -> **解决方案**:任何需要提交 JSON Payload 的操作,先写入 `/tmp/*.json` 文件,再通过 `curl -d @/tmp/payload.json` 发送。 185 +> [!NOTE] 旧 lemonPCRM 的服务端架构(ACP 四层 / Master→Sub-Agent / GraphStore / 微信 server 链路)已从本文件移除。
  186 +> 如确需考古,查 git 历史里本文件的早期版本。
lifelog-recorder/HANDOFF.md
@@ -254,11 +254,35 @@ Tier-0 PhotoFaceWorker (15min, battery-not-low) Tier-1 PhotoVlWorker (1 @@ -254,11 +254,35 @@ Tier-0 PhotoFaceWorker (15min, battery-not-low) Tier-1 PhotoVlWorker (1
254 254
255 剩下: 255 剩下:
256 256
257 -1. **存储 TTL**:删超过 N 天的 .opus,文字永留。Periodic WorkManager job。  
258 -2. **设置页**:存储用量、模型切换、provider 切换、暂停时段配置(v1 定的 MVP 是「一键暂停就够」,但 v2 可能要细化)。 257 +1. ✅ **存储 TTL**(2026-06-08 完成):`StorageManager.prune` 按天目录删超期 .opus、文字永留;每天 periodic worker;设置页「存储」段(用量 + 保留时长 + 立即清理),默认永久保留。
  258 +2. ✅ **设置页**(基本完成):`SettingsScreen` 已含 纪要模型后端 / 聚类·合并·最短识别阈值 / llama-swap 端点 / 分段间隔 / **定时不录(quiet hours)** / 存储用量+TTL / 电池豁免。
259 3. ✅ **多 anchor 平均**(2026-06-07 完成,L2):重命名/合并某说话人时 `rebuildAnchor` 用该人名下全部段的均值重建 anchor,取代单段注册。 259 3. ✅ **多 anchor 平均**(2026-06-07 完成,L2):重命名/合并某说话人时 `rebuildAnchor` 用该人名下全部段的均值重建 anchor,取代单段注册。
260 -4. **回链 lemonPCRM**:Transcript 提到的人名 / 项目 → GraphStore `MENTIONED_IN` 边。 260 +4. **内部 Transcript 实体 → Person 表**(取代旧「回链 lemonPCRM」):在 **app 内部**从 `Transcript.text`/`Summary` 抽实体(人名/项目,端上 LLM 或规则 NER)→ 匹配本地 `Person` → 建「提及」关系(新表 `mentions(segmentId, personId)`),让人物档案显示「TA 被哪些录音提到」(现仅显示「TA 自己说的」=声纹段)。同段共现的人 → 人↔人边。**不再回链 Mac 端 lemonPCRM**(已废弃)。
261 5. ✅ **hermes gateway 自启**(2026-06-04 完成):用 Magisk `service.d` 脚本开机拉起(Termux:Boot 未装,root 方案更稳),见下方「§ 自启(Magisk service.d)」。 261 5. ✅ **hermes gateway 自启**(2026-06-04 完成):用 Magisk `service.d` 脚本开机拉起(Termux:Boot 未装,root 方案更稳),见下方「§ 自启(Magisk service.d)」。
  262 +6. **微信抽取端上化**:消除 photolog 仅剩的 Mac 依赖(微信联系人/头像/聊天/朋友圈现由 Mac 一次性抽取推到 `filesDir/wx_enroll/`)。
  263 +
  264 +### 端上 CRM 补齐 — TODO(对齐并超越旧 lemonPCRM)
  265 +
  266 +> 旧 Mac 端 lemonPCRM 已废弃,能力在 app 内重建。下表是「app 当前缺、旧 lemonPCRM 有」的 6 项,
  267 +> 按优先级排(P0 先做)。能力对比详见 CLAUDE.md §「App 即 Personal CRM」。
  268 +
  269 +- [ ] **P0 · #5 Transcript 内容 → Person「提及」关系**(最高价值,最贴 app 形态)
  270 + - 现状:录音只按**声纹**连到人(谁说的);不从转写文本抽人名/项目。
  271 + - 做法:块处理后(或事后 worker)对 `Transcript.text` 抽实体(端上 LLM 4B 或规则/词典 NER)→ 匹配本地 `Person`(name/realName/nickname/alias,拼音兜底)→ 写新表 `mentions(segmentId, personId, name, confidence)`(Room 迁移 +1)。
  272 + - 出口:`PersonProfileScreen` 加「被提到」tab(现只有「TA 自己说的」=声纹段)。
  273 + - 依赖:端上 4B 已就绪(llama-swap 8080)。
  274 +- [ ] **P1 · #1 人↔人关系(共现边)**
  275 + - 做法:基于 #5,同一会话/时间段被同时提到 + 同时在场(声纹)的人 → `relations(personA, personB, kind, weight)` 共现/认识边,weight 随共现次数累加。
  276 + - 出口:人物档案「相关的人」;后续可做关系图可视化。
  277 +- [ ] **P2 · #6 微信抽取端上化**(消除最后的 Mac 依赖,工程债)
  278 + - 现状:微信联系人/头像/聊天/朋友圈由 Mac 解密 `EnMicroMsg.db`(SQLCipher)+抠头像,推到 `filesDir/wx_enroll/`。
  279 + - 做法:把解密+抽取搬到端上(root + SQLCipher key 端上取),`WeChatEnrollWorker` 直接读微信库;配方见 memory `wechat-android-decrypt.md` / `wechat-avatar-face-enrollment.md`。
  280 +- [ ] **P3 · #2 Organization / Project / Event 实体**(产品决策:要不要从「联系人表」长成「图谱」)
  281 + - 新增节点类型 + 与 Person 的边(属于/参与);可由 #5 的实体抽取顺带产出(项目名/公司名/事件)。
  282 +- [ ] **P3 · #3 关系分析**:关系路径(两人间最短链)/ 社群发现(聚类)/ 待跟进(followups:从录音承诺「下周给他发X」抽待办)。依赖 #1 的关系边。
  283 +- [ ] **P3 · #4 AI 能对数据做动作(agent/工具编排)**:让对话 AI 不止 RAG 问答,还能调工具建人/连边/改资料(端上轻量 tool-calling,Hermes 或本地模型)。最大、最后做。
  284 +
  285 +> 路线:**P0(#5) → P1(#1) → P2(#6)**,三步把「录音→人→关系」在端上闭环;P3 三项是「要不要把 app 升级成真·知识图谱 + AI agent」的产品选择,按需再开。
262 286
263 ### hermes gateway 设置(v0.5 关键前置) 287 ### hermes gateway 设置(v0.5 关键前置)
264 288