2026-10-09 校注:文中部署目录、服务、版本和验收计数为各段标注日期的历史记录;当前可验证状态见 current-status-2026-10-09,本次未复跑历史测试或读取私有健康/对话数据。

Humon 手机派生上下文 v1

目标

在桌面锁屏、离开或无法观测时,Humon 需要知道用户是否正在另一台设备上活动;但这不能变成通知、截图、位置与应用内容的监控。本层只保留能帮助判断跨设备可用性的最小派生状态,并把断连视为 source unknown,而不是“用户离开”。

权威实现

  • 模块:humon_phone.py
  • 私有配置:~/.config/humon/phone.json,权限 600
  • Observation source:android-phone-derived
  • Schema:humon-phone-derived-v1
  • 默认 TTL:600 秒
  • 正式回滚点:${HOME}/.hermes/backups/humon-v3-pre-phone-derived-20260716-224005

最小权限通道

Termux SSH 使用现有 Tailscale SSH、key/known-host 认证和固定短超时;只调用 battery-status 与短时 accelerometer,原始电量/向量只在内存中解析,最终仅保留 battery band 与 stationary/moving。

ADB 只读取 adb devices 中已经连接的单一设备;永不自动连接、配对或扫描。固定读取 battery、power、window policy,只派生 screen_interactive 与 keyguard_locked。

广权限旧 alaya-phone-mcp.service 不是 Humon 依赖,当前 inactive。Humon 不启动它,也不调用 notification、screenshot、shell 或 control 工具。

允许持久化的固定字段

  • schema_version / observed_at / freshness_seconds
  • reachable
  • screen_interactive / keyguard_locked
  • charging
  • battery_band = unknown|critical|low|normal|high
  • motion = unknown|stationary|moving
  • available_signals

缓存同样只含上述派生字段,原子写入;重复使用同一缓存时 source_ref 不变,因此 observation 自动去重。

写入级禁止字段

android-phone-derived 观察除通用 raw-content denylist 外,额外拒绝:

  • location/latitude/longitude;
  • SSID/BSSID/Wi-Fi/IP/MAC/network/RSSI;
  • app/package/foreground_app;
  • notification、clipboard、contact;
  • screenshot/image;
  • device_id/IMEI/serial/phone_number;
  • exact battery percentage/level/temperature;
  • accelerometer/acceleration/values/steps/step_count。

拒绝时只记录被拒绝的键名,不记录值。

融合边界

只有 observed_at≤600 秒、reachable、screen_interactive=true 且 keyguard_locked=false,手机才能把桌面 away|idle|locked|unknown 改为跨设备 active,activity_type=mobile。motion 单独永远不能改变 availability;任何手机字段都不能把 mood/energy/focus/stress 标为 known。

设备断连时只写 source health unavailable;缓存过期后字段恢复 unknown。Agent/perception context 只返回相同的粗粒度 phone block,过期字段先转成 null/unknown。

验证证据

  • Windows 开发镜像与正式 WSL 运行目录:25 项测试通过,compileall 与定向 Ruff 通过。
  • 覆盖 disabled 不探测、SSH 粗化、原始值不落库、ADB 不自动连接、断连缓存/过期、敏感字段拒绝、跨设备可用性、内在维度 unknown、run_once 和 Agent context。
  • 正式 verification 与 22:45 natural cron 均写入 phone-source-status:reachable=false,其余 null/unknown,source health=unavailable。
  • 当前手机离线:Termux SSH 超时,ADB devices 为空;没有把离线解释为人的 away。
  • 22:45 已达 27 条 natural v3,重复五分钟槽 0。
  • 正式库 privacy_events=0、delivered=0、delivery_eligible=0、ground_truth=0、feedback=0,integrity=ok。
  • /api/perception 返回 phone source_status=unavailable、reachable=false、其余 unknown/null、privacy=coarse-derived-only。
  • 私有配置与 known_hosts 权限均为 600;operational_ready=true,delivery_ready=false。

当前缺口

  • 手机重新在线后需用真实 Termux 输出确认运动传感器名称和 movement 可用率。
  • 只有短时运动类别,没有睡眠、HRV、静息心率或锻炼摘要。
  • 可穿戴接入必须沿用本地派生、逐源授权、TTL、固定 schema、可关闭、不可用即 unknown。
  • 手机源不单独授权主动投递;所有帮助仍 shadow-only。

关联