# DESIGN.md — ~/projects/ workspace 的架構與標準（範本）

> 這份講「workspace 是什麼、為什麼這樣設計、每個專案的文件標準」。穩定，不記進度。
> agent 每次都要遵守的規則在 `AGENTS.md`；進度在 `STATUS.md`。
>
> 使用方式：這份大部分可以照用；「已承認的例外」與「允許的變體」換成你自己的專案。
> 第 1 節裡標「作者的做法」的地方是作者的取捨，不是唯一正解。

## 1. 架構與理由

### 核心概念

- **專案是「狀態」，agent 是來處理狀態的 session。** agent 不綁定資料夾。任何 session 進入專案，讀完專案的文件就能接手；離開前把狀態寫回。比喻：護理站的交班本——護理師（session）會換班，病人（專案）不會；交班本寫得好，誰接手都知道下一步。
- 整台主機只有一個常駐入口：在 `~/projects/` 跑 server mode（`claude remote-control`），從 app 隨時開新 session；每個 session 依 AGENTS.md 的意圖判斷決定要不要進某個專案。
- 指令檔的名字（作者的做法）：一律叫 `AGENTS.md`，**不用 `CLAUDE.md`**，因為未來可能用 Claude 以外的工具。代價：Claude Code 只在工作目錄與所有上層目錄都沒有 CLAUDE.md 時才讀 AGENTS.md，整條路徑上不能有 CLAUDE.md（見第 6 節）。只用 Claude 的話用 `CLAUDE.md` 更省事。
- **每個 session 都是總機，長工作派給幫手**（進階，作者的做法）。總機是角色不是編制：使用者開兩個 session 就是兩個總機，Claude Code 的 session 各自獨立、沒有「唯一總機」可認。撞車靠值班表擋：`.busy/` 一專案一檔、`scripts/busy.sh` 登記與檢查，同一專案同時只有一個工人。防污染靠既有原則「狀態在檔案」：幫手之間不互看對話，只讀 STATUS；總機只收摘要。
- **模型選擇是總機的判斷，不是硬規則**：額度寬裕時預設用最強的，只在量大或額度吃緊時降級；小模型只用在「速度重於品質」的判斷。理由：第 0 版這種要一次串起多塊的工作，用強模型比較不會做到一半卡住。
- 上層（root）的 AGENTS.md 在啟動時載入，穩定；子目錄（專案）的 AGENTS.md 只在讀到該目錄檔案時附加，context 壓縮後可能消失。所以**不依賴自動載入，而是靠明確的「進出專案協定」**（見 AGENTS.md）。

### 為什麼不設權限限制（作者的做法）

- 作者早期用 `.claude/settings.json` 的 allow／deny 硬擋寫入。代價是每個新專案都要補規則、symlink 與含空白的路徑要實測、正當的修改也被擋住要繞路。
- 現在改成：安全靠謹慎的指令（AGENTS.md 的操作原則）、刪除與覆蓋前先確認、以及 **git 作為回溯手段**（每個專案自己的 repo，做完一段就 commit；沒 git 的專案靠雲端週備份）。
- 讀取完全不設限：使用者要的是能自由查看他所有資源、做綜合回答的助理。

### 目錄結構

```
~/projects/
  .git/               ← root 自己的 repo（白名單 .gitignore，看不到子專案）
  AGENTS.md           ← root agent 的指令
  DESIGN.md           ← 本檔
  STATUS.md           ← workspace 層級的進度與待辦
  STATUS-ARCHIVE.md   ← 可選
  INFRA.md            ← 本機基礎設施的跨專案正本（有 infra 時才需要）
  scripts/busy.sh     ← 值班表工具（claim／release／check／list）
  .busy/              ← 值班表：一專案一檔，不進 git，程序不在即過期
  <project>/          ← 各專案，各自是（或不是）git repo
    AGENTS.md         ← 可選
    DESIGN.md
    STATUS.md
    STATUS-ARCHIVE.md ← 可選
  temp_workspace/     ← 臨時工作，一件一個子目錄
  infra/              ← 共用基礎設施本身（有的話）
  Archived projects/  ← 不要了但暫時不刪
```

