# 康康 —— 功能设计 Spec(v1.0)

**日期**:2026-05-25
**状态**:Draft, 已与产品方对齐 §1-§6
**关联**:[CLAUDE.md](../../../CLAUDE.md) 工程前提

---

## 0. 概要

康康是一个 iOS 原生健康影像档案 App,**100% 端侧 AI 推理**,基于 SwiftUI + SwiftData + MLX Swift,目标 6 周交付决赛 demo。本 spec 把原始功能清单收敛为 **方案 B**:核心 5 模块 + Live Activity + 分享摘要,其余 P2/P3 全部 deferred。

**5 大核心模块**

1. 统一拍照(合并原 1.x 异常项快拍 + 2.x 关键报告归档)
2. 文字日记
3. 本地 RAG 问答(结构化检索)
4. 趋势分析(Swift Charts + AI 一句话解读)
5. 影像档案库 C1 列表 + C2 详情(看的一半)

**附加 P1**:Live Activity(demo 杀手锏)、分享文字摘要、首启动 Onboarding、Face ID + 永久删除

---

## 1. 整体架构

### 1.1 模块分层

```
UI 层 (SwiftUI)
   │
   ├─ Tab: Home / Trend / Me
   ├─ Modal Sheet: RecordSheet → UnifiedCaptureFlow / DiaryComposer / AskSheet
   └─ Navigation: ArchiveListView → ReportDetailView
        │
        ▼
*Service 层
   ├─ CaptureService     // 拍照 → VL → draft → commit
   ├─ AskService         // 两段式 RAG
   ├─ TrendService       // 聚合 + AI 解读
   └─ ReportCompareService  // 同类型上一份报告 diff(纯模板,不调 LLM)
        │
        ▼
AIRuntime (actor 单例)
   ├─ LLMSession  (Qwen3-1.7B, 流式)
   └─ VLSession   (Qwen2.5-VL-3B, 单次)
        │
        ▼
Persistence
   ├─ SwiftData (Indicator / Report / DiaryEntry / Asset / ChatTurn)
   └─ FileVault (Application Support/Vault/, .completeFileProtection)
```

### 1.2 模块职责与边界

| 模块 | 干什么 | 不干什么 |
|---|---|---|
| **UI** | View + ViewModel,组织展示 | 不直接调 MLX,不读写文件 |
| **CaptureService** | 拍一张全流程:`UIImage → VL prompt → 结构化 JSON → 存盘 + Indicator/Report` | 不管 UI 状态机 |
| **AskService** | RAG:`query → SwiftData 关键词检索 → 拼 prompt → 流式输出 → 引用回链` | 不管对话历史展示样式 |
| **TrendService** | 按指标名/时间范围聚合数据,生成 Chart 数据点 + LLM 一句话解读 | 不画图表 |
| **ReportCompareService** | 找上一份同类型 Report,逐指标 diff,模板拼装 | 不调 LLM |
| **AIRuntime** | MLX 模型加载/卸载/推理,actor 单例,串行化推理 | 不懂业务 |
| **Persistence** | SwiftData 持久化 + FileVault 原图加密目录 + 永久删除 | 不懂 AI |

### 1.3 强制规则(违反即反 spec)

- **UI 永远不直接调 `AIRuntime`**——必须经过 Service 中转,这样 UI 可注入 mock、可预览
- **`AIRuntime` 必须 actor**——同一时刻只允许一个推理任务,MLX 共享显存,并发会 OOM
- **`*Service` 不直接读写 SwiftData 主上下文**——传入 `ModelContext` 或走 ServiceLocator
- **B3 写,C2 读,不要合并主框架**——B3 是 draft 编辑(写入路径),C2 是 detail 浏览(读取路径)

---

## 2. AI 链路

### 2.1 `AIRuntime` 接口

```
康康/AI/
├── AIRuntime.swift          // actor 单例,推理串行化
├── ModelStore.swift         // 模型路径管理 + 下载 + bundle 旁路
├── LLMSession.swift         // Qwen3-1.7B 文本生成,流式
├── VLSession.swift          // Qwen2.5-VL-3B 图像理解,单次
└── Prompts/
    ├── VLExtraction.swift   // 拍照解析(含 few-shot)
    ├── KeywordExtraction.swift  // RAG 第一步
    ├── ChatRAG.swift        // RAG 第二步
    └── TrendNarrative.swift // 趋势一句话解读
```

