女性运行时 × StopWatch 黑客松 Handoff
女性运行时 × StopWatch 黑客松 Handoff
更新日期:2026-08-25
用途:在新会话中继续产品、设计和技术实施。
比赛约束:项目必须在黑客松期间从 0 到 1 实现,不复制现成项目、仓库或 SDK 代码。赛前只做调研、需求、设计规范和探针测试;正式代码在比赛开始后重写。
1. 项目定位
项目暂定名
女性运行时:我怎么又这样了
一句话介绍
一个帮助女性低负担看懂身体规律的轻应用:用户不用填复杂表格,只需对挂脖 StopWatch 说一句话或完成五问,系统将主动感受与 Apple Health 客观数据放入同一条身体时间线,再通过本地知识库生成温和、非诊断的身体观察,并打印一张蓝色单色小贴纸带走。
核心价值
- 不把所有问题归因于经期。
- 不强调“哪里又不舒服”,而是提供可执行的小建议和简短安抚。
- Apple Health 说明身体客观发生了什么;StopWatch 记录用户主观感受到了什么。
- 本地知识库提供可信依据和安全边界,大模型只负责理解、调用工具与口语化表达。
- 产品不是医疗诊断工具。
2. 最终演示故事
- 用户从 StopWatch 首页点击“说一说”。
- 用户说:“下午特别困,还想吃甜的,肩膀有点紧。”
- 系统完成语音转写,并提取困倦、想吃甜食和肩颈不适。
- 记录与 Apple Health 的睡眠、心率、步数等数据进入同一条身体时间线。
- Agent 查询当天身体摘要与本地知识库。
- Web App 展示主观记录、客观背景和温和建议。
- 用户确认后,打印蓝色单色“五行身体观察小贴纸”。
- 用户摇晃 StopWatch 时,可以额外揭晓一张“今日身体提示卡”;这是彩蛋,不阻塞核心流程。
3. 产品功能范围
StopWatch 首页
首页显示三个异形 Icon:
- 说一说:Typeless/语音输入。
- 看看自己:五大基本需求确认。
- 今日身体:今日数据摘要。
五大基本需求
- 困
- 饿
- 渴
- 情绪
- 身体不适
支持简单等级或有/无选择,可以多选,保存为一次完整 checkin。
身体时间线
将两类数据按时间放在一起,但明确标记来源:
- 自动数据:Apple Health。
- 主动记录:StopWatch。
示例:
1 | 07:30 昨晚睡眠 6小时12分 Apple Health |
摇晃彩蛋
- 使用 BMI270 检测明显摇晃。
- 短震后展示一张身体提示卡。
- 有记录时根据当天状态选卡;无数据时使用通用卡。
- 失败或不摇晃不影响记录、摘要和打印。
- 不做塔罗或运势,命名为“身体提示卡”或“今日身体签”。
蓝色身体观察小贴纸
打印机当前只能使用蓝色单色耗材。
五行结构:
1 | 今天的我: |
设计要求:纯蓝与留白;不用灰阶、透明度、渐变;用字号、粗细、边框和间距建立层级;IP 需提供蓝色单色线稿版。
4. StopWatch 设计规格
- 官方真实屏幕:圆形 AMOLED,
466 × 466 px。 - Figma 主画板:
466 × 466 px,单位为 px,不是 mm。 - 物理屏幕圆心:
(233, 233)。 - 仓库参考方案:内部居中
450 × 450 pxUI Frame,位置x=8, y=8。 - 内部 Frame 圆心:
(225, 225)。 - 重要内容建议放在半径
200 px内。 - 普通视觉边界建议不超过半径
209 px。 - 装饰可以延伸到半径
225 px。
素材原则
- 圆、线、按钮、进度条、波形优先由 C++ 绘制。
- IP、插画等复杂内容使用最终显示尺寸的透明 PNG8。
- 不在设备端解析 SVG;SVG/Figma 只作为设计源文件。
- 不导出 2×/3× 大图再让硬件缩放。
- 避免模糊阴影、照片纹理、大面积透明渐变。
- 中文文字不要做成图片。
- 动态元素必须能被一个独立的小矩形框住,矩形外内容进入页面时只画一次。
动画与刷新
- 动画不只限于逐帧:优先代码动画和局部部件动画。
- 录音时间:1fps。
- 波形:5–8fps。
- 等待动画:2–4fps。
- 成功动画:3–6帧,6–10fps,持续不超过1秒。
- IP 动画优先只动眼睛、嘴巴或气泡。
- 待机页面无变化时不刷新。
- 交互结束后尽快降低亮度或熄屏。
- AMOLED 待机尽量使用黑色背景,减少亮色面积。
参考仓库 isalicema/m5-stopwatch-dashboard 只用于理解圆屏安全区、扩大触摸热区、局部刷新和固件/Bridge 分层;不复制其代码。该仓库本身约有 6700 行固件和完整 Mac Bridge,不适合作为比赛起点。
5. 数据架构原则
四类数据
| 类型 | 示例 | 主要来源 |
|---|---|---|
measurement |
心率、HRV、睡眠、步数、腕温 | Apple Health |
checkin |
困、饿、渴、情绪、不适 | StopWatch |
activity |
吃饭、喝水、运动、服药 | StopWatch / HealthKit |
insight |
“睡眠较少时下午更容易困” | 系统推导 |
客观测量与主观感受不能互相覆盖。例如“睡眠6小时12分”和“下午困4/5”是两条事件,只在分析层建立关联。
统一事件模型
1 | { |
防止数据打架
- 每条数据永远保留来源。
- 不使用
metric + time作为唯一键。 - 优先使用
source.system + source_sample_id。 - StopWatch 在本地生成固定
event_id,失败重试时不能重新生成。 - 心率、HRV、睡眠、步数以 Apple Health 为主来源。
- 困、饿、渴、情绪、不适以 StopWatch 为主来源。
- 不同时开启多个长期上传同一累计指标的链路,防止步数、距离、活动能量翻倍。
- 原始事件只追加;结构化视图和每日摘要可以重新计算。
- AI 推导结果不能冒充客观事实。
StopWatch 同步状态
1 | pending → uploading → synced |
服务端应返回逐条 ACK:
1 | { |
6. Apple Health 接入
参考 KKarsyline/Collar_watch 的思想,但比赛期间自行实现,不复制代码。
首版指标:
- 睡眠时长
- 心率
- 静息心率
- HRV
- 步数
- 运动时间
后置指标:腕温、呼吸频率、血氧。
同步规则:
- 使用 HealthKit Anchor 增量读取。
- 上传统一数据接口。
- 服务端返回成功后才提交 Anchor。
- 失败时不推进 Anchor,下次补传。
- 服务端根据源 Sample ID 幂等去重。
- 睡眠可以查询最近48小时完整片段并重新聚合,避免只得到半段睡眠。
待确定:Apple Health 最终由独立 watchOS App、iPhone App、简化上传程序还是比赛 Mock 接入。
7. 本地知识库与 Skill
定位
- 本地知识库保存公共知识、来源、安全边界和提示卡。
- Skill 规定如何查询知识、如何表达以及哪些结论不能推断。
- 用户健康记录不进入公共知识库。
- 首版不用向量数据库,采用确定性标签匹配和规则排序。
Monorepo 结构
1 | packages/body-knowledge/ |
首版知识范围
准备约18–30张卡:
- 困:3张
- 饿/想吃东西:3张
- 渴:2张
- 情绪/压力:3张
- 身体不适:3张
- 女性周期:3张
- 综合自查:1张以上
知识卡示例:
1 | { |
安全边界
- 不提供诊断。
- 不解释异常心率的具体病因。
- 不根据单次数据判断内分泌问题。
- 不把所有情绪和食欲变化归因于月经周期。
- 使用“可能”“同时出现”“可以试试”,不使用“说明你”“一定是……导致”。
- 胸痛、呼吸困难、晕厥、意识异常、持续剧烈疼痛、严重过敏等情况停止普通提示,改为明确就医提醒。
8. 大模型、Function Calling 与 MCP
模型选择
用户计划使用 DeepSeek 或豆包,不使用 OpenAI 作为默认方案。
推荐选择:
- Typeless 已输出文字:只接一个文本模型,DeepSeek 或豆包二选一。
- StopWatch 上传音频:豆包语音识别 + DeepSeek 文本,或全豆包方案。
- 比赛期间不要同时让 DeepSeek 与豆包分析同一条记录。
建议实现供应商抽象:
1 | interface LLMProvider { |
1 | providers/ |
现场通过环境变量切换:
1 | LLM_PROVIDER=deepseek |
必须准备 mock 降级,用预置数据保证现场演示。
Function Calling
适合的工具:
health_now:获取当天紧凑健康摘要。health_timeline:查询一段时间内的客观数据和主动记录。knowledge_search:检索本地知识卡和安全边界。generate_sticker:生成贴纸结构与预览。
不交给模型的内容:鉴权、去重、事件ID、HealthKit Anchor、同步重试、累计指标计算、最终安全拦截、直接打印。
MCP
MCP 不用于 StopWatch 上传,也不代替 REST API。它负责把健康数据和知识库作为可复用的 Agent 工具暴露出去。
1 | apps/mcp-server/ |
即使 DeepSeek 或豆包不原生直连 MCP,也可以在 TypeScript Agent Runtime 中把 MCP 工具转换成 Function Calling Schema,执行工具后再把结果返回模型。
Skill、Function Calling、MCP 分工
| 层 | 责任 |
|---|---|
| Skill | 分析步骤、语气、安全边界、输出格式 |
| Function Calling | 决定当前调用哪些业务工具 |
| MCP | 提供可复用的数据与能力 |
| 本地知识库 | 保存事实卡、来源和规则 |
| REST API | 设备与应用的数据通信 |
9. 代码结构
1 | apps/ |
这里 plugins/ 是团队并行开发的 Feature Modules,不等于 MCP 插件。
10. 非技术团队的插件式分工
用户本人:架构与集成
- 初始化 monorepo。
- 定义
shared-schema与feature-sdk。 - 建立 API 空壳和 Mock 数据。
- 管理环境变量与根配置。
- 负责固件和真实通信。
- 审核与合并 PR。
其他人禁止直接修改共享 Schema、核心 API、固件和根配置。
队友 A:Web App
- 今日摘要。
- 主客观身体时间线。
- 数据卡片。
- 打印入口。
- 仅通过 Mock API 开发。
队友 B:五大需求交互
- 五问选择页面。
- 状态与等级。
- 保存成功反馈。
- 输出固定
BodyCheckinInput。
队友 C:本地知识库
- 知识卡。
- 来源。
- 安全红线。
- 提示卡与贴纸文案。
- 测试输入样例。
队友 D:贴纸与提示卡
- 五行蓝色单色贴纸。
- 圆屏彩色提示卡。
- 单色线稿版。
- HTML/SVG 打印预览。
队友 E:语音与结构化提取
- 接收音频或文本。
- 转写。
- 结构化提取。
- 10组测试语料。
每个模块目录包含:
1 | plugins/<module>/ |
统一约束:一个插件一个分支、一个 PR;不改其他目录;不增加第二套字段;不升级全局依赖;必须提供 Mock、截图和修改清单。
11. API 草案
1 | POST /api/events/batch |
贴纸打印必须由用户显式点击确认,Agent 不得自动执行真实打印。
12. 黑客松优先级
P0:必须完成
- StopWatch 三入口首页。
- 至少一种真实主动记录方式。
- 文本/语音转写和结构化提取。
- Apple Health 至少提供睡眠、心率、步数;若真链路来不及,准备可信 Mock。
- 统一事件结构、来源标记与幂等去重。
- Web App 今日时间线。
- 本地知识卡检索。
- 身体观察输出。
- 蓝色单色小贴纸预览和打印。
- 模型 Mock 降级。
P1:时间允许
- 完整五问。
- 主客观时间关联。
- 卡牌模板匹配。
- 记录编辑。
- 断网队列和自动补传。
- MCP Server。
P2:展示加分
- 摇晃身体提示卡。
- IP 局部动画。
- 更完整睡眠阶段。
- 更多 HealthKit 指标。
- Skill 完整封装。
- 向量检索(比赛后优先)。
13. 实施顺序
- 创建 monorepo、Schema、插件模板和 Mock。
- 先用文本跑通:结构化提取 → 知识检索 → 身体观察 → 贴纸。
- 并行开发 Web、五问、知识卡和贴纸预览。
- 实现统一事件 API 和本地存储。
- 接 StopWatch 真实上传。
- 接 Apple Health 或可靠演示数据。
- 最后加入 MCP、摇晃彩蛋和动画。
14. 当前待确认的技术问题
- Apple Health 最终从 watchOS App、iPhone App、简化上传程序还是 Mock 读取?
- StopWatch 语音是直接 Wi-Fi 上传音频、USB 传 Mac,还是只触发 Typeless?
- Typeless 只负责转文字,还是还负责把文字输入 Web?
- 打印机具体型号、连接方式和接受的数据格式是什么?
- 服务端首版是否采用 TypeScript + SQLite + Drizzle?
- 比赛现场是否有稳定 Wi-Fi?
- 文本模型最终选择 DeepSeek 还是豆包?
- 是否需要在比赛现场真实展示 Apple Health 权限授权和增量同步?
15. 新会话启动提示词
1 | 请阅读这份 handoff,并继续帮助我完成“女性运行时 × M5Stack StopWatch”黑客松项目。 |