2026-10-09 校注:文中部署目录、服务、版本和验收计数为各段标注日期的历史记录;当前可验证状态见 current-status-2026-10-09,本次未复跑历史测试或读取私有健康/对话数据。
Humon 自然五分钟槽单写 v1
暴露的问题
原逻辑在 run_once 先读 latest auto,再判断是否同槽。两个进程若同时读到同一个 previous,就可能都通过检查,再以不同 timestamp 写入同一五分钟槽。代码声明了单写,但 SQLite 没有唯一约束。
窗口隐私迁移期间恰好暴露一次真实竞态:
- 同一槽 2 条 auto,相差 4.826 秒;
- 两条都是 availability/activity=idle;
- 生成 2 条 shadow decision;
- 唯一对应的使用行累计 899 秒/3 samples,其中 300 秒/1 sample 属于重复写;
- quality v2 因 close duplicate + duplicate bin 暂时 degraded。
没有情绪/健康/投递误判,但自然节律、使用时长和 shadow 数会被污染,必须修复。
三层防线
1. 跨进程完整周期锁
run_once 由 serialized_collection 包装,data/collection.lock 使用 Linux fcntl,将 observe → context → fuse → observations/state → usage/shadow/quality 的整个周期串行化。runtime 内部锁改为可重入,避免嵌套锁死。
2. SQLite 部分唯一索引
idx_states_v3_auto_user_slot:
UNIQUE(user, CAST(timestamp/300 AS INTEGER)) WHERE source='auto' AND model='Humon-fusion-v3'
即使有旧进程或绕过锁的调用,数据库也不会接受第二条自然 v3。
3. 冲突降级而非自然污染
save_state 使用 INSERT OR IGNORE 并返回是否成功。若 auto 写被唯一索引拒绝:
- record.source 改为
auto-race-deduped; - 保留一条非自然状态供审计;
- 不进入 AppUsage、shadow、quality snapshot 或 baseline;
- query/history/stats 默认排除;
- 关联 observations 因非自然 state 被质量层排除;
- quality 暴露
sampling.race_deduped_samples。
明确 self-report 落在已占槽时仍转 manual,真值保留但不制造自然样本。
历史修正
natural_slot_unique_v1 对每个重复槽保留最早 auto,其余 demote:
- 当前 1 条重复被改为
auto-race-deduped; - 删除 demoted state 的重复 shadow decision;
- 当 date/hour/process 只匹配一个 derived usage row 时,按该进程当时看到的 prior natural gap 回退 sample seconds/count;
- 本次唯一匹配成功:899s/3 → 599s/2;
- 原始第一条 shadow 保留,所以该槽 shadow rows=1;
- 然后创建部分唯一索引。
回滚点:
${HOME}/.hermes/backups/humon-v3-pre-natural-slot-unique-20260717-002907,directory 700 / DB 600。
验证证据
- 42 项测试、Ruff、compileall 通过。
- 合成 race 覆盖 demote、shadow delete、usage rollback、unique-index rejection。
- run_once mock 覆盖 DB conflict → non-natural audit,且 usage/shadow 不执行。
- 基线合成轨迹改为真实独立五分钟槽,662 natural samples 与三个 horizon 仍 ready。
- 正式 unique index present;duplicate natural slots=0;race_deduped states=1。
- 正式 usage correction 599s/2 samples found;race slot shadow rows=1。
- quality=operational-collecting、operational_ready=true、race_deduped counter=1、delivery_ready=false。
- 下一次真实自然 cron 后 natural v3=47、duplicates=0。
- privacy_events=0、delivered=0、delivery_eligible=0、DB integrity=ok。