```swift
actor AIRuntime {
    static let shared = AIRuntime()

    enum Status { case notReady, downloading(Double), loading, ready, error(String) }
    private(set) var status: Status = .notReady

    func prepare() async throws
    func generate(prompt: String, maxTokens: Int) -> AsyncThrowingStream<TokenChunk, Error>
    func analyze(image: UIImage, instruction: String) async throws -> String
    var lastDecodeRate: Double { get }
}

struct TokenChunk {
    let text: String
    let decodeRate: Double
}
```

### 2.2 模型分发

| 项 | 决策 |
|---|---|
| 模型来源 | HuggingFace `mlx-community/Qwen3-1.7B-4bit` + `mlx-community/Qwen2.5-VL-3B-Instruct-4bit` |
| 体积 | LLM ~1.0GB + VL ~2.0GB ≈ 3GB |
| 存储 | `Application Support/Models/`,`URLSession.downloadTask` + 断点续传 |
| 首启动 | 启动屏 → 隐私承诺 → "下载模型"页(进度 + WiFi 提示) → 主界面 |
| 旁路 | `ModelStore.seedModelsFromBundle()`,demo 现场预装机用 |
| 模型缺失 | App 可启动,AI 入口显示"模型未就绪,前往下载" |

### 2.3 VL Pipeline:拍一张统一流程

```
拍照 (UIImage)
   │
   ▼ Step 1 预处理 (CaptureService)
   - 缩放到 ≤ 1024 长边
   - 写 Vault 作为 Asset(加密)
   │
   ▼ Step 2 VL 解析 (AIRuntime.analyze)
   - VLExtraction prompt 要求输出 JSON
   - 期望 { kind: "single"|"report", items: [...], summary: "..." }
   │
   ▼ Step 3 解析容错
   - JSONDecoder + 宽松正则兜底
   - 失败 → A2/B3 字段为空,提示"识别不完整,请手动补充"
   │
   ▼ Step 4 确认页
   - kind=single → A2ConfirmView(单项 + 一句话)
   - kind=report → B3MetaView(指标列表 + 整体摘要,异常优先)
   - 所有字段可编辑
   │
   ▼ Step 5 保存
   - draft → commit,事务写入 Indicator + Report + Asset
```

**VL prompt 要点**
- 明确"只输出 JSON,不要解释"
- 带 2 个 few-shot 示例(单项 + 多项)
- 异常状态由 VL 基于参考范围直接判断
- **不能让用户卡在错误屏**——失败回退到手动录入

### 2.4 RAG:结构化检索 + LLM 生成(不做 embedding)

```
用户问句
   │
   ▼ Step 1 关键词抽取 (Qwen3-1.7B, ~50 token, <1s)
   { indicators: [...], time_range: {days: 90}, intent: "trend"|"value"|"diary" }
   │
   ▼ Step 2 SwiftData 检索 (AskService)
   - 按 indicators 模糊匹配 Indicator.name
   - 按 time_range 过滤 capturedAt
   - intent=diary 时检索 DiaryEntry.content
   - 返回 ≤ 10 条 + 引用 ID
   │
   ▼ Step 3 拼 ChatRAG prompt
   - System: 不诊断、不建议就医、只描述数据
   - Context: 检索结果, 每条编号 [1]-[n]
   - User: 原始问句
   │
   ▼ Step 4 流式生成 (LLMSession.generate)
   - UI 打字机效果
   - 顶部小字: "本机推理中 · 24.3 tok/s"
   │
   ▼ Step 5 引用回链
   - [1][2] 后处理为可点击 Pill
   - 点击 → 跳 Indicator/Report C2 详情
   - 整轮存 ChatTurn(referencedIDs + decodeRate)
```

**Step 1 失败回退**:近 30 天全表扫描,不卡死。
**Step 5 跨页跳转**:Report 引用走 ReportDetailView,Indicator 引用走 Trends 高亮该点。

### 2.5 Live Activity

| 项 | 决策 |
|---|---|
| 触发 | VL 推理 / RAG 生成开始 |
| 显示 | "Qwen2.5-VL · 24.3 tok/s" / "本机问答中 · 22.1 tok/s" |
| 实现 | ActivityKit + WidgetExtension target,`AIRuntime.lastDecodeRate` 每 0.5s `Activity.update` |
| 结束 | 完成后保留 2s "已完成 · 0.8s" 再 dismiss |
| 真机限定 | 模拟器不支持,W5 末预留 1d 真机调试 |

