# DESIGN.md — 工作區設計原則

> 本檔案是規範性文件：定義原則、目錄結構、檔案格式。只寫**不隨時間改變**的東西；
> 暫時狀態（進行中、待辦、待補）一律放 STATUS.md，操作細節放程式與 `ingest/README.md`。
>
> **Agent 不得自行修改本檔案，也不得默默違反或繞過。** 設計不合用時，向使用者說明衝突、
> 提出修改方案、取得明確同意後才改。本檔案的異動一律獨立 commit，訊息標 `[design]`。

---

## 1. 目錄結構

```
~/projects/health/
├── AGENTS.md            # 角色與操作原則（開場必讀）
├── DESIGN.md            # 本檔案（寫入前必讀）
├── STATUS.md            # Session 交接狀態（開場必讀，唯一允許刪內容的常駐檔）
├── profile.md           # 基本資料快照
│
├── inbox/               # 使用者投遞原始材料（§7）        ─ 不進 Git
├── sources/YYYY/        # 已處理的原始檔，永久保存（§7）   ─ 不進 Git
│
├── regimen/             # 藥品、保健品、固定飲食
│   ├── current.md       #   藥品/保健品現況：吃多少、何時吃
│   ├── diet.md          #   固定飲食現況
│   ├── products/        #   每個產品一檔：產品本身的事實
│   └── history.jsonl    #   上述三者的所有異動，append-only
│
├── checkups/            # 健檢與檢驗報告，一次一檔
├── metrics/             # 日常量測
│   ├── body.csv         #   體組成（體組成計 API 自動寫入）
│   ├── bp.csv           #   血壓（血壓計 API 自動寫入）
│   ├── wearable/        #   穿戴裝置原始資料與 SQLite     ─ 不進 Git
│   └── <device>/        #   各裝置原始回應                 ─ 不進 Git
├── ingest/              # 資料抓取程式與其 README
│
├── consults/            # 問診單（僅在使用者要求時建立，格式不拘）
├── reports/             # 應要求產出的報告（形態不限，見 §3.5）
├── knowledgebase/       # 外部文獻與自行調查的好讀版，一主題一目錄（§3.6）
└── notes/               # 症狀、就醫、疫苗等 append-only 日誌
```

三個核心原則：

1. **快照與歷史分離。** 快照檔（profile.md、regimen/current.md、diet.md）隨時改寫成最新狀態；
   歷史檔（*.jsonl、checkups/、sources/）只增不減，不修改舊內容。
2. **原始不可變，衍生可重建。** 原始回應與原始文件寫入後一個位元都不改；
   SQLite、CSV、報告都是衍生物，隨時可以刪掉重建。
3. **每筆資料可回溯。** 結構化檔案都要指回它的來源（sources/ 路徑、API 端點或使用者自述）。

---

## 2. 通用格式規範

- 時間 **ISO 8601、本地時區**（`2026-08-20`、`2026-08-20T07:30+09:00`）。不確定時可只到月。
- 單位：體重 kg、身長 cm、血壓 mmHg、血糖 mg/dL、脂質 mg/dL、體溫 °C；
  檢驗項目沿用報告單位並照抄參考區間；裝置回傳的英制一律入庫時換算。
- 來源標記：`lab`／`device`／`self`／`md`（醫師告知）。
- 語言：主要語言為主，檢驗項目名稱與醫師原文照抄不翻譯。

---

## 3. 各檔案格式

### 3.1 regimen/

- `current.md`：表格 `名稱 | 類別(藥品/保健品) | 劑量 | 服用時機 | 開始日期 | 目的/備註`。
  只管「吃多少、何時吃」，成分細節連到 `products/`。
- `diet.md`：每餐固定內容（含重量）＋固定食材的規格與營養依據。非固定餐點不記。
- `products/<slug>.md`：產品本身的事實（類別、每單位成分、廠商、標示來源與日期），
  不寫「我吃多少」。換品牌新建一檔，舊檔保留。
