Files
memind/docs/memind-health-p0-experiment.md
T
john f96fdcb3b9 feat(health): add P0 health channel kernel and encrypted health zone.
Lock health recording behind confirm-only state machines, reject public publishes for the health category, and ship the 14-day experiment Page Data templates with tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 18:04:26 +08:00

574 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MeMind Health P0 前置实验方案(14 天人工实验)
日期:2026-09-02
状态:可执行方案。**不涉及业务代码改动,不碰生产链路。**
上游文档:[memind-health-architecture.md](memind-health-architecture.md) §14
---
## 1. 为什么先做这个实验
在写任何健康平台代码前,必须先验证两件事:
1. **用户会不会持续录入**(依从性)—— 这是产品的生死线。没有连续数据,基线永远不成熟,Event Engine 永远不起作用,整套架构价值归零。
2. **基线偏离是否真的早于主观察觉** —— 这是产品的核心命题。
这两件事**不需要任何平台代码**就能验证。实验成本极低,但能避免在错误方向上投入数月开发。
### 1.1 实验的额外产出(同等重要)
除验证假设外,本实验还应顺带产出三项 P0 开发的必要资产:
| 产出 | 用途 |
|---|---|
| **设备照片校验集** | `health-extraction.test.mjs` 的回归用例,防止换模型后精度回退 |
| **真实偏离阈值** | 标定 O6,替代凭空设定的百分比 |
| **入口摩擦排序** | 决定 H5 与服务号谁是留存主战场 |
---
## 2. 假设与结局指标
### 2.1 主结局(一定可测,决定是否继续)
**H1 依从性**:用户能否在无强制手段下连续 14 天录入晨间血压。
```text
主指标:14 天晨间血压录入完成率 = 实际录入天数 / 14
成功阈值:≥ 3/5 参与者完成率 ≥ 80%(即 ≥ 12/14 天)
警戒线: 若 ≥ 3/5 参与者完成率 < 50%,P0 入口形态必须重新设计
```
### 2.2 次结局(可能无法判定,需预设应对)
**H2 核心命题**:手工基线偏离标记是否早于用户主观察觉。
```text
指标:首次偏离标记日期 vs 用户主观首次察觉日期
成功阈值:≥ 3/5 参与者出现「标记早于主观察觉 ≥ 3 天」
```
**重要风险**:14 天内健康人群可能**完全没有偏离**,导致 H2 无法判定。这是本实验最可能的失败模式,必须提前应对(见 §3.2 招募策略、§7.3 无偏离处理)。
### 2.3 探索性观察(不设阈值,仅记录)
- **H3 摩擦**:不同录入渠道的实际使用比例与放弃点。
- **H4 数据质量**:手输 vs 拍照的一致性;用户是否记错测量时间。
- **H5 联动**:睡眠时长与次日晨间血压是否存在个体内相关。
---
## 3. 参与者
### 3.1 样本量
```text
建议:8–10 人(原方案 5 人对 H2 统计力不足)
最低:5 人(仅能验证 H1,H2 视为探索性)
```
若只能招募 5 人,必须明确:**H1 是主结局,H2 降级为探索性观察**,不以 H2 结果决定项目走向。
### 3.2 招募策略(针对 H2 风险)
单纯招健康人,14 天内很可能零偏离。应**有意纳入更可能出现波动的人群**:
| 优先纳入 | 理由 |
|---|---|
| 血压偏高但未服药(正常高值) | 波动概率高 |
| 作息不规律 / 经常熬夜 | 睡眠-血压联动可观察 |
| 50 岁以上 | 基线漂移概率高 |
| 有服药且近期可能调整 | 药物变化是天然扰动 |
**排除**:
- 服用降压药且血压被严格控制的(波动被药物压平)
- 无法自行完成测量的
- 近期计划手术/住院的
**混合建议**:6 人「可能波动」+ 2–4 人「相对健康」作为对照。
### 3.3 知情同意(必须书面确认)
参与前必须明确告知并留存确认记录:
```text
1. 本实验为产品可行性研究,不提供任何医疗诊断或治疗建议
2. 若测量值异常或身体不适,请立即就医,不要等待实验结论
3. 数据仅用于本次产品研究,不对外提供,实验结束后可要求删除
4. 可随时无理由退出,退出不需要解释
5. 实验期间不会有人替你判断健康状况
```
**特别强调第 2 条**:实验中若出现 SpO₂ < 90%、收缩压 ≥ 180、舒张压 ≥ 110 或明显症状,研究者必须立即建议就医并终止该参与者实验。这是伦理底线,不能因为"要收集数据"而延迟。
---
## 4. 测量规程(数据质量的核心)
这一节是整个实验的关键。「参差不齐」的根源就是测量规程不统一 —— 若此处松散,后面所有基线计算都无意义。
### 4.1 晨间血压(必测,主指标来源)
```text
时间:起床后 1 小时内,且服药前(若有服药)
准备:排空膀胱 → 静坐休息 5 分钟
姿势:坐姿,背有支撑,双脚平放,不交叉腿
袖带:同一侧上臂(固定左或右,全程不换),袖带下缘距肘窝 2–3cm
袖带与心脏同高
测量:连续测 2 次,间隔 1 分钟,记录第 2 次读数
禁忌:测量前 30 分钟内不吸烟、不饮咖啡/浓茶、不运动
记录:收缩压 / 舒张压 / 脉搏 / 实际测量时刻
```
**固定同一侧手臂**很重要 —— 双臂血压可差 5–10 mmHg,换臂会直接制造假偏离。
### 4.2 晚间血压(可选但推荐)
```text
时间:睡前 1 小时内
其余规程同晨间
```
### 4.3 睡眠时长
```text
记录:入睡时间(估计)+ 起床时间 → 计算时长
精度:15 分钟取整即可,不要求精确
若有手表/手环数据:优先用设备数据,并注明来源
```
### 4.4 症状
```text
每日勾选(可多选,无症状则选"无"):
无 / 头晕 / 头痛 / 胸闷 / 心慌心悸 / 乏力 / 气短 / 下肢水肿 / 失眠 / 其他
每个勾选项标注严重度:轻 / 中 / 重
```
固定枚举而非自由文本 —— 否则无法做 cluster 分析(对应架构文档 O1)。
### 4.5 体重(隔日)
```text
时间:晨起排空后,空腹,同一体重秤
着装:尽量一致(如仅内衣)
频率:隔日即可,不必每天
```
### 4.6 扰动因素(每日记录,用于关联分析)
```text
昨日是否饮酒:无 / 少量 / 较多
昨日情绪压力:低 / 中 / 高
用药变化:无 / 新增 / 停用 / 剂量调整(注明)
其他:感冒、发烧、加班、旅行等(自由备注)
```
**这一项是 H5 联动假设的关键。** 没有扰动记录,就无法解释偏离原因。
### 4.7 设备照片(用于建校验集)
```text
请参与者在每次晨测后额外拍一张血压计屏幕照片,通过微信发给研究者。
要求:
- 屏幕完整可见,不要求角度端正(正是要收集"不完美"样本)
- 不同光照、不同角度、有反光的都要,越多样越好
- 若屏幕显示时间,请一并拍进去
用途:作为 P0 拍照识别的回归校验集。照片与其手工录入的数值配对,
形成 (图片 → 正确值) 标注对,可直接用于 health-extraction 测试。
```
**这是本实验最被低估的产出。** 真实设备照片标注集很难获得,而它直接决定 P0 拍照识别能否达到 98% 准确率。照片单独收集,**不进 Page Data**(Page Data 不适合存文件)。
---
## 5. 录入工具
### 5.1 方案:Page Data 匿名问卷页(方案 A)
用现有 `page-data-collect` 能力搭建,**无需任何新代码**。仓库已提供可直接 bind 的模板:
- `templates/health-p0-log.html`(参与者录入)
- `templates/health-p0-admin.html`(研究者口令后台)
对应 SQL、dataset 与 bind 规格在 `health-p0-experiment.mjs`。
选择方案 A(匿名 insert + 口令后台)而非登录方案,理由:**参与者无需注册登录,摩擦最低**。这也顺带测试了「零登录摩擦」下的依从性上限。
```text
参与者页:public 模式,仅 insert
研究者页:password 模式,仅 read
```
参与者用 `participant_code`(如 `P01`–`P10`)区分身份,无需账号。
### 5.2 建表 SQL
```sql
CREATE TABLE IF NOT EXISTS health_p0_daily_log (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
participant_code TEXT NOT NULL,
log_date DATE NOT NULL,
-- 晨间血压(必填)
am_measured_at TEXT NULL, -- 实际测量时刻,如 "07:20"
am_systolic INT NULL,
am_diastolic INT NULL,
am_pulse INT NULL,
-- 晚间血压(可选)
pm_measured_at TEXT NULL,
pm_systolic INT NULL,
pm_diastolic INT NULL,
pm_pulse INT NULL,
-- 睡眠
sleep_start TEXT NULL,
sleep_end TEXT NULL,
sleep_minutes INT NULL,
sleep_source TEXT NULL, -- self_estimate | device
-- 体重(隔日)
weight_kg NUMERIC(5,1) NULL,
-- 症状(JSON 数组,含严重度)
symptoms JSONB NOT NULL DEFAULT '[]'::jsonb,
-- 扰动因素
alcohol TEXT NULL, -- none | light | heavy
stress TEXT NULL, -- low | mid | high
medication_change TEXT NULL, -- none | added | stopped | dose_changed
medication_note TEXT NULL,
other_note TEXT NULL,
-- 元信息
entry_channel TEXT NULL, -- h5_form | wechat_manual | other
photo_sent BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMPTZ NULL
);
CREATE INDEX IF NOT EXISTS idx_p0_participant_date
ON health_p0_daily_log (participant_code, log_date DESC);
```
### 5.3 Dataset 注册
```json
{
"name": "health_p0_daily_log",
"table": "health_p0_daily_log",
"description": "MeMind Health P0 前置实验每日记录",
"actions": ["read", "insert"],
"columns": {
"read": ["id", "participant_code", "log_date", "am_measured_at", "am_systolic", "am_diastolic", "am_pulse", "pm_measured_at", "pm_systolic", "pm_diastolic", "pm_pulse", "sleep_start", "sleep_end", "sleep_minutes", "sleep_source", "weight_kg", "symptoms", "alcohol", "stress", "medication_change", "medication_note", "other_note", "entry_channel", "photo_sent", "created_at"],
"insert": ["participant_code", "log_date", "am_measured_at", "am_systolic", "am_diastolic", "am_pulse", "pm_measured_at", "pm_systolic", "pm_diastolic", "pm_pulse", "sleep_start", "sleep_end", "sleep_minutes", "sleep_source", "weight_kg", "symptoms", "alcohol", "stress", "medication_change", "medication_note", "other_note", "entry_channel", "photo_sent"]
}
}
```
### 5.4 页面绑定
```json
// 参与者录入页
{
"relativePath": "public/health-p0-log.html",
"accessMode": "public",
"datasets": {
"health_p0_daily_log": {
"insert": true,
"read": false
}
}
}
// 研究者查看页(独立文件)
{
"relativePath": "public/health-p0-admin.html",
"accessMode": "password",
"password": "<设置 ≥6 位口令>",
"datasets": {
"health_p0_daily_log": {
"insert": false,
"read": true
}
}
}
```
**注意**:参与者页与研究者页必须是**两个 HTML 文件、各 bind 一次**。同页不能同时「匿名 insert」+「口令 read 全量」(平台硬约束)。
### 5.5 表单设计要点(直接影响 H1)
录入页必须做到**60 秒内完成**,否则依从性数据不可信:
- `participant_code` 首次输入后记住(用 URL 参数传递,如 `?p=P01`,**不用 localStorage**,平台禁止)
- `log_date` 默认今天
- 数值输入用 `type="number"` + `inputmode="numeric"`,唤起数字键盘
- 症状默认选中「无」,多数天一键跳过
- 晚间血压、体重、扰动因素默认折叠,不展开不影响提交
- 提交后立即显示「已记录第 N 天」+ 本人历史晨间血压范围(给即时回报,见 §6.3)
---
## 6. 执行流程
### 6.1 时间线
```text
D-3 ~ D-1 招募、知情同意、发放测量规程、确认设备可用、试录 1 次
D1 ~ D7 基线建设期:每日录入,不做任何偏离反馈
D8 中期分析:手工计算 7 天基线(研究者侧,不告知参与者)
D8 ~ D14 观察期:每日录入,研究者每日手工标记是否偏离(不告知参与者)
D14 盲态访谈(关键:必须在告知任何系统判定前进行)
D15 揭盲、对比、结论
```
### 6.2 每日提醒
由研究者手工发送(不做自动化),固定时间:
```text
早 07:00 「早上好,起床后 1 小时内测量血压,记得静坐 5 分钟。[录入链接]」
晚 21:00 (仅对当日未录入者)「今天还没有记录,方便补录吗?」
```
**同时记录提醒效果**:有多少天是提醒后才录的、有多少天是主动录的。这直接反映真实依从性 —— 若 90% 依赖提醒,说明产品必须有可靠推送机制(而这恰恰是弱项,见架构文档 O5)。
### 6.3 基线建设进度反馈(H1 的关键干预)
用户录了 7 天什么反馈都没有,必然放弃。所以 `cold` 期必须给**非偏离类**的即时价值:
```text
D3 「已连续记录 3 天。你的晨间收缩压目前在 122–128 之间。」
D7 「7 天记录完成。初步基线:118–126 / 72–78。继续记录将开启趋势观察。」
D10 「已记录 10 天,数据完整度 100%。」
```
**注意**:D8–D14 观察期**不得**向参与者透露偏离判定,否则污染 D14 盲态访谈。进度反馈只说「记录了多少天」和「基线范围」,不说「你最近偏高」。
### 6.4 退出处理
参与者中断时,必须记录:
```text
- 中断发生在第几天
- 是否有明确原因(忘记 / 麻烦 / 出差 / 设备问题 / 不想继续 / 其他)
- 是暂停还是彻底退出
```
**中断本身就是最有价值的数据。** 不要试图挽留 —— 挽留会污染依从性测量。
---
## 7. 分析方法
### 7.1 D8 基线计算
对每位参与者,用 D1–D7 的晨间数据计算:
```text
n 有效天数(缺失不补)
mean 均值
std 样本标准差
min, max 极值
p25, p75 四分位
typical 建议表示为 round(p25) – round(p75)
```
**分别计算收缩压与舒张压**,不合并。
若某参与者 D1–D7 有效天数 < 5,标记为「基线不可用」,该参与者 H2 不参与判定(但仍计入 H1)。
### 7.2 D8–D14 偏离标记
每天对晨间收缩压做双重判定:
```text
相对偏差: dev% = (value - mean) / mean × 100%
标准分: z = (value - mean) / std
单日标记条件(满足任一):
dev% ≥ +5% 或 z ≥ +1.5
持续偏离标记(首次偏离日期以此为准):
连续 ≥ 2 天出现同向单日标记
```
**为什么用双重判定**:相对偏差直观但忽略个体变异性;z 分数考虑变异性但小样本下 std 不稳。两者取或,宁可多标记,后续人工复核。
**记录每位参与者的「首次持续偏离日期」**,这是与主观察觉对比的关键值。
同时对睡眠做同样计算(方向相反:`dev% ≤ -15%` 或 `z ≤ -1.5`),用于观察 H5 联动。
### 7.3 无偏离情况的处理(必须预设)
若某参与者 D8–D14 完全无偏离标记:
```text
不算失败,记录为「稳定期」。
处理:
1. 该参与者不参与 H2 主判定
2. 但需确认其 D14 主观回答也是「和平时一样」
→ 若主观也说一样 → 这是一次正确的"真阴性",同样有价值
→ 若主观说"不太一样"但系统无标记 → 这是漏检,必须深挖原因
```
**漏检比误报更值得研究。** 若用户明确感到变化而基线检测不到,说明指标组合或窗口选择有问题 —— 这是本实验最有价值的发现之一。
若 **全部参与者均无偏离**,则 H2 无法判定。此时:
```text
1. H1 结论仍然有效,可据此决定 P0 入口形态
2. H2 需延长观察至 30 天,或扩大样本,或调整招募标准
3. 不得因 H2 无结论就否定整个项目方向
```
### 7.4 计算工具
D8 与 D14 的计算量很小(每人 7–14 行数据),**用 Excel / Numbers 即可**,不需要写代码:
```text
mean: =AVERAGE(range)
std: =STDEV.S(range)
p25: =QUARTILE.INC(range, 1)
p75: =QUARTILE.INC(range, 3)
dev%: =(value - mean) / mean
z: =(value - mean) / std
```
保持手工计算的另一个好处:**逼迫研究者逐个看数据**,容易发现异常模式(如某人明显记错时间、某天数值突变),这是自动化脚本会掩盖的。
---
## 8. D14 盲态访谈脚本
**执行纪律**:访谈必须在**告知任何判定结果之前**完成。研究者不得在访谈中透露「你最近偏高」之类信息,否则 H2 结论无效。
按顺序提问,**不要跳问,不要引导**:
```text
Q1(开放,不提任何指标)
「这两周,你觉得自己的身体状态和平时一样吗?」
→ 记录原话
Q2(仅在 Q1 回答"不太一样"时问)
「大概从哪天开始感觉不一样的?」
→ 记录具体日期或"第几天左右"
→ 这是"主观首次察觉日期"
Q3(不一样的具体表现)
「具体是哪里不太一样?」
→ 记录原话,不要提示选项
Q4(扰动因素回溯,此时才可提具体项)
「这两周有没有出现:失眠、感冒、饮酒增加、情绪压力大、
用药变化、加班或作息改变?」
→ 逐项确认,记录时间范围
Q5(录入体验,H1/H3)
「每天记录这件事,麻烦吗?哪一步最烦?」
「如果没有我提醒,你觉得自己能坚持吗?」
「你更愿意用哪种方式记录:网页表单、微信拍照、还是别的?」
Q6(价值感知)
「这两周的记录,对你有用吗?有用在哪里?」
「如果有个助手能告诉你'最近和以前不一样',你会想用吗?」
Q7(继续意愿)
「实验结束后,你会继续记录吗?为什么?」
```
访谈结束后才可揭盲,告知手工分析结果,并观察其反应(这本身是对 Agent 话术的预演)。
---
## 9. 数据记录模板
### 9.1 参与者台账
| 编号 | 年龄段 | 纳入类型 | 设备型号 | 起止日期 | 晨测完成天数 | 完成率 | 中断天 | 中断原因 | 状态 |
|---|---|---|---|---|---|---|---|---|---|
| P01 | | 可能波动/对照 | | | /14 | | | | 完成/退出 |
### 9.2 基线与偏离结果
| 编号 | 有效基线天数 | SBP mean | SBP std | SBP typical | 首次持续偏离日 | 主观首次察觉日 | 提前天数 | 判定 |
|---|---|---|---|---|---|---|---|---|
| P01 | | | | | D__ | D__ / 无 | | 命中/漏检/真阴性/不可判定 |
### 9.3 依从性明细
| 编号 | 主动录入天数 | 提醒后录入天数 | 未录入天数 | 平均录入耗时 | 主要渠道 |
|---|---|---|---|---|---|
### 9.4 照片校验集
| 照片编号 | 参与者 | 日期 | 手工录入值 | 屏幕是否有时间 | 光照/角度备注 |
|---|---|---|---|---|---|
---
## 10. 决策矩阵:实验结果如何影响 P0
| H1 结果 | H2 结果 | 结论与行动 |
|---|---|---|
| 完成率高 | 命中 | **全速推进 P0**,按架构文档执行 |
| 完成率高 | 无偏离/不可判定 | 推进 P0,但延长 H2 观察至 30 天;P1 引擎暂缓 |
| 完成率高 | 漏检为主 | 推进 P0,但**必须先重新设计指标组合与窗口**再做 P1 |
| 完成率低 | 任意 | **暂停 P0,先解决入口摩擦**:优先做设备自动同步(原 P2 提前),或彻底简化录入形态 |
| 大面积中断 | 任意 | 重新评估产品前提:手动录入路线可能不可行,需以设备接入为第一形态 |
**最重要的判断**:如果 H1 失败(大家坚持不下来),那么再精妙的基线算法都没有意义。此时正确的反应不是「优化算法」,而是**把设备自动同步提到第一优先级**,因为它是唯一能把录入成本降到零的手段。
---
## 11. 与后续开发的衔接
实验结束后应产出四份交付物:
1. **实验结论报告**(含 §9 全部表格 + 决策矩阵结论)
2. **偏离阈值标定值** → 写回架构文档 O6
3. **照片校验集** → 归档为 P0 `health-extraction.test.mjs` 的固定用例
4. **入口形态结论** → 决定 H5 与服务号的主次关系
### 11.1 实验数据的处置
实验用 `health_p0_daily_log` 表与页面在结论产出后:
```text
1. 导出结论所需数据 → 归档
2. 应参与者要求删除其数据
3. 关闭 dataset 的公开访问(private_data_close_page_dataset)
4. 下线两个实验页面
```
**不要**把实验表直接当作 P0 的生产表 —— 字段设计目标不同(实验表是宽表便于人工分析,生产表是原子观测便于聚合)。
---
## 12. 实验本身的风险
| 风险 | 影响 | 对策 |
|---|---|---|
| 14 天内无人偏离 | H2 无法判定 | 招募倾向波动人群(§3.2);预设无偏离处理(§7.3) |
| 提醒污染依从性 | H1 高估 | 分别统计主动/提醒后录入(§6.2) |
| 访谈引导 | H2 无效 | 严格盲态,先访谈后揭盲(§8) |
| 测量规程不统一 | 假偏离 | 规程书面化 + 试录 1 次 + 固定同侧手臂(§4.1) |
| 参与者出现真实健康问题 | 伦理风险 | 预设终止阈值,立即建议就医(§3.3) |
| 样本量过小 | H2 统计力不足 | 争取 8–10 人;否则 H2 降级为探索性 |
---
## 13. 相关文档
- [memind-health-architecture.md](memind-health-architecture.md) — 上游架构设计
- [page-data-api-usage.md](page-data-api-usage.md) — Page Data API
- `skills/page-data-collect/SKILL.md` — 建表与页面绑定规范