---

## 3. 数据流与数据模型

### 3.1 SwiftData @Model 全集

```swift
@Model final class Indicator {
    var name: String
    var value: String          // 字符串,允许 ">10" "阴性" 等非数值
    var unit: String
    var range: String
    var statusRaw: String      // "high" | "low" | "normal"
    var note: String?
    var capturedAt: Date

    var report: Report?        // 反向关系,nil 表示单项快拍
    var asset: Asset?
    var pinned: Bool = false   // C2 "关联到趋势" 置 true
}

@Model final class Report {
    var title: String
    var typeRaw: String
    var reportDate: Date
    var institution: String?
    var note: String?
    var summary: String?       // VL 100 字摘要
    var pageCount: Int
    var createdAt: Date

    @Relationship(deleteRule: .cascade, inverse: \Indicator.report)
    var indicators: [Indicator] = []
    @Relationship(deleteRule: .cascade)
    var assets: [Asset] = []
}

@Model final class DiaryEntry {
    var content: String
    var createdAt: Date
    var tags: [String] = []    // VL/LLM 抽取
}

@Model final class Asset {
    var relativePath: String
    var mimeType: String
    var bytes: Int
    var createdAt: Date
}

@Model final class ChatTurn {
    var question: String
    var answer: String
    var referencedIndicatorIDs: [String]
    var referencedReportIDs: [String]
    var createdAt: Date
    var decodeRate: Double
}
```

### 3.2 SwiftData migration

- **W2-W4**:破坏性迁移,改 schema 就删模拟器沙盒。不要写 `VersionedSchema`
- **W5 起**:冻结 schema。需要改 → 写 `SchemaMigrationPlan`,只允许加字段
- **demo 翻车**:启动检测不兼容 → 弹"数据格式更新,需重建" → 删库重启。**绝不静默丢数据**

### 3.3 FileVault

```swift
final class FileVault {
    static let shared = FileVault()
    private let vaultURL: URL  // Application Support/Vault/

    func writeJPEG(_ image: UIImage, quality: CGFloat = 0.85) throws -> (relativePath: String, bytes: Int)
    func loadImage(relativePath: String) throws -> UIImage
    func remove(relativePath: String) throws
    func wipe() throws
}
```

- 目录 `.completeFileProtection`,iOS 硬件级加密
- 不做版本管理、不做去重、不做缩略图缓存(YAGNI)
- 屏幕锁定时文件不可读 → AI 入口本来就由 Face ID 拦,业务上不冲突

### 3.4 拍照→保存时序

```
User → UI(B2Scan) → CaptureService → AIRuntime → Persistence
  │     openCamera
  │     ◄── images[]
  │     analyze(images)
  │                      writeJPEG × N
  │                      ─────────────────────────► Assets stored
  │                      analyze(image1) ──► MLX VL
  │                      ◄── JSON
  │                      (repeat for img2…)
  │     ◄── draft (Report + Indicators in-memory)
  │  edit + save
  │                      commit ──────────────────► Report + Indicators
  │     ◄── reportID
```

- N 页 VL 推理**串行**(AIRuntime 串行化),UI 显示 "第 k/N 页解析中" + 取消按钮
- draft 阶段 SwiftData 未提交,用户取消则 Asset 一并回滚

---

## 4. UI 改造与新建清单

### 4.1 现有视图改造

| 文件 | 改造 | 工作量 |
|---|---|---|
| `RootView` | RecordSheet 加"问问看";首页常驻"问问看"入口 | 0.5d |
| `HomeView` | `@Query` 接真数据,时间线 5 条,"今日摘要"接 `TrendService.dailyDigest()`,影像档案入口数量 | 1.5d |
| `Quick/A1Viewfinder` | 改用 `VNDocumentCameraView` 单张模式 | 0.5d |
| `Quick/A2Confirm` | 接 Indicator draft,字段可编辑,显示一句话解读 | 1d |
| `Quick/A3Batch` | **复用为整份报告指标列表**,异常优先 | 1d |
| `Quick/QuickCaptureFlow` | 改为 `UnifiedCaptureFlow`,kind 分叉 | 1d |
| `Archive/B1Guide` | **砍** | -0.5d |
| `Archive/B2Scan` | 改用 VNDocumentCameraView 多页 | 0.5d |
| `Archive/B3Meta` | 接 Report draft + AI 摘要 + 共用 A3 指标列表 | 1d |
| `Archive/B4Progress` | "第 k/N 页"+ 取消,绑 AIRuntime 队列 | 1d |
| `Trends/TrendsView` | 全新(见 4.2) | 3d |
| `Me/MeView` | 模型管理 + Face ID + 永久删除 + 关于 | 2d |
| `Record/RecordSheet` | 四入口 | 0.5d |
| `Models/Models.swift` | 加 Asset / ChatTurn + 字段 | 0.5d |