- `history.jsonl`：上述三者的所有異動，一行一筆：
  `{"ts", "kind": 藥品|保健品|飲食, "item", "action": start|stop|dose_change|note, "detail", "reason", "src"}`
  初次建檔每項一筆，開始日不明就明講。

### 3.2 checkups/YYYY-MM-DD_機構名.md

完整健檢與零星檢驗都用同一格式，章節固定：
**基本資訊**（日期、機構、方案、原始檔路徑）→ **數值表**（`項目 | 數值 | 單位 | 參考區間 | 判定`，
全部抄錄不挑異常）→ **影像與其他檢查** → **醫師總評/判定** → **與前次比較**（agent 產生）。

### 3.3 metrics/

- `body.csv`：`date,time,weight_kg,body_fat_pct,muscle_kg,visceral_fat,source,note`
- `bp.csv`：`datetime,systolic,diastolic,pulse,position,arm,note`（同時段多次量測全記）

### 3.4 notes/

- `symptoms.jsonl`：`{"ts", "symptom", "severity"(1–10), "context", "duration", "note"}`
- `visits.jsonl`：`{"ts", "facility", "dept", "reason", "dx", "rx", "followup", "src"}`；
  有新處方時同步更新 regimen/。
- `vaccines.jsonl`：`{"ts", "vaccine", "dose", "facility", "lot", "next", "src"}`；缺值寫 `null`。

### 3.5 reports/YYYY-MM-DD_主題.*

由快照檔計算出來的數字（營養估算、趨勢整理、給醫師的摘要）放這裡，帶日期，
標頭寫明衍生自哪些檔。不手改；上游變動就產新版本。

**形態不限**（html、pdf、md……由用途決定；同一份可有多種形態、共用檔名）。
不論形態，要求三點：
單一檔案自足（樣式與圖表全部內嵌，不連任何外部資源）；
圖表由 `metrics/`、`checkups/` 等來源**現算產生，不手繪、不憑印象填數字**；
螢幕版明暗兩色模式都要可讀。
有產生程式時，程式與其輸入一起進 Git；純二進位的衍生物（如 pdf）可重建，不必進 Git。

發布到本機網頁是操作細節，寫在 `reports/README.md`，不寫在本檔。

### 3.6 knowledgebase/<主題>/YYYY-MM-DD_簡述.md

外部文獻（指引、論文）與使用者自行調查的**好讀版**，是知識不是個人資料。
一個主題一個子目錄；`knowledgebase/README.md` 是索引，一行一份：
`主題 | 標題 | 檔案 | 來源 | 收錄日`。

- 一律 md。檔頭固定「收錄資訊」：主題、來源（URL／作者／出版日）、原始檔路徑、收錄日與轉換方式。
- 原檔**不論格式**都先原封不動歸到 `sources/YYYY/YYYY-MM-DD_文獻_簡述.ext`；
  PDF 轉一次並整理成可讀 md，md 是整理過的工作版，之後查資料只讀 md，不再開原檔。
- 建議類問題先查這裡（AGENTS §3.3）；引用時附檔案路徑並標示證據強度，不把文獻結論當成對使用者的醫囑。

---

## 4. 裝置資料自動抓取

穿戴裝置、體組成計與血壓計的資料由本專案自己抓，程式在 `ingest/`，資料落在 `metrics/`。
**參數、端點、資料表 schema、已知的資料特性，以 `ingest/README.md` 與程式本身為準**，本節只定原則：

- **原始回應不可變，查詢層可重建。** raw/ 一天一檔或一活動一目錄，寫入後不改；
  SQLite / CSV 隨時可由 raw/ 完全重建。
- **自動抓取永不登入。** 只用既有 token；token 失效就中止並回報，由人工執行登入程式。
  登入端點有 rate limit，反覆嘗試會鎖帳號。
