# 「随心」主题（Suixin Theme）任务清单（tasks）

> 说明：
>
> - 本清单基于 `spec_kit/SuixinTheme/plan.md` 拆分为可执行任务。
> - 执行过程中：完成一项就在对应条目打勾（`[x]`），并补充必要的实现备注/PR 链接（如有）。
> - **当本 tasks 全部完成后**，需要回到 `spec_kit/overview.md` 在 `SuixinTheme` 条目下标记“已完成编码（阶段性/全部）”。

## 0. 准备与基线确认

- [x] **T0.1 确认现有主题切换链路位置与文件**
  - **涉及文件**：`client/components/home/ThemeModal.tsx`、`client/app/(app)/home.tsx`、`client/src/storage/appStorage.ts`
  - **验收**：确认 `ThemeMode` 当前仅 `scenery/color`，并确认 `Home` 背景分支逻辑位置（方便插入 `suixin` 分支）

- [x] **T0.2 确认用户画像可在 Home 获取**
  - **涉及文件**：`client/src/storage/appStorage.ts`、`client/src/features/userProfileScoring/*`
  - **验收**：`getUserProfileScoring()` 在 Home 已可读到 `stage/need/emotion_score/profile_confidence/profile_answered`

## 1. 数据与存储层改造（ThemeMode + suixin state）

- [x] **T1.1 扩展 `ThemeMode` 枚举支持 `suixin`**
  - **涉及文件**：`client/src/storage/appStorage.ts`（类型 + `getThemeMode/setThemeMode` 兼容）
  - **要点**：
    - 新类型：`'scenery' | 'color' | 'suixin'`
    - `getThemeMode()` 读取到未知值时回退 `scenery`（保持兼容）
  - **验收**：TypeScript 编译无类型报错；旧存储值仍可正常读取

- [x] **T1.2 新增本地存储：`ui.theme.suixin.state`**
  - **涉及文件**：`client/src/storage/appStorage.ts`
  - **新增内容**：
    - `type SuixinThemeStateV1`
    - `getSuixinThemeState()` / `setSuixinThemeState()`（建议）
  - **验收**：能读写该 key；结构包含 `base_theme_id/seed/step_index/last_color`

## 2. 「随心」颜色算法模块（纯函数 + 可测试）

- [x] **T2.1 新增 `suixinTheme` 模块目录与色盘常量**
  - **建议路径**：`client/src/features/suixinTheme/`
  - **新增文件建议**：
    - `palette.ts`：Base Theme（5）+ Neutral（1）常量
    - `types.ts`：`BaseThemeId`、`SuixinThemeStateV1`（若不放在 storage）
  - **验收**：色值与 `设计说明文档/个性化背景颜色推荐算法.md` 完全一致

- [x] **T2.2 实现 Base Theme 选择（Theme Picking）**
  - **建议文件**：`client/src/features/suixinTheme/pickTheme.ts`
  - **规则**（必须对齐文档 Hard Rules）：
    - `stage.unknown === 1` → `neutral`
    - `need` 为空 `{}` → `neutral`
    - 否则取 `Object.keys(need)[0]`，未知 key → `neutral`
  - **验收**：不同画像输入下输出主题 id 符合预期

- [x] **T2.3 实现线性 `lerp`（仅线性，禁止 easing）**
  - **建议文件**：`client/src/features/suixinTheme/colorMath.ts`
  - **要求**：
    - `hex ↔ rgb` 转换
    - `lerpRgb(a,b,t)`：\(t\in[0,1]\) clamp
    - 输出标准 `#RRGGBB`
  - **验收**：插值边界 t=0/1 输出正确；中间值可复现、无跳段

- [x] **T2.4 实现 \(t\) 生成（切文案步进 + 往返波形）**
  - **建议文件**：`client/src/features/suixinTheme/progress.ts`
  - **要求**：
    - `N=12` 可配置常量
    - 采用往返波形，避免回卷突跳
  - **验收**：连续 step_index 下 \(t\) 始终在 \([0,1]\)，且相邻变化幅度稳定

- [x] **T2.5（可选增强）按 emotion/confidence 控制“动态增强开关”**
  - **说明**：一期允许先不做亮度微扰，只实现“禁动态开关”
  - **对齐点**：
    - 文档：`emotion_score ≤ 0.2` 禁止任何扰动
    - `emotion_score=null` 视为不确定，同样禁止扰动
  - **验收**：低情绪/不确定时不触发增强分支（一期未实现亮度微扰，默认不启用任何扰动）