### 4.2 新建视图

#### `Features/Capture/UnifiedCaptureFlow.swift`(P0,1d)
状态机 View,根据 `CaptureService` 状态切换 Camera → Progress → A2 / B3。

#### `Features/Ask/AskSheet.swift`(P0,2d)
- Modal sheet, fraction(0.9)
- 顶部:3 个动态推荐问题 chip
- 中部:对话流(`ChatTurn` 气泡)
- AI 流式打字机 + 顶部小字 tok/s
- 引用 `[1][2]` → Pill → 跳源
- 底部输入框 + 发送
- **不做**:多轮上下文连续追问(每问独立 RAG)

#### `Features/Trends/TrendsView.swift`(P0,3d)
- 顶部横向 chip:指标(从 pinned + 高频 Indicator.name 去重)
- 时间范围 segmented:3M / 6M / 1Y / 全部
- Swift `Chart`:折线 + 参考范围 `RuleMark` 条带 + 异常点高亮
- 点 tap → C2 详情
- 下方 AI 解读卡片(`TrendNarrative`)

#### `Features/Archive/ArchiveListView.swift`(P0,2d)—— C1
- `@Query` 全部 Report,按 `reportDate` 年份分组
- 顶部分类 chip:全部 / 体检报告 / 化验单 / 影像报告 / 处方
- 卡片:左缩略图 + 右(标题 + 异常 chip + 日期 + 机构)
- 入口:HomeView "我的报告档案" 卡 → push

#### `Features/Archive/ReportDetailView.swift`(P0,2d)—— C2
- 三 Tab Picker:原图 / 解读 / 指标
- **原图 Tab**:`TabView(.page)` 翻页,点击放大,长按保存到相册(需相册权限)
- **解读 Tab**:数字摘要(`indicators.count` / 偏高 / 偏低 / 正常)+ `Report.summary` + **对比上次区块**
- **指标 Tab**:`Report.indicators`,异常优先
- 底部两按钮:
  - **关联到趋势** → 本报告 `Indicator.pinned = true` 批量更新
  - **重新解读** → `CaptureService.reanalyze(report:)` 重跑 VL
- 其他入口:ChatTurn 引用 / Trends 数据点 / Home 时间线

#### `Features/Me/MeView.swift`(P1,2d)
1. 模型状态:Qwen3-1.7B / Qwen2.5-VL-3B 状态、占用空间、上次速度
2. 隐私:Face ID Toggle(`@AppStorage`)、永久删除(二次确认)
3. 数据:导出文字摘要(`UIActivityViewController`)
4. 关于:版本 + 模型许可证

#### `Features/Onboarding/OnboardingFlow.swift`(P1,2d)
3 页:隐私承诺 → 模型下载(进度 + WiFi 提示) → 完成。`@AppStorage("onboarded")` 记录。

#### `LiveActivity/CaptureActivity.swift` + WidgetExtension target(P1,2d)
- `CaptureActivityAttributes`: modelName / status / decodeRate / elapsedMs
- 锁屏 + 灵动岛 compact/expanded
- AIRuntime 推理时 start/update/end
- 真机限定

### 4.3 服务层文件

```
康康/AI/                          [7.5d]
├── AIRuntime.swift               2d
├── ModelStore.swift              1d
├── LLMSession.swift              1d
├── VLSession.swift               1d
└── Prompts/                      2.5d
    ├── VLExtraction.swift
    ├── ChatRAG.swift
    ├── KeywordExtraction.swift
    └── TrendNarrative.swift

康康/Services/                    [4.5d]
├── CaptureService.swift          1.5d
├── AskService.swift              1.5d
├── TrendService.swift            1d
└── ReportCompareService.swift    0.5d

康康/Persistence/                 [1d]
├── FileVault.swift               0.5d
└── PermanentDelete.swift         0.5d

康康/Security/                    [0.5d]
└── AppLock.swift                 0.5d
```