- `~/` 底下不能有 CLAUDE.md 或 AGENTS.md（會被所有子目錄繼承，且擋掉 AGENTS.md 的 fallback）；`~/.claude/CLAUDE.md` 也建議移除，內容併進 root AGENTS.md，只留一份。
- root repo 的 `.gitignore` 是白名單，只追蹤 root 的幾份文件；子專案的版本控制各自管。理由：子專案有各自的敏感度與備份策略，混在一個 repo 裡會互相牽制。

## 2. 專案檔案標準

| 檔案 | 內容 | 性質 |
|---|---|---|
| `DESIGN.md` | 這個專案是什麼、為什麼這樣設計、架構、資料流、重要決策與理由 | 穩定 |
| `STATUS.md` | 目前進度、下一步、未決問題、已知問題 | 易變 |
| `STATUS-ARCHIVE.md`（可選） | 從 STATUS 移出的歷史紀錄。STATUS 太長、或專案自己覺得需要時再加 | 只增不改 |
| `AGENTS.md`（可選） | 此專案的穩定操作規則：怎麼 build／run／test、指令的坑、不能動的檔案、外部服務限制 | 穩定 |
| `README.md`（可選） | 給人看的簡介，或公開 repo 需要的說明；不作為 agent 的主要文件 | — |

原則：DESIGN 講「是什麼、為什麼」，STATUS 講「做到哪」，AGENTS 講「怎麼操作」。三者不重複。
每個專案至少要有 DESIGN.md 與 STATUS.md，就算暫時很短。

已承認的例外（作者的例子，換成你自己的）：

- **temp_workspace** 的狀態在各子目錄：一件工作一個子目錄，各自帶 README 記做了什麼、怎麼跑、坑。
- **公開 repo 的專案**可以讓 `README.md` 兼作 DESIGN（公開 repo 需要 README，測試與腳本都讀它）；DESIGN.md 只指過去。
- 專案可以保留額外的穩定文件（例：`DESIGN-CHANGELOG.md`、`DECISIONS.md`），只要在 DESIGN 或 AGENTS 指路。

## 3. 內容分類規則

整理既有文件、或替新專案建文件時，逐段分到：

| 內容類型 | 去處 |
|---|---|
| 設計決策、架構、資料模型、為什麼這樣做 | 專案 `DESIGN.md` |
| 目前進度、待辦、未決問題 | 專案 `STATUS.md` |
| 已完成、已過時的進度紀錄 | 專案 `STATUS-ARCHIVE.md`（或刪除，歷史靠 git） |
| 穩定的操作規則（指令、坑、禁區） | 專案 `AGENTS.md`（瘦身版） |
| 關於使用者本人、跨專案通用的規則 | root `AGENTS.md` |
| 值得長期記住但不屬於任何專案的知識 | 筆記庫（有的話） |
| 明顯過時、與現況矛盾、純粹是舊 session 的臨時筆記 | 刪除 |

整理是搬移和刪除過時內容，不是重寫；原文措辭盡量保留。分類不確定的段落列為問題，不猜。

補充規則（作者整理舊專案時踩出來的）：

- **舊的 Claude 記憶也是來源**（`~/.claude/projects/<目錄>/memory/`）。逐條對照專案文件的正本再決定：已經寫在文件裡的丟掉；與現況矛盾的丟掉（舊記憶常停在被推翻前的規則）；只有還沒寫進文件的才搬。不整筆照搬。記憶目錄本身不刪。
- **一段內容一半通用、一半專案特有時，拆開寫**：通用部分進 root `AGENTS.md`，專案的例外留在專案 `AGENTS.md`，並寫明是例外。
- **改檔名後，舊名的引用分三種處理**：活的文件與程式 → 跟著改；凍結或只能追加的（定版報告、有日期的產出、決策紀錄、ARCHIVE 舊條目）→ 不改，在專案的決策紀錄或 STATUS 記一條「舊名＝新名」；別的專案裡的引用 → 等進那個專案時處理，或列進 root `STATUS.md`。
- **專案有自己的治理規則時**（例如 DESIGN 要使用者核准才能改），照它的流程走。
- **已承認的結構變體不硬改成標準樣子**，只修違反它自己規則的地方。
- 瘦身不一定變短：併入記憶後，AGENTS.md 可能反而變長。判準是「每一段都是怎麼操作」，不是行數。

