產品開發 Workflow

從「使用者需求」到「Code」的五階段流程。 核心原則:前段守住人類判斷,後段才把實作交給 AI


流程總覽

flowchart LR
    R[User Requirement<br/>使用者需求] --> F[ Functional Spec<br/>功能規格]
    F --> O[ OOA<br/>物件導向分析]
    O --> P[Pseudo Code<br/>虛擬碼]
    P --> C[Code<br/>程式碼]

    classDef human fill:#e8f0ff,stroke:#3b6,stroke-width:2px
    classDef hybrid fill:#fff4e0,stroke:#e90,stroke-width:2px
    classDef ai fill:#ffe8e8,stroke:#c33,stroke-width:2px

    class R,F human
    class O,P hybrid
    class C ai
顏色意義
人主導,AI 協助
協作(共同決定)
AI 主導,人 review

階段一:User Requirement(使用者需求)

性質

紀錄區,不是規格。只負責收集與保存原始需求素材,不要求結構化。

內容形式(任何皆可)

  • 文字筆記、會議紀錄、訪談逐字稿
  • 圖片、白板照片、手繪草圖
  • 語音檔、影片片段
  • 既有文件(PDF、Email、Slack 對話截圖)
  • 連結(Jira、Linear、Notion)

唯一硬性要求

來源可追溯。每一份素材都要能說出「誰、何時、為何提的」。

產出結構

requirement/{feature}/
├── index.md           ← 索引 + 一句話 problem statement
├── raw/               ← 原始素材(圖、錄音、檔案)
└── notes/             ← 整理過的筆記(可選)

index.md 至少包含:

  • Problem statement:一句話講清楚要解決什麼問題
  • Stakeholders:誰提的、誰受影響
  • 素材清單:每筆有來源、日期、簡述
  • 未解問題:還沒釐清的點(給下一階段消化)
  • 需求收斂結論:把紀錄收斂成 Stage 2 的乾淨 input;每點回指素材/已答未解問題,不寫 scope(做不做什麼是 Stage 2)

AI vs 人

動作主導
收集素材
整理 index、打標籤AI
標記重複/矛盾AI
對未解問題提出澄清題目AI
草擬需求收斂結論AI(人確認)
確認素材真實性與優先級

Exit Gate(離開本階段的條件)

  1. index.md 存在
  2. Problem statement 一句話寫得出來
  3. 至少有一份原始素材或筆記
  4. AI 已挑出未解問題清單,人確認可以進下一階段
  5. 需求收斂結論已寫,且每點可回指素材/已答未解問題、無 scope 決策

階段二:Functional Spec(功能規格)

性質

結構化的功能定義。比 Story 更明確,比軟體規格(OOA、API spec)更高層。 回答「這個功能要做什麼、長什麼樣、邊界在哪」,但回答「怎麼實作」。

必備內容

  1. Use Cases
    • 角色(Actor)+ 觸發條件 + 行為 + 預期結果
    • 至少涵蓋 happy path + 主要 alternate path
  2. 流程圖或狀態機(Mermaid 即可)
    • 使用者操作流程,或系統狀態轉換
  3. 輸入 / 輸出範例
    • 具體值,不要只寫型別
    • 包含正常值 + 邊界值 + 異常值
  4. 邊界條件 / 異常情境
    • 列舉式:什麼情況下應該發生什麼

可選但建議

  1. 驗證 Python script
    • 把核心邏輯寫成短腳本跑一次
    • 用途:自我檢核 spec 是否自洽、給人 demo 用
    • 不強制 —— 純 CRUD 或 UI 類功能寫了反而冗餘

禁區(這些是 OOA 的事,不要在這寫)

  • Class diagram、繼承關係
  • DB schema、欄位定義
  • API endpoint 細節(URL、HTTP method、payload)
  • 套件結構、模組切分

產出

spec/{feature}/{feature}.fp.md

requirement/{feature}/ 同名成組

文件頂部 breadcrumb:

> 來源:[requirement/{feature}/](../../requirement/{feature}/index.md)
> 下游:[OOA]({feature}.ooa.md)(尚未建立)

AI vs 人

動作主導
從 requirement 草擬 Use CaseAI
補流程圖、輸入輸出範例AI
挑漏洞(邊界、矛盾、未覆蓋的 case)AI
範圍決定(什麼做、什麼不做)
優先級
最終定稿