### 4.4 工作量

| 类别 | 估算 |
|---|---|
| 现有改造 | ~13d |
| 新建视图(含 C1/C2 +4d) | ~16d |
| AI 层 | ~7.5d |
| Services 层(含 ReportCompare +0.5d) | ~4.5d |
| Persistence / Security | ~1.5d |
| **纯开发** | **~42.5d** |
| 联调 / Bug / polish | ~7.5d 缓冲 |
| **总计** | **~50d ≈ 6 周** |

任何一项延期 > 1d,按 §6.R7 砍 P1 不动 P0。

---

## 5. 6 周时间表

### W2(本周,5/25-5/31)—— AI 跑通 + Schema 重建
- MLX SPM 引入 + Xcode target
- `AIRuntime` actor + `prepare()` + `generate()`
- `LLMSession` 跑通 Qwen3-1.7B 加载 + 文本生成
- `ModelStore` 路径管理 + bundle 旁路(下载延后到 W6)
- `Models/Models.swift` 新增字段 + Asset / ChatTurn
- 删模拟器沙盒确认 Schema 重建
- `FileVault` 写/读/删测试图

**里程碑**:debug 按钮点击控制台打印 LLM 流式输出 + 速度
**验收**:decode ≥ 15 tok/s,无 OOM
**红线**:跑不通周五前换 llama.cpp

### W3(6/1-6/7)—— 日记 + 基础 RAG
- `DiaryComposer` 接 RecordSheet
- `AskSheet` 打字机 UI + 流式
- `AskService` 两段式 RAG:`KeywordExtraction` → SwiftData → `ChatRAG`
- 引用 `[1][2]` → Pill(目标视图可 stub)
- `ChatTurn` 持久化

**里程碑**:写 3 条日记 → 问"我最近写了什么" → 带引用回答
**验收**:首 token < 2s,引用 ID 匹配
**红线**:JSON 抽取失败率 > 30% → 加 few-shot 或换 prompt

### W4(6/8-6/14)—— VL + 统一拍照 + C1
- `VLSession` 跑通 Qwen2.5-VL 加载 + 单图推理
- `VLExtraction` prompt(few-shot + JSON)
- `CaptureService.analyze` → draft → commit
- `UnifiedCaptureFlow` 状态机
- A1/B2 改 `VNDocumentCameraView`
- A2/A3/B3/B4 接真数据
- **W4 末:`ArchiveListView` C1**(分类 + 年份分组)

**里程碑**:三张真化验单 → 70% 字段自动填好;档案列表可见所有报告
**验收**:VL 单页 < 8s,JSON 失败有可见兜底
**红线**:VL > 15s 或失败率 > 40% → 降级 Vision OCR + Qwen3 文本后处理

### W5(6/15-6/21)—— C2 + Trends + 隐私 + Live Activity
- **`ReportDetailView` C2** 三 Tab + 关联到趋势 + 重新解读
- **`ReportCompareService`** + C2 解读 Tab "对比上次"
- `TrendService` + `TrendsView`(Swift Charts + AI 解读)
- `HomeView` 接 `@Query` 真数据 + 时间线 5 条
- `TrendService.dailyDigest()` 接首页摘要卡
- `AppLock` Face ID 启动锁
- `PermanentDelete` 接 Me 页
- WidgetExtension target + `CaptureActivity`
- **真机调试 Live Activity**

**里程碑**:C1 → C2 三 Tab → 对比上次 → 关联到趋势 → Trends 上看到新指标;拍照灵动岛滚 tok/s
**验收**:Charts ≥ 3 个指标各 ≥ 6 点;Live Activity 锁屏可见
**红线**:Live Activity 周三前调不通 → 降级 App 内顶部条

### W6(6/22-6/28)—— 首启动 + Me + Polish + Demo
- `OnboardingFlow`(隐私承诺 + 模型下载 + 完成)
- `ModelStore` 真实 URLSession 下载 + 续传 + 进度
- `MeView`(模型状态 + 隐私 + 关于)
- 9.4 分享文字摘要
- 所有空状态插画 / 文案
- `#if DEBUG` 种子数据(12 份报告)
- 真机录 3 分钟 demo 视频(含 Live Activity)
- PPT 5 页核心(按卖点排序)

**里程碑**:零安装到首问答 < 5 分钟;demo 视频成片
**验收**:评委 iPhone 跑得动(提前预拷模型)
**红线**:W6 不再加新功能

