Files
mindfulness/spec_kit/overview.md
2026-02-25 17:13:29 +08:00

20 KiB
Raw Permalink Blame History

Spec Kit Overview

本文件用于简短记录当前项目每个 spec 的核心内容摘要,便于快速总览与追踪变更。

Client Bootstrap

  • 目标:初始化正念 APP 客户端工程规范,确保可运行、可切环境、可多语言扩展、目录标准化、可 EAS 打包
  • 核心范围:客户端工程骨架与文档(client/README.md、环境变量约定、i18nCN/EN/ES/PT/TC、推送/小组件/卡片滑动的一期能力约束
  • 主要约定
    • 环境:.env.dev / .env.prod,推荐 EXPO_PUBLIC_ 前缀
    • 语言码:zh-CN/en/es/pt/zh-TW
    • 目录:app/(可选 expo-router+ src/features/services/store/utils 等)+ assets/
    • 打包EAS Builddev/prod bundle id 约定
  • 阶段产物
    • spec_kit/Client Bootstrap/spec.md
    • spec_kit/Client Bootstrap/plan.md
    • spec_kit/Client Bootstrap/tasks.md
  • 已完成编码(阶段性)
    • Expo 工程已在 client/ 初始化,并完成 pnpm install
    • i18n 基座已接入5 份语言资源 + 设备语言优先/设置可切换/持久化 + 入口初始化
    • 推荐 Feed 请求链路增加调试日志(仅开发环境):打印 Feed API 请求头与请求体,便于联调排查
    • 环境变量注入增加调试日志(仅开发环境):打印参与 API_BASE_URL 计算的 EXPO_PUBLIC_* 与最终解析结果,便于定位“打到哪个后端”

Client User Identity

  • 目标:在无账号体系或账号可选的前提下,为客户端建立稳定的 client_user_id,用于与 APNs/FCM 的 Push Token 做绑定,支撑精准推送与 Token 变更更新
  • 关键结论client_user_id 使用**随机 UUID默认 UUID v4**合适;将其视为不透明字符串,不使用可追踪设备硬件标识
  • 阶段产物
    • spec_kit/Client User Identity/spec.md

App Push

  • 目标:实现“每日提醒”推送闭环:首次进入 Onboarding 可选择每日推送次数05可跳过个人主页每日提醒弹窗可改次数/关闭;客户端使用首次生成 UUIDclient_user_id)与后端关联;后端按用户配置定时推送
  • 关键选型:客户端继续使用 expo-notifications;后端使用 Expo Push Service + 定时任务Celery/等价方案)按用户偏好发送
  • 阶段产物
    • spec_kit/App Push/spec.md
    • spec_kit/App Push/plan.md
    • spec_kit/App Push/tasks.md
  • 已完成编码(阶段性)
    • 客户端:新增 client_user_idUUID v4生成与持久化每日提醒次数范围修正为 050 表示关闭)
    • 客户端Onboarding 结束页(每日提醒)在用户选择次数 > 0 时直接触发系统权限申请;授权后获取 Expo Push Token 并调用后端 register/preferences(移除单独的 push 引导页)
    • 客户端Onboarding 问卷完成后“开通推送权限”流程增加 loading 态(完成按钮转圈 + 全页禁用交互,避免重复触发/重复上报)
    • 客户端:个人主页“每日提醒”弹窗移除测试模式强制无权限逻辑,改为真实读取系统权限;并在开关/点击 OK 时同步后端偏好
    • 客户端:新增推送接口封装 client/src/services/pushApi.tstoken 获取、register/preferences/get、自动上报时区与 locale并携带用户画像供后端 Push 模板使用)
    • 后端:新增 Push 数据模型 + Alembic 迁移(push_tokens / push_preferences / push_send_log
    • 后端:新增 Push API/v1/push/register/v1/push/preferences/v1/push/testdev并新增基础限流
    • 后端:实现 Celery 定时任务
      • 每日生成计划(按用户时区在 9:0024:00 均匀分段随机抖动生成 05 个时间点)
      • ETA 发送任务(幂等:同一用户同一天同一 slot 只发一次;用户中途关闭/降次数会跳过)
      • 发送文案复用推荐模块 scene="push"(降风险)
    • 后端:pytest 全量通过27 passed

Project Bootstrap

  • 目标:完成项目仓库初始化与工程约定落地,明确 client/server 结构、dev/pro 环境隔离、MySQL/Redis 资源命名与访问边界
  • 核心范围根目录结构与文档、dev/pro 配置策略、MySQL schema 命名(mindfulness_dev/mindfulness、Redis ACL + key 前缀隔离(dev:*/pro:*
  • 主要约定
    • MySQLprod=mindfulnessdev=mindfulness_dev,统一 utf8mb4 与 snake_case
    • Redis单实例通过 ACL 限制不同用户只能访问对应前缀;应用侧强制 key 使用 dev:/pro: 前缀
    • 安全:真实 IP/账号/密码/Token 不写入仓库,仅提供 .env.example 结构
  • 阶段产物
    • spec_kit/Project Bootstrap/spec.md
  • 近期变更
    • 新增后端镜像构建基础:server/Dockerfileserver/.dockerignore
    • 新增后端镜像打包与推送工作流:.gitea/workflows/server-build.yml(自动递增 semver tag 并推送到 Docker Hub
    • 新增后端蓝绿部署工作流:.gitea/workflows/server-deploy.ymlSSH 上机 + Docker 蓝绿启动 + Nginx upstream 切流 + 健康检查与失败回滚)
    • 后端配置缺失时报错增强:app/core/config.py 将缺失的必填环境变量用中文提示并给出注入方式;补充 server/env.example 与 Docker 运行说明

Onboarding App Shell

  • 目标落地首次进入体验Onboarding 35 页可跳过 + 每日提醒可跳过/可关闭)与主应用壳(点赞/讨厌、收藏夹入口、通用设置入口)
  • 核心范围Onboarding 多页流程、主界面反应操作Like/Dislike、收藏夹、设置页版本、iOS 小组件入口/说明)
  • 阶段产物
    • spec_kit/Onboarding App Shell/spec.md
    • spec_kit/Onboarding App Shell/plan.md
    • spec_kit/Onboarding App Shell/tasks.md

iOS Widget

  • 目标:实现真正的 iOS 桌面小组件WidgetKit Extension展示美观文案并与 App 共享数据
  • 核心范围WidgetKit 扩展、App Group 数据共享、尺寸适配Small/Medium/Large、点击跳转回 App
  • 阶段产物
    • spec_kit/iOS Widget/spec.md
    • spec_kit/iOS Widget/plan.md
    • spec_kit/iOS Widget/tasks.md
  • 近期变更
    • iOS 主 App Bundle ID 已统一为 com.damer.mindfulnessWidget Extension 为 com.damer.mindfulness.emotionwidget
    • 修复 iOS 签名 Team 配置不一致:为主 AppDebug与 Widget ExtensionDebug/Release显式补齐 DEVELOPMENT_TEAM=WS92GPX9H2,避免打包/上传过程中回退到默认 Team 导致显示 “Other Team”
    • iOS 构建号已提升到 2,并将 client/ios/client/Info.plist 改为自动跟随 MARKETING_VERSION / CURRENT_PROJECT_VERSION
    • 推送 entitlements 的 aps-environment 已切到 production(用于 TestFlight/线上包)
    • 清理未接入编译的 WidgetKit 骨架残留:移除磁盘上的 client/ios/MindfulnessWidget/ 文件,并从 client/ios/client.xcodeproj/project.pbxproj 删除对应工程引用(避免 Xcode 显示幽灵文件)
    • 修复 Xcode Archive 偶发显示 “Generic Xcode Archive”在共享 scheme Dear Mama 的 Archive Post-actions 自动补齐 .xcarchive/Info.plistApplicationProperties,并在缺失时补齐 Name/SchemeName + 自检提示(根治 Organizer 无法识别主 App、无法分发/上传 TestFlight 的问题)
    • Widget 名称与描述支持多语言TC/EN默认 ENWidget Extension 增加 Localizable.stringsen.lproj / zh-Hant.lprojEmotionWidget.swift 使用本地化 key 作为 .configurationDisplayName/.description
    • 个人主页弹窗:小工具入口暂时隐藏锁屏小工具说明;桌面小工具引导弹窗标题(繁中/TC更新为“如何加入小工具”(并统一弹窗标题使用该文案);品牌文案改为 Dear Mama(含引导搜索词与 Widget 标题)

Text Wrap

  • 目标:将 Home 与 Widget 的文案换行算法从 UI 中独立成可复用模块,输出稳定、可控、可解释的换行结果(同输入同输出)
  • 核心范围wrapText() 纯函数入口、TC/EN token 口径与索引体系、候选断点生成、DP/Beam 搜索、硬约束/评分/tie-break、溢出与兜底、debug meta 与 Golden Cases
  • 阶段产物
    • spec_kit/Text Wrap/spec.md
  • 已完成编码(阶段性)core-contract核心口径与契约
  • 已完成编码(阶段性)grapheme-segmentationTC 字符簇分割)
  • 已完成编码(阶段性)width-measurement宽度测量与降级
    • 修复measureSliceWidthCached 的切片缓存 key 增加 sliceText hash避免不同文本的相同 (start,end) 发生串缓存
  • 已完成编码(阶段性)breakpoint-candidates候选断点生成与裁剪
    • 变更文件
      • client/src/features/textWrap/breakpoints/types.ts
      • client/src/features/textWrap/breakpoints/enCandidates.ts
      • client/src/features/textWrap/breakpoints/tcCandidates.ts
      • client/src/features/textWrap/breakpoints/filterAndDedup.ts
      • client/src/features/textWrap/breakpoints/generateBreakpoints.ts
      • client/src/features/textWrap/breakpoints/index.ts
      • client/src/features/textWrap/breakpoints/__tests__/generateBreakpoints.test.ts
      • spec_kit/Text Wrap/modules/breakpoint-candidates/plan.md
      • spec_kit/Text Wrap/modules/breakpoint-candidates/tasks.md
  • 已完成编码(阶段性)scoring-tiebreak评分模型与确定性裁决
    • 变更文件
      • client/src/features/textWrap/scoring/types.ts
      • client/src/features/textWrap/scoring/weights.ts
      • client/src/features/textWrap/scoring/lexicons.ts
      • client/src/features/textWrap/scoring/phraseMatch.ts
      • client/src/features/textWrap/scoring/score.ts
      • client/src/features/textWrap/scoring/tieKey.ts
      • client/src/features/textWrap/scoring/index.ts
      • client/src/features/textWrap/scoring/__tests__/scoringTiebreak.test.ts
      • spec_kit/Text Wrap/modules/scoring-tiebreak/plan.md
      • spec_kit/Text Wrap/modules/scoring-tiebreak/tasks.md
  • 已完成编码(阶段性)search-engine-appAPP 搜索器DP + TopK
    • 变更文件
      • client/src/features/textWrap/searchApp/types.ts
      • client/src/features/textWrap/searchApp/topK.ts
      • client/src/features/textWrap/searchApp/constraints.ts
      • client/src/features/textWrap/searchApp/dpTopK.ts
      • client/src/features/textWrap/searchApp/index.ts
      • client/src/features/textWrap/searchApp/__tests__/searchApp.test.ts
      • spec_kit/Text Wrap/modules/search-engine-app/plan.md
      • spec_kit/Text Wrap/modules/search-engine-app/tasks.md
      • client/src/features/textWrap/measure/measureSliceWidthCached.ts
  • 已完成编码(阶段性)search-engine-widgetWIDGET 搜索器Beam Search
    • 变更文件
      • client/src/features/textWrap/searchWidget/types.ts
      • client/src/features/textWrap/searchWidget/topK.ts
      • client/src/features/textWrap/searchWidget/constraints.ts
      • client/src/features/textWrap/searchWidget/beam.ts
      • client/src/features/textWrap/searchWidget/index.ts
      • client/src/features/textWrap/searchWidget/__tests__/searchWidget.test.ts
      • spec_kit/Text Wrap/modules/search-engine-widget/plan.md
      • spec_kit/Text Wrap/modules/search-engine-widget/tasks.md
  • 已完成编码(阶段性)overflow-fallback溢出与兜底
    • 变更文件
      • client/src/features/textWrap/overflow/types.ts
      • client/src/features/textWrap/overflow/ellipsis.ts
      • client/src/features/textWrap/overflow/fallback.ts
      • client/src/features/textWrap/overflow/index.ts
      • client/src/features/textWrap/overflow/__tests__/overflowFallback.test.ts
      • spec_kit/Text Wrap/modules/overflow-fallback/plan.md
      • spec_kit/Text Wrap/modules/overflow-fallback/tasks.md
  • 已完成(阶段性)golden-testsGolden Cases 与性质测试)
    • 变更文件
      • client/src/features/textWrap/golden/fixtures.ts
      • client/src/features/textWrap/golden/__tests__/golden.test.ts
      • spec_kit/Text Wrap/modules/golden-tests/plan.md
      • spec_kit/Text Wrap/modules/golden-tests/tasks.md
  • 已完成编码(阶段性)integrationHome / Widget 接入)
    • 变更文件
      • client/src/features/textWrap/types.ts
      • client/src/features/textWrap/wrapText.ts
      • client/src/features/textWrap/index.ts
      • client/src/features/textWrap/__tests__/wrapText.integration.test.ts
      • spec_kit/Text Wrap/modules/integration/plan.md
      • spec_kit/Text Wrap/modules/integration/tasks.md
    • 接入情况
      • HomeAPP已在 client/app/(app)/home.tsx 接入 wrapText() 渲染 wrappedText(含 \n
      • iOS WidgetWidgetKitApp 侧在写入 widget.dailyReco.v1 缓存时,额外生成 wrapped_text_by_familysmall/medium/large并写入 App GroupWidget 侧按 WidgetFamily 优先读取该字段渲染(保证换行一致且无需在 Extension 内跑 JS
    • 近期变更
      • Widget 接入:client/src/modules/dailyWidgetReco/index.ts 生成 wrapped_text_by_familyclient/ios/情绪小组件/EmotionWidget.swift 按 family 读取;client/app/(app)/home.tsx 前台触发一次“尽力而为”的补齐/刷新
      • Home 排版风格微调:支持 scoringOverrides,在 Home 里对 TC 做“更偏好标点停顿/更好看”的权重与理想宽度微调(不影响默认 v1
  • 目标:实现开屏页(使用 client/assets/images/index/ 图片资源),首次加载展示渐变同意按钮并提供隐私/协议入口
  • 核心范围:开屏 UI、首次同意状态持久化consent.accepted)、点击同意后进入后续 Onboarding/App 流程
  • 阶段产物
    • spec_kit/Splash Consent/spec.md
    • spec_kit/Splash Consent/plan.md
    • spec_kit/Splash Consent/tasks.md
  • 近期变更
    • 启动流程优化:将 Expo Router 初始路由调整为协议页 /(splash)/splash,并在协议页已同意时直接分发到 /(app)/home/(onboarding)/onboarding,避免系统开屏结束后先渲染 index(转圈页)再跳协议页导致的“闪一下”
  • 目标:在客户端首次进入同意页底部补充「隐私协议/用户使用协议」入口,并将协议链接改为由后端托管与按设备语言下发(默认回退 EN
  • 核心范围:后端提供协议链接下发接口(可配置、可多语言);客户端按设备语言请求并展示链接,失败不阻塞“同意并继续”
  • 阶段产物
    • spec_kit/Policy Links/spec.md
    • spec_kit/Policy Links/plan.md
    • spec_kit/Policy Links/tasks.md
  • 已完成编码(任务清单已执行完毕)
    • 后端新增 GET /v1/legal/links(按 Accept-Language 分发,默认回退 EN返回 resolvedLang
    • 后端配置:LEGAL_* 环境变量(server/env.example 已补齐示例;不配置时走内置协议页兜底)
    • 后端新增内置协议内容页:
      • GET /v1/legal/privacy
      • GET /v1/legal/terms
      • GET /v1/legal/support(技术支持页面,提供审核可用的公开支持信息)
    • 客户端新增协议接口封装 client/src/services/legalApi.ts
    • 客户端工程化:新增统一 HTTP 封装 client/src/utils/http.tsbaseURL/超时/JSON/统一错误),并将 legalApi.ts / recoApi.ts 接入
    • 客户端接入两处入口:app/(splash)/splash.tsxcomponents/home/ProfileModal.tsx
    • 变更文件清单
      • server/app/api/v1/legal.py
      • server/app/core/config.py
      • server/app/legal_docs.py
      • server/app/main.py
      • server/env.example
      • server/tests/test_legal_links_unittest.py
      • client/src/services/legalApi.ts
      • client/src/services/__tests__/legalApi.test.ts
      • client/app/(splash)/splash.tsx
      • client/components/home/ProfileModal.tsx
      • spec_kit/Policy Links/spec.md
      • spec_kit/Policy Links/plan.md
      • spec_kit/Policy Links/tasks.md

Card UI

  • 目标:优化卡片页 UI 与交互,支持右上角主题切换与个人主页弹窗,并将喜欢/讨厌改为 icon + 动效
  • 核心范围
    • 系统导航栏右上角两个圆形 icon主题theme.svg/ 我的(my.svg
    • 底部上拉弹窗Sheet统一内容区背景 #FAF3EC,点 X 关闭
    • 主题两种模式:scenery / color(本期最少影响 Home 页面背景),并持久化 ui.theme.mode
    • 喜欢/讨厌按钮:使用 like.svg / hate.svg,喜欢提供“心形填满”强反馈动效(like_filled.svg
    • 每日提醒弹窗:次数 +/-、Push 提醒开关、渐变 Ok 按钮,并持久化设置
  • 阶段产物
    • spec_kit/Card UI/spec.md
    • spec_kit/Card UI/plan.md
    • spec_kit/Card UI/tasks.md
  • 已完成编码(阶段性)
    • 已接入 react-native-svg-transformer + client/metro.config.js
    • 新增 SheetModalThemeModalProfileModal 并在 Home 中接入
    • 新增 DailyReminderModal 并从个人主页弹窗打开
    • Home右上角 icon 按钮、主题切换背景、喜欢/讨厌 icon + 动效
    • 修复:收藏(“我的喜欢”)不展示后端推荐文案的问题——收藏时持久化写入 text 快照,并在 ProfileModal 的 Favorites 页面同时兼容 Mock 与推荐缓存内容回填

User Profile Scoring

  • 目标:将 Onboarding 问卷答案映射为标准化“用户画像 U”并输出硬规则与置信度元信息供推荐/Push 等模块统一复用
  • 核心范围mom_stage离散、emotion_score01 连续、context离散、need离散四维度以及 profile_version/source/generated_at/confidenceV1.1
  • 主要约定
    • 输出结构稳定可版本化,便于规则演进
    • 支持题目可跳过:新增 profile_answered 标记各题是否作答;字段缺失时由推荐算法走“通用值 + 不确定性惩罚”
    • mom_stage 跳过按安全策略视为 unknown用于避免冒犯emotion/context/need 跳过不强行填默认值
    • 置信度 conf_U = 时间衰减 × 作答完整度(答得越少越不确定),用于推送场景降个性化/降风险
    • 硬规则优先于任何分数计算:unknown 仅在“育儿压力且强个性化personalization_power=1”时禁推block_health_medical 全场景硬过滤
  • 测试覆盖:提供“输入题目答案 → 输出用户画像”的回归用例,覆盖字段映射、置信度衰减与硬规则触发(可选但建议)
  • 阶段产物
    • spec_kit/User Profile Scoring/spec.md
  • 已完成编码(阶段性)
    • 客户端 Onboarding 完成时已收集问卷答案并生成用户画像,写入本地存储供推荐/Push/Widget 复用

SuixinTheme

  • 目标:在 Home 现有「风景 / 纯色」主题基础上新增「随心」主题,背景颜色根据用户问卷画像个性化推荐
  • 核心范围:复用既有 Base Theme5 套)+ Neutral1 套),按 need/stage/emotion/confidence 选色并做 session 锁定Theme Lock支持 TC/EN 文案
  • 阶段产物
    • spec_kit/SuixinTheme/spec.md
    • spec_kit/SuixinTheme/plan.md
    • spec_kit/SuixinTheme/tasks.md
  • 已完成编码(全部)
    • 客户端新增第三主题 suixin(随心/Ease与现有主题切换入口一致
    • Home冷启动会话内锁定 Base Theme切换文案时在同主题内线性插值输出纯色背景并持久化 ui.theme.suixin.state
    • i18n新增 theme.suixinTC/EN
    • 测试新增随心模块单测Vitest并通过tsc --noEmit 通过
  • 变更文件
    • client/src/storage/appStorage.ts
    • client/app/(app)/home.tsx
    • client/components/home/ThemeModal.tsx
    • client/src/i18n/locales/all.json
    • client/src/utils/bootSession.ts
    • client/src/features/suixinTheme/palette.ts
    • client/src/features/suixinTheme/colorMath.ts
    • client/src/features/suixinTheme/progress.ts
    • client/src/features/suixinTheme/pickTheme.ts
    • client/src/features/suixinTheme/index.ts
    • client/src/features/suixinTheme/__tests__/suixinTheme.test.ts
    • client/app/_layout.tsx