## 4. STATUS／STATUS-ARCHIVE 規則

- 頂部一行「最後更新：日期（一句話摘要）」。段落順序：**最近做完的事 → 一句話現況 → 未完成 → 坑**；專案可再加自己的段（常用指令、程式地圖）。
- STATUS 只記狀態，不記原則；原則寫進 DESIGN。
- 「最近做完的事」**只留最近 5 條**：寫第 6 條時把最舊的整段搬去 ARCHIVE。
- 「未完成」裡結了案的小節**整段搬**去 ARCHIVE，不是只把標題改成「已結案」；還有沒做完的尾巴時，尾巴留下、敘事搬走。
- 做完一段就回頭核對「未完成」與「坑」有沒有過期。
- ARCHIVE 只追加，按輪次分節、標明搬入日期；不必每次讀，考古時才翻。
- 拆檔的理由：STATUS 是每個 session 的必讀，長到幾十 KB 後讀它本身就是固定成本。

允許的變體（在專案的 DESIGN 或 AGENTS 宣告即可）：

- **不用 ARCHIVE、完成即刪**：固定區塊、全檔 50 行內、歷史靠 git。適合狀態少、變動小的專案。
- **固定區塊＋決策另檔**：STATUS 固定幾個區塊，結案事項進 ARCHIVE，決策進 `DECISIONS.md`。

## 5. 新專案範本

1. `mkdir ~/projects/<name>`；名稱用小寫與底線／連字號，避免空白（含空白的路徑在 shell、symlink、部分工具都要多測）。
2. 建 `DESIGN.md`（是什麼、為什麼、架構）、`STATUS.md`（頂部「最後更新」＋第 4 節的四段）；需要時再建 `AGENTS.md`、`STATUS-ARCHIVE.md`。空白範本在 `project-template/`。
3. `git init`；`.gitignore` 排除資料、憑證、`.venv/`。沒有 git 的專案要在 DESIGN 寫明備份方式。
4. 在 root `AGENTS.md` 的專案索引加一行。
5. 用到基礎設施（反向代理、通知、systemd timer、雲端備份）照 `INFRA.md` 的情境做；unit 檔正本放專案的 `systemd/`，用 `systemctl --user link` 掛入。
6. 臨時、一次性的工作**不開新專案**，放 `temp_workspace/<工作名>/`。

## 6. 指令檔載入的注意事項

依 Claude Code 官方文件（作者 2026-09 查；版本會變，請自行再確認）：

- **AGENTS.md 是 fallback**：預設模式 `claude-md-or-agents-md` 下，只在工作目錄與所有上層目錄都沒有 CLAUDE.md 時才讀 AGENTS.md。對應的設定 key 是 `pluginConfigs.agents-md@builtin.options.instructionFiles`（`~/.claude/settings.json` 沒設就是預設）。
- 使用者層的 `~/.claude/CLAUDE.md` **不算**擋 fallback 的 CLAUDE.md，會和 AGENTS.md 一起載入。
- 子目錄的 AGENTS.md 只在讀到該目錄檔案時附加，和子目錄 CLAUDE.md 一樣；文件沒說 compaction 後會不會保留。所以 root AGENTS.md 要求「進專案前明確讀該專案的 AGENTS／DESIGN／STATUS」，不靠自動載入。
- `--add-dir` 不會載入被加目錄的 AGENTS.md。
- `claude -p`（headless）與 `claude remote-control --spawn=same-dir` 開出的 session 都照上述規則讀 cwd 的指令檔。
- **驗證方式**：在 root 指令檔放一行只有它才有的標記句，開新 session 問；答得出來才算載入。