Exit Gate

  1. 涵蓋 requirement 中所有列入範圍的 user need(逐項對照)
  2. Use Cases 完整(happy + 主要 alternate)
  3. 至少一張流程圖 / 狀態圖
  4. 輸入輸出範例具體(有實際值)
  5. 人簽核(在文件底部留簽名 + 日期)

階段三:OOA(物件導向分析)

性質

軟體規格的結構面。把 Functional Spec 翻譯成軟體世界的語彙。

內容

  • 領域語彙(Ubiquitous Language)
  • Object Model(類別、屬性、方法)
  • 關係(繼承、組合、聚合、關聯)
  • Event(領域事件)
  • Use Case Sequence Diagram

產出

spec/{feature}/{feature}.ooa.md

AI vs 人

協作。AI 用結構化方法協助分析(類別圖、SOLID 檢視),人決定領域邊界與命名。

Exit Gate

  1. 類別圖完整(涵蓋 Functional Spec 中所有 Use Case 的物件)
  2. 通過 SOLID 檢視
  3. 領域語彙表完整
  4. 人簽核

階段四:Pseudo Code(虛擬碼)

性質

軟體規格的流程面。把 Functional Spec 定義的行為,展開成帶決策邏輯的流程,並用 OOA 的類別/方法結構承載。

必備

  • §編號 的決策節點(後續 Code 要在註解引用)
  • §編號永久:新內容附加新號、絕不重編;被取代的段落標 刪除線 + 後繼 § 指標,集中移至文件底部「§廢棄歷史」,主流程僅留一行 tombstone(去發散、保留追溯)
  • 對外節掛全域碼:被下游(OOA/Code/別份 spec)引用的 §-section,其權威引用形式 = 全域碼 §{SHORT}-PC-{NUMBER}(見 §可追溯性「全域編碼」);純內部子節點維持本地 §N.M
  • 涵蓋所有 business decision branch
  • 不要寫得像真實程式語言,重點是邏輯流不是語法

產出

spec/{feature}/{feature}.pseudo.md

AI vs 人

協作。AI 起草,列出所有分支;人檢查流程正確性。

Exit Gate

  1. 所有 business decision 都有 §編號
  2. 對照 Functional Spec 的 Use Cases,每條 happy/alternate path 都覆蓋
  3. 人簽核

階段五:Code

性質

實作。

規範

  • Code 必須在 Javadoc / 註解中引用對應虛擬碼的全域碼 §{SHORT}-PC-{NUMBER}(見 §可追溯性「全域編碼」);對外公開類別/方法另掛自身 §{SHORT}-RC-{NUMBER}
  • 測試覆蓋 Functional Spec 中的輸入輸出範例

AI vs 人

AI 主導。人 review + 跑測試。

Exit Gate

  1. 測試通過(含 spec 中的範例值)
  2. § 引用完整
  3. Code review 通過

可追溯性(Traceability)

同名成組

requirement/login/         ← 階段一
spec/login/login.fp.md   ← 階段二
spec/login/login.ooa.md               ← 階段三
spec/login/login.pseudo.md       ← 階段四
src/.../Login*.java        ← 階段五

共用 / 跨 feature spec(例外)

有些 functional spec 不屬於單一 feature,而是多個 feature 共用的領域物件(Published Language),例如 spec/domain-model/domain-model.fp.md。這類 spec:

  • 無 requirement 上游 —— 從多個消費 feature 的共同需求抽出,非由單一 requirement/{feature}/ 衍生;不適用「同名成組」回指 requirement,也不與 requirement 做上游 audit。
  • 可追溯性改走 consumer → shared:各消費 feature 在自己的 spec 以 breadcrumb/相對 markdown 連結指向共用 spec([domain-model](../domain-model/domain-model.fp.md)),「誰引用我」由 backlinks 彙整(Quartz 站對標準 markdown 連結自動建)、不手維護。一律純 GFM、不用 wikilink(見 §連結慣例(GFM))。
  • 欄位級真相在自己的 OOA:Stage 2 只放概念層;欄位/型別落在 spec/{shared}/{shared}.ooa.md

每份文件頂部標註上游與下游連結。中斷的環節(例如某個 requirement 改了但 spec 還沒同步)一目了然。