## 3. UI：ThemeModal 增加「随心」入口

- [x] **T3.1 ThemeModal 新增第三个主题卡片**
  - **涉及文件**：`client/components/home/ThemeModal.tsx`
  - **要点**：
    - `ThemeMode` 类型同步为包含 `suixin`
    - 新增 `ThemeCard`：`onPress={() => onSelect('suixin')}`
    - 布局改为 3 卡可展示（`flexWrap`/调整 gap/尺寸），避免小屏溢出
    - 预览图占位（可先复用 `theme_color.png` 或新增 `theme_suixin.png`）
  - **验收**：弹窗可见第三项；选中态边框正确；无布局溢出

## 4. i18n：新增主题文案（TC/EN）

- [x] **T4.1 增加 `theme.suixin` 翻译键**
  - **涉及文件**：`client/src/i18n/locales/all.json`
  - **文案建议**：
    - `zh-TW`: `隨心`
    - `en`: `Ease`（语义化命名；如需改音译，后续可替换）
  - **验收**：切换语言后 ThemeModal 的第三项标题正确显示，不出现缺失 key

## 5. Home：随心主题渲染 + 冷启动/切文案计算

- [x] **T5.1 Home 增加 `suixin` 分支并使用 `backgroundColor`**
  - **涉及文件**：`client/app/(app)/home.tsx`
  - **要点**：
    - `themeMode === 'suixin'` 时，不渲染风景图
    - 背景色来自 suixin 状态（`last_color`）或初始化计算结果
  - **验收**：选择随心主题后背景变为算法输出色；切回风景/纯色逻辑不受影响

- [x] **T5.2 冷启动（进程级）计算并锁定 Base Theme**
  - **涉及文件**：`client/app/_layout.tsx`（或新增全局单例模块）、`client/app/(app)/home.tsx`
  - **要点**：
    - 生成一次 `boot_id`（仅内存）用于判断“本次进程首次进入 Home”
    - 首次进入 Home 且 theme=suixin：根据画像选 `base_theme_id` 并初始化 `seed/step_index/last_color`
    - 写入 `ui.theme.suixin.state` 持久化
  - **验收**：同一次运行内多次进入 Home 不重复“冷启动重算”；重启 App 后会重算一次

- [x] **T5.3 切换文案时更新 suixin 颜色（不跨主题）**
  - **涉及文件**：`client/app/(app)/home.tsx`
  - **要点**：
    - 在 `triggerNextContent` 切换 index 后：若 theme=suixin，`step_index += 1` → 计算 \(t\) → `lerp` 得到新 `last_color`
    - 持久化更新 state
  - **验收**：上滑切下一条文案时背景色小幅变化；Base Theme 不变（同一色系内变化）

## 6. 收藏背景记录兼容

- [x] **T6.1 收藏逻辑兼容 suixin**
  - **涉及文件**：`client/app/(app)/home.tsx`（`favItem.background` 写入）
  - **规则**：
    - `suixin` 与 `color` 一致：保存 `hex` 到 `background`
  - **验收**：收藏后在 Favorites 列表缩略卡片可正确显示背景色

## 7. 测试与回归

- [x] **T7.1（推荐）为 suixin 模块补单测**
  - **建议路径**：`client/src/features/suixinTheme/__tests__/`
  - **覆盖点**：
    - `stage.unknown=1` → neutral
    - `need={}` → neutral
    - `need={rest_balance:1}` → rest_balance
    - 往返波形 \(t\) 的边界与范围
    - `lerp` 边界与格式
  - **验收**：测试通过，避免回归

- [x] **T7.2 手动验收（按 spec）**
  - **验收清单**：
    - ThemeModal：三主题可切换，选中态正确
    - 随心：冷启动首次进入 Home 生效；切文案时同主题内变色
    - Hard Rules：unknown / need 跳过 → Neutral
    - 多语言：TC/EN 标题正确
  - **备注**：已完成自动化回归（`vitest` + `tsc`）；如需视觉确认可在模拟器/真机打开 ThemeModal 与 Home 做肉眼验收

## 8. 收尾：overview.md 标记

- [x] **T8.1 tasks 全部完成后更新 `spec_kit/overview.md`**
  - **位置**：`## SuixinTheme` 条目
  - **内容**：补充“已完成编码（全部）”与关键变更文件清单（可选）
  - **验收**：overview 总览可读、可追踪

