Functional Spec Partner — 七步工作流詳解
本檔為
SKILL.md引用的詳細工作流指南。在每次對話開始前讀一次。
前置條件
進入本工作流前確認:
requirement/{feature}/index.md已存在且可讀。沒有它,這層沒輸入,停下。- 使用者明確要產出這份 feature 的 functional spec,不是「順便看看」。
- feature 名與 requirement 同名(同名成組是可追溯性的基石)。
不符合任一條 → 明說缺什麼、停下,不要替使用者跳過 Stage 1。
步驟 1 — 定位 requirement 輸入
目標:讀完 Stage 1 的產出,建立自己的脈絡,再開始草擬。
操作
- 讀
requirement/{feature}/index.md:- Problem statement(一句話)
- Stakeholders(誰提的、誰受影響)
- 素材清單(每筆來源、日期、簡述)
- 未解問題清單
- 視需要瀏覽
requirement/{feature}/raw/或notes/。 - 檢查
spec/{feature}/{feature}.fp.md是否已存在:- 存在 → 視為延續編輯,讀過後與使用者對齊是補洞還是改既有條目。
- 不存在 → 全新 spec。
與使用者對齊
我讀過 requirement/{feature}/index.md,看到:
- Problem statement:…
- {N} 個未解問題(最關鍵的是 X、Y)
- 素材主要來自 {來源}
我打算先草擬 {M} 個 use case 給你挑,先從 {第一個} 開始。OK 我就開始。
異常
- requirement 不存在 → 「Stage 1 還沒輸出,我這層沒輸入。要回去補還是先停?」由使用者決定。
- requirement 有未解問題但使用者要繼續 → 把未解問題標進 spec 的「待裁定」區,不腦補。
步驟 2 — 草擬 Use Cases
目標:把 requirement 中的需求點轉成結構化 use case 草稿,請使用者挑錯。
一次一個草稿
Use Case A1: 細排既有工單
- Actor:排程員
- 觸發條件:在排程主畫面按「細排」
- 行為:
1. 系統載入目前未完成工單清單
2. 依加型/扣型分組
3. 套用產能限制,產生排程結果
4. 顯示結果於甘特圖
- 預期結果:所有可排工單已分配時段;無法排者列入未排清單
- 例外路徑:見 §邊界條件 B2、B3
這個草稿你看:
- Actor 對嗎?
- 行為步驟有沒有漏?
- 預期結果這樣寫夠不夠具體?
涵蓋面檢查
每個 use case 都問:
- Happy path 有沒有寫到?
- 主要 alternate path 有沒有列?(例如:失敗、取消、超時、無資料)
- Actor 是不是同一個?多 actor 流程要切多個 use case 還是用 swimlane?
對 requirement 逐項回溯
requirement index.md 提到 5 個需求點,我目前的 use case 對應:
- 需求 R1 → UC A1
- 需求 R2 → UC A2
- 需求 R3 → UC A1(同一條流程的延伸)
- 需求 R4 → 我把它列為「明確不做」對嗎?
- 需求 R5 → 還沒對應,這個是漏了還是不在範圍?
漏的逐條對齊。Exit Gate 第 1 條就是「涵蓋 requirement 中所有列入範圍的 user need」。
不要做
- ❌ 一次給三個 use case 倒著問「都對嗎」
- ❌ 把 requirement 沒寫的需求腦補成 use case
- ❌ Scope 決定(做/不做)自己拍板 — 一律請使用者選
步驟 3 — 建流程圖/狀態機
目標:用 Mermaid 把核心 use case 的流程或狀態轉換畫出來。
選 flowchart 還是 state diagram
| 情境 | 用 |
|---|---|
| 使用者操作流程、系統處理步驟 | flowchart |
| 物件/資源在不同狀態間轉換(工單從 NEW → SCHEDULED → DONE) | stateDiagram-v2 |
| 兩者都要 | 切兩張圖,各畫各的 |
範例(flowchart)
flowchart TD Start[排程員按細排] --> Load[載入未完成工單] Load --> Empty{有工單嗎?} Empty -- 否 --> Done[顯示空清單] Empty -- 是 --> Group[依加型/扣型分組] Group --> Schedule[套用產能限制排程] Schedule --> Fail{全部可排?} Fail -- 是 --> Show[顯示甘特圖] Fail -- 否 --> Partial[排可排的+列出未排清單] Partial --> Show
規則
- Label 寫人話,不寫程式碼
- 條件節點用
{},動作節點用[] - 一張圖一個主題;超過 15 個節點就拆
- 流程中的每個決策點要在後面的「邊界條件」段對應到一條規則
與使用者對齊
這張流程圖你看:
- 主要路徑(NEW → SCHEDULED → DONE)對嗎?
- 「全部可排」這個決策點我看 requirement 沒明寫,要不要也把「部分可排」單獨成一個分支?
步驟 4 — 逼出 I/O 範例
目標:每個 use case 給正常值、邊界值、異常值三組具體輸入輸出。
格式
### Use Case A1 的 I/O 範例
#### 正常值
- input:
- 工單清單 = [
{ id: 1042, type: 加型, qty: 100, dueDate: 2026-06-15 },
{ id: 1043, type: 扣型, qty: 50, dueDate: 2026-06-20 }
]
- 產能 = { 2026-06-01: 8h, 2026-06-02: 8h }
- output:
- 排程結果 = [
{ orderId: 1042, scheduledAt: 2026-06-01T08:00, duration: 4h },
{ orderId: 1043, scheduledAt: 2026-06-01T12:00, duration: 2h }
]
- 未排清單 = []
#### 邊界值
- input:
- 工單清單 = [ 500 張同型工單 ]
- 產能 = { 2026-06-01: 8h }
- output:
- 排程結果 = [...前 N 張...]
- 未排清單 = [...剩下的 500-N 張,含原因「產能不足」...]
#### 異常值
- input:
- 工單清單 = []
- output:
- 排程結果 = []
- 未排清單 = []
- (不報錯,視為合法空輸入)
規則
- 必須有實際值 —
Long、String、orderId、「成功訊息」全部不收 - 日期用 ISO 8601 或人類可讀格式,挑一種一致使用
- 集合不要寫「等等」— 至少列兩三筆代表性元素
- 異常值至少一條,不要省
寫不出來怎麼辦
寫不出具體值 = spec 還沒清楚。回 use case 步驟把該條補細,或標進「未解問題」。不要捏假值充數。
步驟 5 — 列邊界條件 / 異常情境
目標:把流程圖中的決策點、I/O 範例中的異常值,整理成枚舉式的邊界條件表。
格式
### 邊界條件
| 編號 | 條件 | 結果 |
|---|---|---|
| B1 | 工單清單為空 | 回傳空結果,不報錯 |
| B2 | 工單數量 ≤ 0 | 報 InvalidQuantityException |
| B3 | 產能完全為 0 | 全部工單進未排清單,標示原因「無產能」 |
| B4 | 工單交期早於今日 | 仍依規則排,但在結果標 `overdue: true` |
| B5 | 同型工單超過 500 張 | 依排序規則處理,不分批 |
涵蓋面檢查
- 流程圖每個
{}決策節點都有對應的一條邊界條件嗎? - I/O 範例的「異常值」都有對應的邊界條件嗎?
- requirement 的未解問題中是否有變成邊界條件的?
編號是契約
B1、B2 等編號之後會被 use case 的「例外路徑」、Stage 4 的 pseudo code §編號 引用。一旦寫出就append-only:
- 新條件加新編號(B6、B7…)
- 廢棄條件用
~~刪除線~~+ 廢棄原因,不要重編號
步驟 6 — (可選)寫驗證 Python script
目標:把核心邏輯短腳本跑一次,確認 spec 自洽。
何時寫
- 流程含演算法或多步決策(細排、配料、產能扣減)
- 邊界條件多、彼此交互影響
- 使用者明確要 demo
何時不寫
- 純 CRUD(新增/查詢/修改/刪除)
- 純 UI 互動(按鈕觸發某個顯示)
- 純資料查詢、報表
範例骨架
# spec/{feature}/{feature}.fp.validate.py
"""
驗證 spec/{feature}/{feature}.fp.md 的 I/O 範例是否自洽。
跑法:python {feature}.validate.py
"""
def schedule(orders, capacity):
# 對應 functional-spec §UC A1 行為步驟
...
return scheduled, unscheduled
# I/O 範例 — 正常值
orders = [
{"id": 1042, "type": "加型", "qty": 100, "dueDate": "2026-06-15"},
{"id": 1043, "type": "扣型", "qty": 50, "dueDate": "2026-06-20"},
]
capacity = {"2026-06-01": 8, "2026-06-02": 8}
scheduled, unscheduled = schedule(orders, capacity)
assert len(scheduled) == 2
assert unscheduled == []
# I/O 範例 — 邊界值(500 張同型)
...規則
- 腳本只驗證 spec 自洽,不是實作雛形
- 跑得通 ≠ 設計正確;只代表「I/O 範例不矛盾」
- 跑不通 → spec 有洞,回去補
步驟 7 — 組裝 + 請人簽核
目標:寫檔、留簽核欄位、提示後續。
操作
- 套
output-template.md組裝完整文件 - 寫入
spec/{feature}/{feature}.fp.md - 文件底部留簽核欄位(姓名 + 日期,由使用者自己填)
- 提示:
- 「簽核欄位請你填名 + 日期,這份才算定稿(Exit Gate 第 5 條)」
- 「路徑可加進 ticket」
收尾話術
這份 functional spec 我們確認了:
- {N} 個 use case(A1 ~ A{N})
- {M} 張流程圖/狀態機
- 每個 use case 三組 I/O 範例
- {K} 條邊界條件(B1 ~ B{K})
- {有/沒有} 驗證 script
我會:
1. 套 output-template 組裝
2. 寫到 spec/{feature}/{feature}.fp.md
3. 留簽核欄位給你填
可以嗎?
異常情境
使用者要求「跳過 use case 直接畫流程圖」
可以加速,但不要省。流程圖的每個決策節點要對得回某個 use case 的行為步驟,沒有 use case 的流程圖是孤兒。
流程圖我會畫,但我需要先知道是哪個 use case 的流程。我快速列三個候選 use case(A1/A2/A3),你挑一個我直接畫,OK?
使用者堅持要寫 class diagram
class diagram 是 Stage 3 OOA 的事,這份 spec 寫了反而會跟 OOA 文件衝突。
這層我們只到「對外觀察點」— 例如 input/output、流程、邊界。
要不要記成「下一步交 OOA 處理」?
使用者答不出某個 use case 的 alternate path
不要腦補。記成 use case 內的「待裁定 alternate path」並標進文件,明說此 use case 在這點上尚未 Exit Gate ready。
I/O 範例的具體值需要查資料
如果使用者答不出具體值(例如「客戶實際資料長什麼樣」),可選:
- 標
具體值待確認並繼續 - 暫停這個 use case,先處理其他
不要用「example_value_123」這種假值寫進去,那會在 OOA / Code 時被當真。