需求收斂結論作為上游錨點

Stage 1 index.md 的「需求收斂結論」是下游 Spec 回指源頭需求的錨點:它把多輪澄清後「需求收斂到什麼」描述成 Stage 2 的乾淨 input,並讓「是哪個需求造就了這個 Spec」可被直接定位。它收斂紀錄、不下 scope —— 每點回指素材或已答未解問題,scope 仍由 Stage 2 拍板。

連結慣例(GFM)

本 repo 同時是 git 版控庫、VSCode 編輯對象,並由 Quartz v5 靜態站對外呈現。原始碼一律純 GFM(GitHub Flavored Markdown)——VSCode 預覽 / GitHub / Quartz 三處渲染一致。不用 Obsidian 方言[[wikilink]]^block-id、非 GFM callout、#N 假 tag)。

連結類型語法
檔案間 / breadcrumb相對路徑 markdown 連結 [顯示文字](../path/file.md)。深度:requirement/{feature}/index.md 兩層深用 ../../{stage}/…spec/{feature}/ 內 fp/ooa/pseudo 兩層深、連 requirement 用 ../../requirement/…;同 feature 各階段為同層 sibling,直接用檔名 {feature}.ooa.md連同資料夾 sibling 也用 markdown 連結、絕不用 wikilink
同檔章節跳轉markdown 連結到標題錨 [顯示文字](#slug)(slug 見下「錨點 slug」)
跨檔指某區段markdown 連結到該檔 + 標題錨 [#10](../../requirement/{feature}/index.md#未解問題)
提示框GFM alert:> [!NOTE][!TIP][!IMPORTANT][!WARNING][!CAUTION]僅這 5 種,三處皆渲染)
流程圖```mermaid fenced block(GitHub / VSCode / Quartz 皆渲染)
狀態標籤#未答#粗排 等為純文字標記(非可點 tag、非連結);編號導航一律用標題/區段連結

逐項精準錨由 build 注入(不靠 Obsidian ^id§碼§{SHORT}-{TYPE}-{N})與未解問題逐題#qN,依題號)由站台 pipeline 的 linkify-codes.mjs 在 build 時注入 id,原始碼維持純 GFM。引用即寫 [#N](#qN)[§…](…#gc-…),定義處不需手寫錨。

錨點 slug(跨檔/同檔指標題):用 github-slugger 形式(小寫、空白→-、去標點,CJK 保留;如 I/O 範例#io-範例圖 2:…(9 站)#圖-2…9-站)。純 CJK 無空白標點的標題 slug = 原文(如 #未解問題)。lint-links.mjs 會驗同檔錨對得上標題。

為何純 GFM:同一份原始碼同時要滿足 Obsidian + GitHub + Quartz 三套語意,是 broken link/錨點/預覽問題的根源。收斂成 GFM 一套後三處渲染一致;豐富功能(graph/backlinks/搜尋)由 Quartz 站對標準 markdown 連結提供,不靠 Obsidian。lint-links.mjs 守門擋住 wikilink/^id/非 GFM callout 回潮。

全域編碼(§{SHORT}-{TYPE}-{NUMBER})

每階段的「對外」項目散落在各自的本地編號(FS 的 B1…、Requirement 的 ^q1…、Pseudo Code 的 §1.1…)。這些號在單一文件內唯一,跨 feature/vault/repo 卻撞號(RCS 的 §1.1 與 capacity-module 的 §1.1 無法區分),一旦被外部 code repo 或別份 spec 引用就斷追溯。全域碼給「對外」項目一個跨界唯一識別。

說明
格式§{SPEC_SHORT_NAME}-{TYPE}-{NUMBER},例 §RCS-FS-6§RCS-PC-7.3.6§DM-OA-1
SPEC_SHORT_NAME每個 spec/feature 的短名,配發於 spec-codes.md單一真相
TYPEURFSOAPCRC(對應五階段)
NUMBER[0-9.]+沿用本地號的數字部分,去字母前綴、保留小數階層、不零填補(B66q33§7.3.67.3.6

哪些算「對外」:UR=需求收斂結論;FS=邊界條件/異常情境;OA=Domain Service/Calculator/Strategy 介面/Exception 等公開型別;PC=被下游引用的 §-section(公開方法契約);RC=對外公開類別/方法。

兩層並存:全域碼 = 跨界「對外」錨點;本地 §N.M 子節點 = 文件內部導航,維持不動。只有對外項目掛全域碼。

rename ≠ renumber:「沿用本地號」⇒ 全域碼是本地號的跨界書寫形式,號碼 1:1 保留,不違反「§編號永久」。append-only、廢棄保 tombstone 同本地號紀律。

跨界即反向索引:全域碼全域唯一 ⇒ 直接 grep §{SHORT}-{TYPE}-{NUMBER}(跨 vault + code repo)即可定位所有引用,不另維護對照表。

反向追蹤

Code 註解的全域碼 §{SHORT}-RC/PC-… → 找到虛擬碼章節 → breadcrumb 往上找 OOA → spec → requirement。 出了 bug 或要改需求時,從任何一層都能定位;全域碼讓「哪份 spec 的哪一項」無歧義。


AI vs 人 邊界總覽

階段主導AI 角色人角色
1. Requirement整理索引、提澄清題收集素材、確認真實性
2. Functional Spec起草、挑漏洞、補邊界範圍、優先級、定稿
3. OOA協作建模、SOLID 檢視領域邊界、命名
4. Pseudo Code協作起草、列分支流程正確性
5. CodeAI依規格產 codereview、跑測試
— 跨階段彙整AI掃描各 feature 既有狀態欄位、重生進度看板(dashboard.md手寫區備註、看板上的取捨判斷

跨階段彙整由 spec-dashboard skill 執行(見 §跨階段進度彙整)。它是衍生視圖:不裁定、不改任何來源檔,看板每一格都回指既有欄位。


常見陷阱

  1. Requirement 階段就開始談解法 —— 拉回來,這階段只記「想解決什麼」並把它收斂成需求收斂結論(每點回指來源),但不下 scope 結論(做不做什麼是 Stage 2)。
  2. Functional Spec 寫成 API 文件 —— 砍掉,那是 OOA / Software Spec 的事。
  3. 跳過 Functional Spec 直接 OOA —— OOA 沒有結構化的 input 就會亂、就會發散,這正是這個 workflow 要解決的問題。
  4. Code 完成後文件不同步 —— 任何改動都要從對應階段往上更新,否則可追溯性瓦解。
  5. AI 在前段越權 —— Requirement / Functional Spec 是人決定。AI 給草稿沒問題,但拍板權在人。

跨階段一致性檢視(Consistency Audit)

解決的問題:熟悉系統的人為了效率,常會直接編輯 Functional Spec / OOA / Pseudo Code,而不從 Requirement 重新跑下來。這是合法路徑,但會產生跨階段隱性 drift —— 這個機制把 drift 顯性化。

兩條合法的變更路徑

A. 正規變更(top-down) 需求真的變了 → 從階段一開始改,往下游 cascade,每層重過 Exit Gate。

B. 直接編輯(mid-stage edit) 熟悉系統的人直接動下游文件。前置條件:改動必須符合該階段的格式規範(格式壞掉 = 自己變亂源)。動作:改完在簽核 / commit 前跑一次 Consistency Audit。

各階段直接編輯的審視範圍

修改了 Functional Spec

上游(往 Requirement 看)

  • 改動是否仍在 Problem Statement 與需求收斂結論範圍內?
  • 是否引入了 Requirement 沒記錄的 user need?
  • 是否與既有 Requirement 筆記矛盾?
  • 例外 —— 共用/跨 feature spec(如 domain-model,設計上無 requirement 上游,見 §可追溯性 → 共用/跨 feature spec):略過上述 requirement 比對,改檢查「是否引入任何消費方 spec 都未涵蓋的概念」。

下游(往 OOA / Pseudo / Code 看)

  • 哪些 Use Case 被改 → 對應的 Object Model 元素?
  • 哪些 I/O 範例被改 → 對應的 § 編號需重看?
  • 是否新增了下游沒覆蓋的分支?

修改了 OOA

上游:Model 是否仍能服務 Functional Spec 的所有 Use Case?是否引入了 Spec 沒提到的概念? 下游:哪些 § 引用了被改動的 class / method / event?哪些 code 引用了這些 §?

修改了 Pseudo Code

上游:流程是否仍對應 Functional Spec 的 Use Cases?分支是否完整? 下游:哪些 code 在註解引用了被改的 §?需重 review + 測試重跑。

Impact Report 範本

# Consistency Audit: {feature} / {modified-stage}
 
- 修改文件:spec/login/login.fp.md
- 修改日期:2026-06-01
- 編輯者:Alan
- Diff 摘要:(一句話)
 
---
 
## 上游一致性
 
| 項目 | 狀態 | 說明 |
|---|---|---|
| Problem Statement 範圍 | ✅ / ⚠️ / ❌ | ... |
| Requirement 素材覆蓋 | ... | ... |
 
**需討論項目**
1. ...
 
## 下游影響
 
| 下游文件 | 受影響章節 | 行動 |
|---|---|---|
| spec/login/login.ooa.md | §3 User class | 需更新 |
| spec/login/login.pseudo.md | §2.1 驗證流程 | 需重看 |
| LoginService.java | line 42-78 | 測試重跑 |
 
## 建議行動清單
 
- [ ] 與 stakeholder X 確認 Problem Statement 是否擴張
- [ ] 更新 spec/login/login.ooa.md §3
- [ ] ...
 
## 簽核
 
- [ ] 編輯者已跑過 audit
- [ ] AI 產出 Impact Report
- [ ] Reviewer 確認:____

狀態判定

狀態意義處理
✅ 一致改動與上下游自洽直接通過
⚠️ 需討論不矛盾但可能有 implication進討論清單,由人裁定
❌ 矛盾直接違反上游或讓下游失效阻擋簽核,必須處理

AI vs 人

動作主導
偵測 diff(git diff 或前後文比對)AI
比對上下游內容AI
初判一致 / 需討論 / 矛盾AI
產出 Impact ReportAI
裁定 ⚠️ 項目
決定下游怎麼修(要不要修、誰修、何時修)
執行下游更新依該階段原本的 AI/人 邊界

設計理由

  1. AI 不自動 cascade 修下游。下游本來就有自己的 AI/人 邊界,自動 cascade 會跳過該層人判斷 —— 那就是 AI 越權。
  2. AI 只負責「指出影響」。修不修、怎麼修,回到該階段的規則。
  3. ❌ 矛盾要擋簽核。⚠️ 與 ✅ 不擋,因為熟手判斷 > 死板規則。
  4. 編輯者自己跑 audit。不是別人來抓 —— 是自己對自己的紀律工具。

跨階段進度彙整(Spec Dashboard)

解決的問題:多個 feature 同時在不同階段推進時,狀態散落在各文件 breadcrumb 的「狀態」欄、requirement 的「未解問題/仍待 Stage X 拍板」、breadcrumb 的「(尚未建立)」、spec-codes.mdaudit/ 的 ❌ —— 沒有一處能一眼看出「誰卡在第幾階段、下一步缺什麼」。

spec-dashboard skill 掃描上述既有欄位,彙整成根目錄 dashboard.md。它與 Consistency Audit 是不同職責:

Consistency AuditSpec Dashboard
觸發mid-stage edit 後、簽核前想看/刷新整體進度時
範圍單一改動的跨階段上下游全 feature 的階段彙整
產出audit/{feature}-{date}-{stage}.mddashboard.md
判斷初判 ✅/⚠️/❌ 一致性不判一致性,只彙整既有狀態

dashboard.md 結構:自動區(階段總覽表 + 擷取式 todo,skill 全量重生)+ 手寫區(人手寫備註,skill 原樣保留、絕不覆寫)。

AI vs 人

動作主導
掃描來源檔、判階段、擷取 todo、重生自動區AI
手寫區備註、看板上的取捨判斷

設計原則:dashboard 是衍生視圖,不是第二真相源。自動區每一格都回指既有欄位;skill 不裁定、不改任何來源 spec、不 cascade。讀不到某欄位就標 ? 交回人,不編造。


變更管理速查

場景路徑必跑 Audit?
需求真的變了A. top-down cascade否(本來就逐層改)
熟手直接編輯下游文件B. mid-stage edit + Audit
只改 Code 不改文件禁止
Code refactor 不變行為允許,但 commit message 要標註,且 § 註解仍要對得上

核心紅線:任何路徑都不允許跳過文件直接動 Code。一旦發生,這個 feature 的可追溯性就壞了。