- **節流、可中斷、可續跑。** 呼叫之間有間隔，429 退避後仍失敗就保留進度中止；
  已抓到的檔案略過，重跑不重抓。**最近幾天的資料視為暫定，每次重抓**（裝置延遲同步）。
- **秘密不進 repo。** 帳密在 `.env`，token 在 `~/.config/`，皆 600。密碼不得出現在程式碼、log、輸出。
- **查詢優先於印象。** 回答運動、睡眠、心率、體重問題時先查 SQLite / CSV。

---

## 5. STATUS.md 規則

唯一允許刪除內容的常駐檔，用途是 session 之間交接，不是歷史。固定四區塊：
**進行中**（跨 session 未完成）、**追蹤中**（觀察中的症狀或數值，附起始日與連結）、
**待辦**（使用者交代未做、或等使用者提供）、**最近寫入**（最新 10 筆）。

- 每次寫入後與 session 收尾時更新，含頂部時間戳。
- 完成即移除，不留「已完成」區 —— 歷史由 Git 保存。
- 全檔 50 行以內。
- 不設 STATUS-ARCHIVE.md：這是 root `DESIGN.md` §4 允許的「不用 ARCHIVE、完成即刪」變體。
- 任何「暫時」性質的資訊（部署進度、待補欄位、待驗證事項）只能在這裡，不能在 DESIGN.md。

---

## 6. 版本控制

Git 只追蹤**程式與文字檔**（md / html / csv / jsonl），不追蹤原始資料與二進位衍生物：
`metrics/<device>/`（可重抓）、`inbox/`（暫存）、`sources/`（二進位原始檔）。

- 每次寫入後 commit，訊息 `[類型] 一句話摘要`；STATUS.md 隨其他異動一起 commit。
- DESIGN.md 與 AGENTS.md 的異動獨立 commit。
- **`sources/` 是唯一不可重建的資料**，且不在 Git 內；備份以 `backup_health.py` 加密上傳雲端硬碟，
  **每週自動執行**（systemd timer），沒變的包不重傳；覆蓋雲端上的舊版前先留檔到 `archive/`，
  archive/ 程式永不刪、清理一律由使用者手動。還原用 `restore_health.py`（會隨備份一起上傳）；
  操作細節見兩支程式與 `~/projects/INFRA.md` §5。
- Git 本身只有本機一份時不構成備份。

---

## 7. 收件匣與原始檔

分工：**使用者只把材料丟進 `inbox/`，其餘全由 agent 處理。** 任何形式都收，不需分類、不需改名。
使用者說「給你了 X」一律指 inbox/。Agent 每次開場檢查 inbox/，有東西主動處理。

**流程**，一個檔案一個 commit：
辨識類型與日期（不確定就問）→ 解析並覆述給使用者確認 → 寫入對應的結構化檔 →
原始檔**移動**到 `sources/YYYY/YYYY-MM-DD_類型_簡述.ext`（日期用文件本身的，改名是唯一允許的異動）→
更新 STATUS.md 並 commit。處理完 inbox/ 為空；處理不了的留在原地並在 STATUS 待辦寫明原因。

**類型詞彙**（檔名只能用這些）：

| 類型 | 內容 | 寫入 |
|---|---|---|
| 健檢 | 年度健康檢查 | checkups/ |
| 檢驗 | 門診抽血、尿檢等零星檢驗 | checkups/ |
| 處方 | 處方箋、藥袋、用藥手冊 | regimen/ |
| 就醫 | 診療明細、醫師信件、轉診單、診斷書 | notes/visits.jsonl |
| 疫苗 | 接種證明 | notes/vaccines.jsonl |
| 體組成 / 血壓 | 量測儀截圖或匯出 | metrics/ |
| 文獻 | 指引、論文、使用者自行調查的整理 | knowledgebase/ |
| 其他 | 以上皆非 | 問使用者 |

**規則**：sources/ 只增不減；同一文件重複投遞（內容 hash 相同）告知並跳過。