### 每周日 retro 决策树

```
本周 P0 全完成?
├─ 是 → 进下周
└─ 否,延期 > 2d
       → 砍下周 1 项 P1
         砍顺序:Live Activity → Onboarding 简化 → 分享摘要 → Me polish
         绝不动:C1 / C2 / 对比上次 / 统一拍照 / AskSheet / Trends / Face ID
```

---

## 6. 风险与回退预案

### R1 · MLX 跑不通 / 速度太慢 🔴 致命
**信号**:W2 周五,decode < 10 tok/s 或首 token > 5s,OOM
**回退**:① 更小量化 → ② llama.cpp + GGUF(失 SME2 卖点)→ ③ Qwen2.5-0.5B
**预防**:W2 第一天就跑通;iPhone 15 Pro+ 基线

### R2 · VL 准确率不够 🔴 致命
**信号**:W4 中,5 张真化验单 < 60% 字段正确;频繁残缺 JSON
**回退**:① 加强 few-shot 到 4-5 个 → ② 降级 Vision OCR + Qwen3 文本后处理(失"VL"故事但保识别)→ ③ Demo 只用已知能解析的图
**预防**:W3 末准备 5-10 张真单做回归集;A2/B3 必备兜底文案

### R3 · Live Activity 真机调不通 🟠 高
**信号**:W5 末,Capability/证书问题,模拟器没法测
**回退**:① 只保锁屏不要 App 内顶部条 → ② 整个砍,改 App 内顶部 `safeAreaInset` 粘性条 → ③ Demo 视频后期加字幕
**预防**:W5 周一建好 target

### R4 · SwiftData migration 翻车 🟠 高
**信号**:Schema 编过但启动崩 / cascade 误删
**回退**:W5 前删沙盒;W5 后 `VersionedSchema` 只加字段;demo 翻车显式弹窗"重建",绝不静默丢数据
**预防**:每次改 @Model 重启验证;Schema 改动 W2-W4 集中,W5 冻结

### R5 · 3GB 下载体验灾难 🟠 高
**信号**:demo 现场装包后下载 30 分钟还没好,中断不能续
**回退**:① demo 用预拷模型设备 + `seedModelsFromBundle()` → ② 分两步下(先 LLM 后 VL)→ ③ 视频备份
**预防**:W6 在 2 台 demo 机断网测试

### R6 · 健康话术翻车 🟡 中
**信号**:LLM 输出"你应该……""建议就医"
**回退**:System prompt 末尾追加禁令;AskService 后处理过滤诊断关键词;启动屏永久免责小字
**预防**:W3 RAG 跑通后立刻做 20 条危险问题安全测试,写进单元测试

### R7 · 时间不够 🟡 中
**信号**:某周日 P0 还有 > 1d 没完成
**回退顺序**:Live Activity → Onboarding 简化 → 分享摘要 → Me polish
**绝不砍**:C1/C2、对比上次、统一拍照、AskSheet、Trends、Face ID
**预防**:每周日 retro

### R8 · 评委 iPhone 不支持 SME2 🟡 中
**信号**:iPhone 14 非 Pro 装包,速度比预期慢
**回退**:不依赖评委设备,自带 iPhone 15 Pro / 16 Pro 演示
**预防**:W6 准备 2 台 A17/A18 demo 机

### 风险红绿灯仪表盘

| 风险 | W2 | W3 | W4 | W5 | W6 |
|---|---|---|---|---|---|
| R1 MLX | 🔴 | 🟡 | 🟢 | 🟢 | 🟢 |
| R2 VL | — | — | 🔴 | 🟡 | 🟢 |
| R3 Live Activity | — | — | — | 🔴 | 🟡 |
| R4 Migration | 🟡 | 🟡 | 🟡 | 🟠 冻结 | 🟢 |
| R5 模型下载 | — | — | — | 🟡 | 🔴 |
| R6 医疗话术 | — | 🟡 | 🟡 | 🟡 | 🟢 |
| R7 P0 进度 | 🟡 | 🟡 | 🟠 | 🔴 | 🟡 |
| R8 demo 设备 | — | — | — | — | 🔴 |

每周日 retro 显式确认当周"关键"项:**通过 / 需补救 / 触发回退**。

---

## 7. 非目标(明确不做)

写代码时如果想加,先回这里看一眼:

