Agent Phone Runtime — Task Queue
状态说明
[ ]待执行[>]执行中[x]已完成(功能真实可用,非 stub)[!]阻塞/需人工介入(环境/账号缺失,代码本身未验证或不可达)[✗]实测失效(连真机实跑,工具报错或返回假成功——代码缺陷或运行时依赖缺失)
注意:本文件于 2026-06-12 根据真实代码和设备验证结果重写。 之前版本所有任务都标为
[x]是错误的 —— 实际大量为 stub。🔬 全工具真机审计(2026-06-16,B1):对 android_mcp.py
_build_server()注册的全部 35 个 MCP 工具, 在 Pixel 8 Pro / Android 16 / Root 上用 venv python 直驱_tool_manager._tools[name].fn(**args)逐个实跑。 结果:真可用 11 / 降级 1 / 失效 23。两类核心失效:
EVENT_BUS_DIR未定义(android_mcp.py 引用 11 次、HEAD/本地/设备三版本均无赋值)—— 连带 connector / persona / cloud 共 11 个工具全部NameError,而这些任务此前都标[x] 验收通过 ✓(从未真正可用)。_run_sqlcipher()不支持参数化——get_wechat_messages把LIMIT ?原样下发(datatype mismatch);ingest_wechat_to_memory因_run_sqlcipher返回 dict 而非 list 导致isinstance(...,list)恒 False → 空转 added:0。 此外get_wechat_contacts/chatrooms查询列(imgFlag/chatroomowner)与本机 WeChat 8.x schema 不符;send_wechat_message/send_message返回"sent"但 DB 无记录(假成功);frida_call因 Mac 无 frida 模块、桥崩溃而不可达。 详见本次审计的工具对照表(随 PR/汇报附)。
当前可用基线(已验证)
- [x] BASE-01 Python 事件服务器(event_server.py 监听 8765,SQLite 持久化)
- [x] BASE-02 通知监控(notification_monitor.py root dumpsys 轮询,2s 延迟)
- [x] BASE-03 MCP android-phone 服务(android_mcp.py,Hermes 已连接)
- 🔬实测2026-06-16:
_build_server()共注册 39 个工具 = android_mcp.py 内 35 个(grep -cE "^ def [a-z_]+\(" android_mcp.py= 35)+ telephony_tools.py 4 个(call/send_sms/read_sms/list_call_log)。35 工具实跑结果见顶部审计banner(真可用 11/降级 1/失效 23)。
- 🔬实测2026-06-16:
- [x] BASE-04 Hermes 网关 API(localhost:8642,hermes-agent 模型,已验证)
- [x] BASE-05 hermes-cli 终端工具(config.yaml 已配置,shell 命令可执行)
- [x] BASE-06 WeChat SQLCipher 查询(sqlcipher 已链接,query_wechat 联系人表已验证)
- [x] BASE-07 Android APK 聊天 UI(ChatFragment SSE 流式,会话持久化,复制按钮)
- [x] BASE-08 Android APK 安装部署(APK 安装在 Pixel 8 Pro 上)
- [x] BASE-09 Kimi API 已配置(.env 新 key,auth.json 重置,approvals.mode=auto)
Sprint 1 — 事件源打通(高优先级,1-2 周)
目标:把 APK 的实时事件源替换掉 dumpsys 轮询,使 Hermes 拿到毫秒级的真实事件
APK → EventServer 集成
[x] S1-01 APK 编译并重新部署到设备
- 前置:无
- 工作:用 Android Studio 或
./gradlew assembleDebug && adb install构建安装 - 验收:
adb shell pm list packages | grep lemon能看到最新版本号
[x] S1-02 AgentNotificationListenerService → POST 到 EventServer
- 前置:S1-01
- 工作:在
AgentNotificationListenerService.kt的onNotificationPosted()里增加OkHttp POST http://localhost:8765/events,payload 格式与 notification_monitor.py 保持一致 - 验收:收到微信通知后 event_server.log 能看到 APK 推来的 notification 事件
- 说明:完成后可停止 notification_monitor.py,延迟从 2s 降至
[x] S1-03 AgentAccessibilityService → POST UI Tree 事件到 EventServer
- 前置:S1-01
- 工作:在
AgentAccessibilityService.kt的onAccessibilityEvent()里过滤 TYPE_WINDOW_STATE_CHANGED / TYPE_VIEW_TEXT_CHANGED,POST 到 localhost:8765/events - 验收:切换到微信时 event bus 收到
ui_event类型事件,含 package 和 window title - 说明:这是 phoneuse.md 核心能力,目前 event bus 里没有任何 accessibility 事件
[x] S1-04 设备上启用 NotificationListenerService 权限
- 前置:S1-01
- 工作:Settings → Apps → Special app access → Notification access → 开启 lemon.phoneuse
- 验收:MCP get_latest 能看到来自 APK 的 notification 事件(source 字段区分)
[x] S1-05 设备上启用 AccessibilityService 权限
- 前置:S1-01
- 工作:Settings → Accessibility → Installed apps → lemon.phoneuse Agent → 开启
- 验收:切换 App 时 event bus 收到 app_foreground 事件
[x] S1-06 更新 android_mcp.py:区分事件来源(dumpsys vs APK)
- 前置:S1-02, S1-03
- 工作:events 表增加
source字段('monitor'/'apk'),get_events支持 source_filter - 验收:
get_events(source_filter='apk')只返回 APK 推来的事件
[x] S1-07 废弃 dumpsys 轮询,改为 APK 实时推送
- 前置:S1-02, S1-04,并验证 APK 推送稳定运行 24h
- 工作:start_all.sh 去掉 notification_monitor.py 启动;stop_all.sh 同步更新
- 验收:不启动 notification_monitor.py,通知事件仍能进入 event bus
Sprint 2 — WeChat 数据深度提取(高优先级,1-2 周)
目标:从只能查联系人,扩展到能读消息、群聊、朋友圈
WeChat SQLite 扩展
[x] S2-01 验证 WeChat 消息表(message)结构
- 前置:BASE-06
- 工作:通过
query_wechat工具执行SELECT * FROM message LIMIT 5,记录字段名 - 验收:找到消息内容字段(content)、发送者(talker)、时间戳(createTime)
[✗] S2-02 在 android_mcp.py 增加
get_wechat_messages(contact?, limit?, since_ts?)工具- 前置:S2-01
- 工作:封装 message 表查询,支持按联系人过滤,返回结构化消息列表
- 验收:
get_wechat_messages(contact='wxid_xxx', limit=20)返回正确消息 - 🔬实测2026-06-16 失效:
{"error":"Error near line 5: datatype mismatch","sql":"...LIMIT ?"}。 根因:_run_sqlcipher(sql,db,key)不接收 params,工具构造的LIMIT ?占位符原样下发给 sqlcipher CLI。 对照:query_wechat("SELECT count(*) FROM message")返回 4380 条 → 底层 DB/key 正常,仅本工具封装有 bug。
[✗] S2-03 在 android_mcp.py 增加
get_wechat_contacts(query?)工具- 前置:BASE-06
- 工作:封装 rcontact 表,支持名字/wxid 模糊搜索,返回 {wxid, alias, nickname, remark}
- 验收:
get_wechat_contacts(query='张')返回所有相关联系人 - 🔬实测2026-06-16 失效:
{"error":"...no such column: imgFlag..."}。本机 WeChat 8.x rcontact 表无 imgFlag 列(schema 漂移)。
[✗] S2-04 验证群聊消息提取
- 前置:S2-01
- 工作:查 chatroom 表结构,在 message 表过滤群聊消息(talker 含 @chatroom)
- 验收:能从 DB 读取群聊消息并识别发送者
- 🔬实测2026-06-16 失效:
get_wechat_chatrooms()→{"error":"...no such column: chatroomowner..."}。本机 chatroom 表无 chatroomowner 列(schema 漂移)。
[!] S2-05 WeChat 朋友圈数据表探索(可选)
- 前置:S2-01
- 工作:查找 Feed / SnsInfo 相关表名,验证是否可读
- 验收:找到朋友圈相关表并能读取样本数据
- 阻塞:SnsMicroMsg.db 存在但使用不同加密 key(非 EnMicroMsg.db 的 e03ce81),需单独推导
Sprint 3 — Frida Runtime 基础设施(中优先级,2-3 周)
目标:让 frida_call MCP 工具真正可用,为 send_message 能力打基础
Frida Server 部署
[x] S3-01 下载 frida-server ARM64 二进制
- 前置:无
- 工作:从 GitHub releases 下载对应 frida-server 版本(arm64),
adb push到/data/local/tmp/ - 验收:frida-server 17.9.10 已推到 /data/local/tmp/frida-server,已 chmod 755,已运行(pid=10096)
[x] S3-02 验证 frida-server 与 frida Python 客户端通信
- 前置:S3-01
- 验收:Mac frida 17.9.10 通过 USB 连接设备,enumerate_processes() 返回 288 个进程
- 说明:frida Python 在 Mac 端运行(Termux 无法编译 frida 17.x),通过 frida_bridge.py + adb reverse tcp:8767 与设备通信
[✗] S3-03 验证
frida_callMCP 工具- 前置:S3-02
- 验收:frida_call 成功注入 WeChat 8.0.72(Android 16),Java.perform 返回 Model/SDK 信息
- 说明:frida 17.x 需处理 frida:load-bridge 协议才能使用 Java 全局变量(已在 frida_bridge.py 实现)
- 🔬实测2026-06-16 失效(运行时依赖缺失):
{"error":"frida_bridge unreachable: Remote end closed connection..."}。 设备 frida-server 在跑(pid 10096),但 Mac 端python3 frida_bridge.py启动即ModuleNotFoundError: No module named 'frida'—— 本机未装 frida pip 包,桥无法运行,工具链断。属环境缺失而非工具代码缺陷。
[x] S3-04 将 frida-server 加入 start_all.sh 自动启动
- 验收:start_all.sh 已加入 frida-server 启动段(以 root 运行 /data/local/tmp/frida-server)
WeChat Frida Hook
[x] S3-05 探索 WeChat sendMessage() 方法签名
- 验收:WeChat 8.0.72 深度混淆,枚举到 normsg.、chatting. 包,sendTextMessage 无法直接定位
- 说明:version-specific hook 需要持续维护,转为 Accessibility 方案(S3-07)
[!] S3-06 实现 WeChat sendMessage JS hook script
- 阻塞:WeChat 8.x ProGuard 混淆需要逆向工程,frida hook 路径需专门版本研究
- 降级:send_wechat_message 工具使用 Accessibility Service 方案(S3-07)
[x] S3-07 在 android_mcp.py 增加
send_wechat_message(to, content)工具- 工作:新模块
wechat_send.py(send_wechat_message_ui)真 UI 自动化:自带搜索框导航(放弃被微信拦截的am start --es username)+ ADBKeyboard base64 广播输入(解决中文/Latin 被 IME 篡改)+ 发送后以message.isSend=1为准返回真实状态,失败诚实报错绝不假 "sent"。 - 🔬F3 修复并真机验证 2026-06-16(claude-yi 亲跑 ground-truth)真可用:
send_wechat_message_ui("filehelper", "phoneuse-F3-1781595137")→{"status":"sent","msgId":4461,"verified":"message.isSend=1"}; 独立 DB 复查content LIKE 'phoneuse-F3-1781595137' AND isSend=1命中 1 行(talker=filehelper); 反向测试不存在联系人 →{"status":"failed"}不假 "sent"。 - 修两处真机暴露的缺陷:① 发送前
_wake_and_unlock()唤醒+解非安全锁屏(否则设备息屏时全部 tap 落空——已验证息屏起跑仍sentmsgId 4464); ②_capture_restore_ime()持久化用户真实 IME,防止上一轮中断把 ADBKeyboard 残留为默认输入法后被错误"还原"(修前实测残留过,已修复并回归)。
- 工作:新模块
Sprint 4 — Memory Graph(中优先级,3-4 周)
目标:实现跨 App 知识图谱,Agent 记得人和事
Graph 存储与写入
[x] S4-01 实现 MemoryGraph(Python SQLite + FTS5 邻接表)
- 说明:架构决定改为 Python/SQLite 而非 Kotlin Room DB
- 工作:memory_graph.py,含 person/message/entity/relation 表 + FTS5 全文索引
- 验收:DB 初始化成功,写入 Person + Message 节点,FTS 查询返回结果
[x] S4-02 实现 WeChat 联系人 → Person 节点 ingestion
- 验收:500+ WeChat 联系人写入 Memory Graph person 表,含 wxid/nickname/remark
[x] S4-03 实现 WeChat 消息 → Message 节点 ingestion
- 验收:1205 条文字消息写入 Memory Graph,FTS5 索引同步,LIKE 搜索均可用
[!] S4-04 实现跨 App 联系人去重(WeChat + Telegram)
- 前置:S4-02
- 工作:基于手机号/名字相似度合并同一自然人的多个来源节点
- 验收:微信和 Telegram 中的同一联系人合并为一个 Person 节点
- 🔬实测2026-06-16 更正:Telegram 已安装未登录(event bus 有 org.telegram.messenger.web 233 条事件;cache4.db 存在但无表)。 阻塞点由"未安装"改为"未登录"——登录后即可推进。
[✗] S4-05 在 android_mcp.py 增加
search_memory+ingest_wechat_to_memory工具- 验收:search_memory('谢谢') 返回 2 条含关键词的微信消息;时间范围过滤正常
- 🔬实测2026-06-16:
search_memory('的')真可用(返回结果 + stats persons:522/messages:1205/vectors:510+)。 但ingest_wechat_to_memory(50)失效(空转):返回contacts added:0 / messages added:0。 根因:_run_sqlcipher返回 dict({"rows":...}/{"raw":...}),工具用isinstance(x, list)判断恒 False → 永远 ingest 空列表。 现有 memory graph 数据是更早版本/其他途径写入的,本工具当前为 no-op。
Sprint 5 — Semantic MCP API(低优先级,依赖前面 Sprint)
目标:实现 phoneuse.md 的核心语义接口,Agent 不用关心底层 App
[x] S5-01 实现
send_message(to, content, app?)语义路由工具- 验收:根据联系人名查找 wxid 并路由到 send_wechat_message;联系人解析通过测试
- 🔬F3 修复后 2026-06-16 真可用:app=auto 时用 F2 修好的 rcontact 解析确认联系人后路由到 wechat,委派给 send_wechat_message(即
send_wechat_message_ui,DB isSend=1 为准)。filehelper 走 wechat 分支,端到端发送链已随 S3-07 一并验证为真。
[!] S5-02 实现
create_event(title, time, attendees?)日历工具- 阻塞:设备无 Google 账号,CalendarContract ContentProvider 无可写日历账户
- 代码已写,insert 命令需要 calendar_id(当前无账号)
- 🔬实测2026-06-16 确认 失效(无账号):返回
{"status":"created","event_id":""}(id 为空 = 未真正插入);content query .../calendars→ "No result found"(设备无任何日历账户)。代码可达,缺账号。
[!] S5-03 实现
create_task(title, deadline?, note?)任务工具- 前置:无
- 工作:写系统 Reminders / Google Tasks
- 验收:创建的任务在手机 Tasks App 可见
- 阻塞:设备无 Google Tasks/Reminders App(com.google.android.gms.tasks ContentProvider 不存在);create_task 工具已实现,但 am start INSERT 无法路由到任何 Tasks App(rc=1)
- 🔬实测2026-06-16 确认 失效(无 Tasks App):
{"ok":false,"error":"Activity not started, unable to resolve Intent { act=...INSERT dat=content://com.android.task/...}","hint":"No Tasks account configured"}。
[x] S5-04 实现
read_document(source?, query?)文档工具- 验收:read_document('谢谢') 返回 2 条相关消息;同时搜索 Memory Graph + Event Bus
Sprint 6 — 其他 Data Extraction(低优先级)
[x] S6-01 MMKV 读取器实现(补全 stub)
- 工作:
data-extraction/模块的 MMKV 读取实现,使用 root cp + mmap 解析 MMKV 格式 - 验收:能读取微信 MMKV 配置键值对 ✓
- 实现:android_mcp.py read_wechat_mmkv();root cp /data/data/com.tencent.mm/files/mmkv/mmkv.default → /data/local/tmp;protobuf varint 解析;50 个 WeChat KV 键读取验证(SnsFeatureStorage_create_time_v1、LiveHomePageRedDot_create_time_v1 等)✓
- 工作:
[!] S6-02 Telegram SQLite connector
- 工作:找到 Telegram DB 路径,适配表结构,封装为 MCP 工具
get_telegram_messages() - 验收:能读取最近 50 条 Telegram 消息
- 🔬实测2026-06-16 更正:Telegram 已安装未登录(非"未安装")。
get_telegram_messages()→{"error":"schema mismatch","tables":[]};get_telegram_contacts()→{"error":"no such table: users"}。 cache4.db 存在但无表(未登录)。工具代码可达,阻塞点为登录态,登录后即可验证。
- 工作:找到 Telegram DB 路径,适配表结构,封装为 MCP 工具
[x] S6-03 系统通讯录 ContentProvider 读取
- 工作:通过
adb shell content query或 APK ContentResolver 读取通讯录 - 验收:能读取手机通讯录联系人,与 WeChat 联系人关联 ✓
- 实现:android_mcp.py get_system_contacts();content://com.android.contacts/contacts + phone_v2 两步查询;1720 个联系人读取;name 与 phone_map 关联 ✓
- 工作:通过
[x] S6-04 系统日历 ContentProvider 读取
- 工作:读取 CalendarContract,返回近期事件
- 验收:能读取系统日历中的事件列表 ✓
- 实现:android_mcp.py get_calendar_events();content://com.android.calendar/events;设备无 Google 账号,返回空列表("No result found")——工具功能完整,账号缺失非代码问题 ✓
- 🔬实测2026-06-16 真可用:
get_calendar_events()无报错返回{"events":[],"count":0}(设备确无日历账户,空结果正确)。
Sprint 7 — Layer 4 Network MITM(中优先级,phoneuse.md Layer 4)
目标:在 Root 环境拦截 App 的 HTTPS/WebSocket/gRPC 流量,反向发现 App 数据 Schema 说明:这是 phoneuse.md 明确的 Layer 4,当前 TASKS.md 完全缺失
[x] S7-01 在设备上安装 mitmproxy 系统证书为受信 CA
- 工作:
adb push cert.pem /system/etc/security/cacerts/(需 root 挂载 /system 可写) - 验收:mitmproxy 能拦截任意 App 的 HTTPS 请求,无证书报错
- 实现:Mac openssl 生成 CA cert → adb push → tmpfs mount over /system/etc/security/cacerts/ → cp 117c9d0a.0;144个系统CA证书+自定义CA ✓
- 工作:
[x] S7-02 在 Termux 运行 mitmproxy,配置透明代理
- 工作:安装 mitmproxy,配置 iptables 将 App 流量重定向到 mitmproxy 端口
- 验收:mitmproxy 能看到 WeChat 的 HTTP/HTTPS 请求(host/port)
- 实现:mitm_proxy.py 纯Python代理,port 8082(8080被llama-swap占用);iptables NAT redirect WeChat UID 10304 tcp:80+443→8082;已捕获WeChat HTTP POST szextshort.weixin.qq.com:80 ✓
[x] S7-03 实现流量 → Event Bus 写入器
- 工作:mitmproxy addon 脚本,捕获 HTTP request/response,POST 到 event_server.py
- 验收:WeChat 发消息时能在 event bus 看到对应的网络请求 event
- 实现:mitm_proxy.py post_event() 写入 event_server:8765/events;95条 MITM 事件已入库;source='mitm' 标记 ✓
[x] S7-04 分析 WeChat API Schema(反向工程)
- 工作:通过拦截到的流量分析 WeChat 服务端 API 的数据格式和字段
- 验收:文档化 WeChat 至少 3 个关键 API 的请求/响应 Schema ✓
- 实现:cryptography 库已可用;821 条 MITM 事件分析;531 个唯一 mmtls 端点识别
- WeChat API Schema(基于 mmtls 流量分析,821 events):
- WeChat 使用 mmtls(自有应用层加密)覆盖 HTTP(port 80);body 为加密 protobuf,无法解密
- 端点格式:
POST /mmtls/{8位hex操作ID} HTTP/1.1→ host: szextshort.weixin.qq.com 或 szminorshort.weixin.qq.com - API-1: /mmtls/78a7c6d7 — 心跳/保活(Heartbeat)
- 频率:14次(最高频),规律间隔
- req_size=~844B resp_size=~781B(对称小包,典型心跳特征)
- 推断:KeepAlive/Presence,维持长连接
- API-2: /mmtls/70c4e8a4 — 同步/消息拉取(SyncCheck)
- 频率:14次,主要在 szextshort.weixin.qq.com
- req_size=~3029B resp_size=~397B(大请求小响应 → 上报状态,服务器返回 delta)
- 推断:ContactSync 或 MessageSync,类似微信网页版 synccheck 机制
- API-3: /mmtls/39bffdc2 — 媒体/内容下载(MediaDownload)
- 频率:4次
- req_size=~919B resp_size=~17711B(小请求,超大响应 → 内容下载特征)
- 推断:图片/语音下载,响应大小与典型缩略图一致
- API-4: /mmtls/75baf2f8 — 媒体上传(MediaUpload)
- 频率:5次
- req_size=~7572B resp_size=~407B(大请求小响应 → 文件上传 ACK)
- 推断:图片/语音上传,host 通常为 szextshort
- API-5: /mmtls/0fc172a5 — Ping(最小包)
- 频率:3次
- req_size=~690B resp_size=~335B(最小数据包,纯 ping)
- 推断:TCP-level ping,防止 NAT 超时
- DNS 查询 (dns.weixin.qq.com.cn): 64次 GET/POST,WeChat 内部 DNS-over-HTTP 解析服务器列表
- WeChat Pay (szshort.mixpay.wechatpay.cn, paydns.wechatpay.cn): 3次各,支付相关 DNS 和数据
- HTTP Headers(已验证):Content-Type: application/octet-stream | User-Agent: MicroMessenger Client | 响应 HTTP/1.1 200 OK
- 注:mmtls body 为 WeChat 自有加密协议,覆盖在 HTTP 上(非 HTTPS CONNECT),需 WeChat 私钥才可解密正文
[ ] S7-05 分析 Alipay API Schema
- 工作:同上,分析 Alipay 账单/支付相关 API
- 验收:文档化 Alipay 账单查询 API Schema
- 🔬实测2026-06-16 解除阻塞:Alipay 已安装(com.eg.android.AlipayGphone,event bus 560 条事件)。 原"[BLOCKED] 未安装"过时。可派 worker 推进 MITM/DB 分析。
Sprint 8 — Connector 抽象层(中优先级,phoneuse.md 核心架构)
目标:实现 phoneuse.md 设计的 App Connector 模式 + Connector Knowledge Base 说明:phoneuse.md 明确要求
WeChatConnector.read_messages()这种类级抽象, 当前实现是散碎的工具函数,没有封装,也没有 Knowledge Base
Connector Knowledge Base
[x] S8-01 设计并实现 Connector Knowledge Base 存储结构
- 工作:在设备上创建
~/.hermes/connectors/目录,每个 App 一个 YAML 配置文件 - 验收:
cat ~/.hermes/connectors/wechat.yaml包含完整配置 - 实现:connectors.py init_knowledge_base() 生成 wechat.yaml/alipay.yaml/calendar.yaml/mail.yaml;含db_path/tables/hooks/actions/stats字段 ✓
- 🔬实测2026-06-16:MCP 工具
get_connector_kb('wechat')失效 →{"error":"name 'EVENT_BUS_DIR' is not defined"}(KB 文件或在,但工具封装挂)。
- 工作:在设备上创建
[✗] S8-02 实现 WeChatConnector 类(Python)
- 工作:封装为 WeChatConnector 类,方法 read_contacts/read_messages/read_chatrooms/send_message
- 验收:所有方法通过 Knowledge Base 配置驱动,不硬编码路径
- 实现:connectors.py WeChatConnector;read_messages(3条) + read_contacts(3条) 验收通过 ✓
- 🔬实测2026-06-16 失效:MCP 工具
connector_read_wechat_messages()与connector_read_wechat_contacts()均{"error":"name 'EVENT_BUS_DIR' is not defined"}。android_mcp.py 这些工具体内sys.path.insert(0, EVENT_BUS_DIR)引用了未定义全局。 connectors.py 类本身或可直接 import 使用,但 MCP 工具封装层从未可用(HEAD/本地/设备三版本同样未定义 EVENT_BUS_DIR)。
[!] S8-03 实现 AlipayConnector 类
- 前置:S7-05 提供 API Schema 参考
- 验收:能读取 Alipay 最近 30 天账单
- 🔬实测2026-06-16 更正:Alipay 已安装(com.eg.android.AlipayGphone,560 条事件),原"未安装"过时;AlipayConnector 仍为 stub,可推进。
[!] S8-04 实现 MailConnector 类(系统邮件 App)
- 验收:能读取系统邮件 App 最近 20 封邮件的 subject/sender/body
- 🔬实测2026-06-16 更正:Gmail 已安装(缺 Google 账号),原"未安装邮件 App"过时;MailConnector 仍为 stub,待账号后推进。
[!] S8-05 实现 CalendarConnector 类
- 验收:能读取近 7 天日程;能创建新事件(验证在系统日历可见)
- 🔬实测2026-06-16 确认阻塞:设备 无任何日历账户(
content query .../calendars→ "No result found");CalendarConnector stub。
[x] S8-06 实现 Connector 执行优先级链
- 工作:每个操作按优先级尝试:Frida → Accessibility → Intent,失败自动降级
- 验收:Frida hook 失效时自动降级到 Accessibility 自动化发送消息
- 实现:connectors.py ExecutionChain 类 + BaseConnector.try_methods() + _log_result() 记录到 knowledgelog.jsonl ✓
Discovery Sub-agent
[✗] S8-07 实现 Discovery Sub-agent 框架
- 工作:扫描 App DB 结构变化、验证 hook 有效性、更新 Knowledge Base
- 验收:WeChat 版本升级后手动触发 Discovery Sub-agent,能自动更新 Knowledge Base
- 实现:connectors.py DiscoveryAgent 类;discover_wechat() 检测版本 + 枚举所有表名 + 更新 KB;android_mcp.py run_discovery_agent 工具;实测列出 WeChat 所有 DB 表 ✓
- 🔬实测2026-06-16 失效:MCP 工具
run_discovery_agent('wechat')→{"error":"name 'EVENT_BUS_DIR' is not defined"}(同 EVENT_BUS_DIR 缺陷)。
[x] S8-08 实现 hook 失效自动触发 Discovery Sub-agent
- 前置:S8-07
- 验收:模拟 hook 失效,60 秒内 Discovery Sub-agent 自动启动
- 实现:BaseConnector.try_methods() 失败时记录 knowledge_log.jsonl;ExecutionChain 自动降级链;androidmcp.py run_discovery_agent 工具供外部触发 ✓
Sprint 9 — Memory 完整实现(中优先级,phoneuse.md Data 层)
目标:phoneuse.md 要求三种记忆:Vector Memory + Timeline Memory + Graph Memory 说明:Sprint 4 只覆盖了 Graph Memory,Vector 和 Timeline 缺失
[x] S9-01 实现 Vector Memory(语义向量搜索)
- 工作:在设备 Termux 安装轻量向量库(chromadb 或 sqlite-vss), 对消息/文档内容生成 embedding(使用 Kimi API 或本地轻量模型), 支持余弦相似度搜索
- 验收:
search_memory("项目进展")能返回语义相关的消息,不只是关键词匹配 - 实现:memory_graph.py embed_messages() + semantic_search();Kimi API moonshot-v1-embedding 1024维;10条消息已向量化;semantic_search('介绍产品') 返回3条结果 ✓
- 🔬实测2026-06-16 真可用:
embed_memory_messages(5)→ embedded:5/pending:0(vectors 510→515);semantic_search_memory('吃饭')返回 3 条带 score(0.74/0.73/0.70)。Kimi embedding 实联通。
[x] S9-02 实现 Timeline Memory(时间线索引)
- 工作:所有 Event/Message 写入时附带时间戳索引,支持:
- "今天发生了什么"
- "上周和张三的对话"
- "3月份的账单"
- 验收:
search_memory("上周", person="张三")能按时间范围过滤返回 - 实现:search_memory() 支持 since/until 参数时间过滤;android_mcp.py search_memory 工具已接入 ✓
[x] S9-03 三种 Memory 统一查询接口
- 工作:
search_memory(query, person?, since?, until?, source_app?)内部并联三种检索: Vector(语义相关)+ Timeline(时间范围)+ Graph(关系链路),结果合并去重 - 验收:复杂查询("张三上个月和我说过什么关于项目的事")能同时命中三种索引
- 实现:android_mcp.py search_memory + semantic_search_memory + embed_memory_messages 三工具统一接口;FTS5关键词 + 时间过滤 + Kimi向量检索并联 ✓
- 工作:
Sprint 10 — Persona 模块(低优先级,phoneuse.md Agent Formula)
目标:实现 phoneuse.md Agent Formula 里的 Persona 组件 说明:Agent = LLM × Tools × Data × Persona,当前 Persona 完全缺失
[✗] S10-01 设计 Persona 数据结构
- 工作:
~/.hermes/persona.yaml存储用户画像: - Preference(语言风格、工作习惯、常用 App)
- Goal(当前项目、优先级)
- Style(回复简洁/详细、中文/英文)
- Relationship(重要联系人列表及关系类型)
- 验收:Hermes system prompt 从 persona.yaml 动态生成
- 实现:persona.py 完成;get_persona/update_persona/generate_system_prompt_fragment;yaml/json自适应 ✓
- 🔬实测2026-06-16 失效:MCP 工具
get_persona()/update_persona('_selftest','phoneuse')均{"error":"name 'EVENT_BUS_DIR' is not defined"}(同 EVENT_BUS_DIR 缺陷)。
- 工作:
[✗] S10-02 实现 Persona 自动更新(从行为推断)
- 工作:从 event bus 的用户行为(常用 App、活跃时间段、常联系人)自动更新 Persona
- 验收:Persona 里的"常用 App"和"重要联系人"能从真实使用数据中提炼
- 实现:infer_from_memory_graph() 从 memory_graph.db 提取高频联系人 top-10;android_mcp.py infer_persona_from_behavior 工具 ✓
- 🔬实测2026-06-16 失效:MCP 工具
infer_persona_from_behavior()→{"error":"name 'EVENT_BUS_DIR' is not defined"}。
[✗] S10-03 Persona 接入 Hermes System Prompt
- 工作:Hermes 启动时加载 Persona,注入到 system prompt 作为背景上下文
- 验收:Hermes 能根据 Persona 调整回复风格和任务优先级判断
- 实现:generate_system_prompt_fragment() 生成 Markdown 片段;android_mcp.py get_persona_prompt 工具 ✓
- 🔬实测2026-06-16 失效:MCP 工具
get_persona_prompt()→[persona error: name 'EVENT_BUS_DIR' is not defined]。
Sprint 11 — Collective Knowledge Network(长期目标)
目标:phoneuse.md 横向层,跨设备分享 App 操作经验 说明:当前完全未实现,属于产品护城河层,排在所有本地功能之后
[x] S11-01 设计云端 Knowledge 上传格式
- 工作:定义上传 schema(只含结构性知识,不含用户数据)
- 验收:格式文档评审通过,隐私字段清单确认
- 实现:cloud_knowledge.py make_knowledge_entry() schema_version/intent/app/app_version/execution_path/success_rate/validated_by;无用户数据字段 ✓
[✗] S11-02 实现本地经验上传客户端
- 工作:Connector 操作成功后,异步上传结构性知识到云端 API
- 验收:成功发送一条微信后,上传记录出现在云端
- 实现:cloud_knowledge.py upload_knowledge();无 API key 时本地缓存 pending_*.json;android_mcp.py upload_operation_knowledge 工具 ✓(需配置 HERMES_CLOUD_KEY 生效)
- 🔬实测2026-06-16 失效:
upload_operation_knowledge(...)与retry_cloud_uploads()均{"error":"name 'EVENT_BUS_DIR' is not defined"}(同 EVENT_BUS_DIR 缺陷,未触及网络)。
[✗] S11-03 实现云端经验拉取(Pull 模式)
- 工作:执行意图前,先查询云端是否有该 App 版本的已验证经验
- 验收:新设备能从云端直接拉取 WeChat hook 配置,不需要本地探索
- 实现:cloud_knowledge.py pull_knowledge()/get_best_execution_path();本地缓存降级;android_mcp.py pull_cloud_knowledge 工具 ✓
- 🔬实测2026-06-16 失效:
pull_cloud_knowledge('wechat','send_message')→{"error":"name 'EVENT_BUS_DIR' is not defined"}。
[ ] S11-04 实现云端 Knowledge 服务端(需独立后端项目)
- 工作:部署收集→去重→验证(N 台交叉验证)→分发管道的后端服务
- 验收:多台设备上传同一 App 经验后,云端正确合并并分发
- 状态:[DEFERRED] 需要独立后端项目,超出当前范围
技术债务 & 维护
[ ] DEBT-01 gRPC protoc codegen 接通(低优先级)
- 说明:AndroidRuntimeServer.kt 的 gRPC 接口已设计,但未跑 protoc 生成代码
- 只有当 Hermes 需要从 Mac 远程控制 Android 时才需要,当前 Termux 本机够用
[x] DEBT-02 approvals.cron_mode 从 deny 改为 auto(中优先级)
- 说明:当前 cron_mode=deny,定时任务里 terminal 命令会被拒绝
- 工作:
sed -i 's/cron_mode: deny/cron_mode: auto/'in config.yaml 后重启 gateway - 验证:config.yaml 已有
cron_mode: auto✓
[x] DEBT-03 notification_monitor.py 到 APK 集成后的过渡删除
- 前置:S1-07 验证稳定
- 工作:从 start_all.sh 彻底移除 notification_monitor.py 相关逻辑
- 验证:notification monitor 启动段已从 start_all.sh 移除;status 输出中对应行已删除 ✓
[x] DEBT-04 Android APK 添加自动重连 EventServer 逻辑
- 说明:APK 启动时如果 event_server.py 还未跑起来,推送会失败,需要带 retry
- 实现:EventServerClient.kt post() 增加 maxRetries=3 指数退避(500ms/1000ms/2000ms);APK 重新编译安装 ✓
覆盖度验证
| phoneuse.md 模块 | 对应任务 | 覆盖状态 |
|---|---|---|
| Layer 2 — Event Collection (Accessibility) | S1-03, S1-05 | ✅ 覆盖 |
| Layer 2 — Event Collection (Notification) | S1-02, S1-04 | ✅ 覆盖 |
| Layer 2 — Event Collection (Intent/Clipboard) | S6-03(系统);APK Intent 未规划 | ⚠️ 部分 |
| Layer 3 — SQLite (WeChat/Telegram/Mail/Notes) | S2, S6-02, S8-04 | ✅ 覆盖 |
| Layer 3 — MMKV / Realm / LevelDB | S6-01;Realm/LevelDB 仍缺 | ⚠️ 部分 |
| Layer 4 — Network MITM | S7 | ✅ 覆盖 |
| Layer 5 — Frida (WeChat/Alipay/Telegram) | S3, S8-02~S8-03 | ✅ 覆盖 |
| Semantic Extraction Engine (统一实体映射) | S8-02~S8-05 Connector 层 | ✅ 覆盖 |
| Personal Memory Graph | S4 | ✅ 覆盖 |
| Vector Memory | S9-01 | ✅ 覆盖 |
| Timeline Memory | S9-02 | ✅ 覆盖 |
| MCP Generic APIs (send/search/create/read) | S5 | ✅ 覆盖 |
| Connector Knowledge Base | S8-01 | ✅ 覆盖 |
| Discovery Sub-agent | S8-07, S8-08 | ✅ 覆盖 |
| Execution Priority Chain | S8-06 | ✅ 覆盖 |
| Persona (Preference/Goal/Style/Relationship) | S10 | ✅ 覆盖 |
| Collective Knowledge Network (云端) | S11 | ✅ 覆盖 |
| Agent Hypervisor 长期目标 | 依赖所有 Sprint 完成 | 🔮 愿景 |
仍有小缺口(可接受):
- APK Intent broadcast 捕获(S6-03 只覆盖通讯录 ContentProvider,Intent 监听未单独规划)
- Realm / LevelDB 读取器(S6-01 只有 MMKV,Realm/LevelDB 可按需补充)
优先级汇总
| Sprint | 核心价值 | 难度 | 周期 |
|---|---|---|---|
| Sprint 1 — APK 事件源打通 | 实时事件(替换 2s 轮询) | 低 | 1-2 周 |
| Sprint 2 — WeChat 深度提取 | 能读消息(现在只有联系人) | 低 | 1 周 |
| Sprint 3 — Frida 基础设施 | 能发消息(只读 → 读写) | 中 | 2-3 周 |
| Sprint 4 — Memory Graph | Agent 记住人和事 | 高 | 3-4 周 |
| Sprint 5 — Semantic MCP | 语义 API(phoneuse.md 核心) | 中 | 依赖 S3/S4 |
| Sprint 6 — 其他数据源 | 覆盖更多 App | 中 | 按需 |
| Sprint 7 — Network MITM | Layer 4 拦截流量 | 高 | 2-3 周 |
| Sprint 8 — Connector 抽象层 | App Connector + Knowledge Base | 中 | 3-4 周 |
| Sprint 9 — Memory 完整实现 | Vector + Timeline Memory | 中 | 2 周 |
| Sprint 10 — Persona 模块 | 用户画像 + 个性化 | 低 | 1-2 周 |
| Sprint 11 — Collective Knowledge | 云端经验共享(护城河) | 极高 | 独立项目 |
推荐执行顺序:Sprint 1 → 2 → 3 → 4 → 8 → 5 → 9 → 7 → 10 → 11