- ❌ 医疗诊断、剂量推荐、急诊判断、医生预约
- ❌ 连拍模式(1.6)
- ❌ AES 自实现 / 截屏黑屏防护(走 iOS 系统级)
- ❌ 加密 ZIP 导出(9.1-9.3)——只留 9.4 文字摘要
- ❌ 多页 PDF 自写透视校正(VisionKit 白送)
- ❌ 用药提醒、复检提醒、体检周年提醒(11.x)
- ❌ 语音输入(12.x)
- ❌ 多指标相关性、聚类(13.x)
- ❌ 暗黑模式、主题色切换(14.x)
- ❌ 多 profile / 家庭成员(15.x)
- ❌ AI 模型升级 in-app(17.x)
- ❌ iCloud 同步(18.x,与"100% 本地"冲突)
- ❌ Widget / Home Screen 小组件(19.x;Live Activity 不算)
- ❌ 社交、广告、内购、账号系统

**例外加回**:报告对比 16.1(P0,已加回,见 §4.2 C2 + §5 W5)

---

## 8. 评委 PPT 卖点排序

写每个功能时记住为什么这么做:

1. **影像档案系统**(统一 VL 拍照 + C1/C2 归档库)— 核心创意
2. **100% 本地 + SME2 加速** — 技术亮点
3. **本地 RAG 长期记忆** — 端侧不可替代性
4. **隐私三件套**(系统级 file protection + Face ID + 永久删除)— 信任建立
5. **AI 趋势解读 + 对比上次** — 长期价值
6. **Live Activity 实时 tok/s** — 现场记忆点

每写一个功能,问自己:这条提升了上面哪一项?都没有就别做。

---

## 附录 · 与原始功能清单的映射

| 原编号 | 状态 | 落地位置 |
|---|---|---|
| 1.x 异常项快拍 | **合并** | UnifiedCaptureFlow(kind=single) |
| 1.2 智能取景框 | **砍** | VNDocumentCameraView 取代 |
| 1.6 连拍模式 | **砍** | YAGNI |
| 2.x 关键报告归档 | **合并** | UnifiedCaptureFlow(kind=report) |
| 2.1 多页扫描 | 改造 | VNDocumentCameraView 多页 |
| 2.6 原图加密 | 改造 | FileVault `.completeFileProtection` |
| 3.x 自然语言日记 | P0 | DiaryComposer + DiaryEntry |
| 4.x AI 问答 | P0 | AskSheet + AskService(结构化 RAG) |
| 4.4 流式输出 | P0 | LLMSession + AskSheet 打字机 |
| 5.x 趋势分析 | P0 | TrendsView + TrendService + Swift Charts |
| 6.1-6.2 本地 + 离线 | 自然结果 | MLX + 无网络依赖 |
| 6.3 数据加密 | 改造 | `.completeFileProtection`(系统级) |
| 6.4 Face ID | P0 | AppLock |
| 6.5 截屏防护 | **砍** | iOS 无官方 API |
| 6.6 永久删除 | P0 | PermanentDelete |
| 7.x 首页 | P0(已有骨架) | HomeView 接真数据 |
| 8.x 模型管理 | P1 | MeView |
| 9.4 分享文字摘要 | P1 | MeView "导出" |
| 9.1-9.3 加密 ZIP 导出 | **砍** | |
| 10.x 引导 | P1(简化) | OnboardingFlow 3 页 |
| 11.x 提醒 | **砍** | |
| 12.x 语音 | **砍** | |
| 13.x 进阶趋势 | **砍** | |
| 14.x 暗黑/主题 | **砍** | |
| 15.x 多 profile | **砍** | 数据模型成本太大 |
| **16.1 报告对比** | **加回 P0** | C2 解读 Tab + ReportCompareService |
| 17.x 模型升级 | **砍** | |
| 18.x iCloud 同步 | **砍** | 与本地卖点冲突 |
| 19.2 灵动岛 | P1 加分 | CaptureActivity LiveActivity |
| 19.1 Widget | **砍** | |
| **C1 档案列表** | **新增 P0** | ArchiveListView |
| **C2 报告详情三 Tab** | **新增 P0** | ReportDetailView |
| **C2 关联到趋势** | **新增 P0** | Indicator.pinned 批量更新 |
| **C2 重新解读** | **新增 P0** | CaptureService.reanalyze |

---

**END OF SPEC v1.0**
