Skip to content

用 GitHub Issues 驅動 AI 全流程開發:從需求討論到 macOS 成品

在這篇教程中,我們會完整走一遍這樣的過程:先把一個還比較模糊的想法告訴 AI,再和它一起把需求討論清楚;接著讓 AI 寫出需求文檔、在 GitHub 上拆好任務,最後按照任務順序把軟件真正做出來。

這種方法叫 Spec 驅動開發。Spec 是“需求規格”的簡稱。它不是一份寫完就放在角落里的文檔,而是後續拆任務、寫代碼、測試和審查時共同遵守的依據。需求發生變化時,先更新 Spec,再繼續實現,而不是只在聊天里臨時補一句。

和上一篇有什麼區別?

《從 Vibe Coding 到 Spec Coding》主要解釋為什麼規範會成為 AI 開發的核心;本文不再重復理論,而是用一個真實 GitHub 倉庫演示如何把規範變成 Issues、任務依賴、提交、測試和最終成品。

我們不會停在“講概念”這一步。文章里的倉庫、Issues、代碼、測試和截圖都來自一次真實開發。最開始,我們只有下面這一句話:

我想做一個 macOS 上的 CRM,用來管理聯繫人關係,幫助我梳理人脈。可以先使用假數據。

最後,我們得到了一個名為 Relationship Compass 的原生 macOS 應用。它可以搜索和篩選聯繫人、維護關係檔案、導入 CSV、記錄互動,並自動算出下一次應該聯繫誰。

最終完成的 Relationship Compass 聯繫人管理界面

你可以直接查看這次實踐產生的公開 GitHub 示例倉庫。倉庫只使用假數據,裡面保留了需求文檔、GitHub Issues、提交記錄、源代碼和測試。

1. 先理解:什麼是 Spec 驅動開發

很多人第一次用 AI 寫代碼時,會採用下面這種方式:

text
告訴 AI 想做什麼 → AI 寫代碼 → 發現不對 → 再補一句要求 → 繼續修改

做一個小頁面時,這種方式通常夠用。但項目變大後,很容易遇到三個問題:

  1. 前面討論過的要求,過幾輪對話後被忘掉了;
  2. AI 一次改很多文件,你不知道現在到底完成了多少;
  3. 功能看起來能運行,卻沒人逐條檢查它是否真的符合最初需求。

Matt Pocock 的 Skills 就是為瞭解決這些問題。這裡的 Skill 可以先簡單理解成“寫給 AI 的標準工作流程”。它不會只告訴 AI 寫哪一段代碼,而是規定 AI 在每個階段應該先做什麼、產出什麼、什麼時候停下來讓你確認。

1.1 它和直接讓 AI 寫代碼有什麼不同

普通的 AI 輔助開發,常常把聊天記錄當成唯一需求來源。Spec 驅動開發則會在寫代碼前,先把已經確認的要求保存成倉庫里的正式文檔。後續每一步都回到這份文檔檢查。

直接從聊天開始寫Spec 驅動開發
AI 主要依賴當前聊天內容AI 以倉庫中的 Spec 為主要依據
想到一個要求就直接補一句先確認需求,再更新 Spec 和任務
進度通常只存在於 AI 的總結里進度保存在 GitHub Issues 和提交中
完成後主要看“能不能運行”完成後逐條對照 Spec 檢查有沒有漏項

因此,Spec 驅動開發的重點並不是“多寫一份文檔”,而是讓需求從聊天中的一句話,變成整個開發過程都能引用、更新和驗證的共同標準。

1.2 GitHub 在這條流程中具體做什麼

一次聊天只能保存“我們剛才說了什麼”,GitHub 則可以長期保存“項目已經決定了什麼、接下來要做什麼、哪些事情已經完成”。

在這篇教程里,GitHub 不只是存放源代碼的網盤。它同時承擔三種角色:

  1. 項目檔案室:保存 Spec、項目用詞和重要技術決定;
  2. 任務看板:用 Issues、優先級和依賴關係表示工作順序;
  3. 完成記錄:用提交、測試結果和關閉狀態證明每張任務是怎樣完成的。
GitHub 中的內容用大白話解釋本例中的實際文件或記錄
需求文檔(Spec)這個軟件最後要做到什麼specs/relationship-compass-mvp.md
Issue一張可以獨立完成的任務卡#2 Browse sample Contacts
任務依賴哪張任務卡必須先完成#3 要等待 #2
Commit這一輪具體改了什麼feat: browse sample contacts
Tests已經完成的功能有沒有被後續修改弄壞swift test
架構決策記錄(ADR)為什麼選擇這種技術,而不是另一種docs/adr/0002-native-swiftui-macos.md

下面這張表更具體地展示了 GitHub 在每個階段發生的變化:

開發階段GitHub 中發生什麼Relationship Compass 的實際結果
需求討論結束把統一用詞和重要決定寫入倉庫CONTEXT.md 和 2 份 ADR
生成 Spec保存需求文件,並創建一張總 Issuespecs/relationship-compass-mvp.mdIssue #1
拆分任務創建實現 Issues,添加優先級和前置依賴Issues #2–#6
逐張實現每完成一張 Issue,就產生對應提交並運行測試5 個主要功能提交
完成任務移除 ready-for-agent,添加 completed-by-agent,關閉 Issue#2–#6 全部關閉
最終審查把審查修復繼續提交,確認無遺漏後關閉總 Issue3 個修復提交,#1 最終關閉
mermaid
flowchart LR
  A["討論結果"] --> B["倉庫中的 Spec"]
  B --> C["GitHub 總 Issue #1"]
  C --> D["實現 Issues #2–#6"]
  D --> E["優先級 + 前置依賴"]
  E --> F["代碼提交 + 測試"]
  F --> G["關閉實現 Issue"]
  G --> H["最終審查"]
  H --> I["關閉總 Issue"]

所以 GitHub 在這裡更像一塊“有記憶的開發工作台”。AI 每次開始工作前都可以先讀取當前狀態;人也可以隨時打開倉庫,看到需求、進度、代碼和驗證結果,而不必翻完整聊天記錄。

1.3 整條路線先看一遍

這次實踐會依次使用五個命令:

  1. grill-with-docs:先和 AI 討論,把“我大概想做什麼”變成雙方都理解的明確範圍;
  2. to-spec:把已經確認的討論整理成一份正式需求文檔;
  3. to-tickets:把大需求拆成幾張有先後順序的 GitHub Issues;
  4. implement:讓 AI 從第一張可以開始的任務卡出發,邊測試邊實現;
  5. code-review:完成後再檢查兩遍,一遍看代碼質量,一遍看有沒有漏掉需求。
text
想法 → 討論清楚 → 寫成文檔 → 拆成任務 → 逐個實現 → 檢查結果

現在不需要記住所有英文名詞。你只要先記住一件事:我們不再讓 AI 拿到一句話就馬上寫完整項目,而是先把需求說清楚,再讓它按有記錄、有順序、可檢查的方式開發。

2. 開始之前要準備什麼

如果你只想理解這套工作方法,可以直接繼續往下讀。如果你想自己跟著做一遍,需要提前準備:

  1. 一個 GitHub 賬號;
  2. 已經登錄的 GitHub CLI,也就是終端里的 gh 命令;
  3. Node.js 18 或更高版本,用來安裝 Skills;
  4. 一個能夠讀取項目 Skills 的編程 AI 工具;
  5. 如果要運行本文的 macOS 示例,還需要一台 Mac 和 Xcode。

2.1 安裝 Matt Pocock 的 Skills

先在你準備開發的項目目錄中打開終端,然後運行:

bash
npx skills@latest add mattpocock/skills

安裝過程可能會詢問你要把 Skills 安裝到哪裡。如果希望直接安裝全部內容、不逐項確認,可以使用:

bash
npx skills@latest add mattpocock/skills -y

本次實踐實際安裝了 35 個 Skills。安裝完成後,它們會出現在項目的 .agents/skills/ 目錄中。本文重點使用的是下面這條主流程:

text
grill-with-docs → to-spec → to-tickets → implement → code-review

這裡比最初流傳的“四步流程”多了最後的 code-review。原因很簡單:軟件“能運行”不等於“已經按要求做好”。完成實現後,再單獨檢查一次,往往能發現測試和第一次開發都沒有注意到的問題。

項目特別大時怎麼辦?

如果你的項目大到連“應該先討論哪些問題”都不清楚,可以先使用 wayfinder。它會幫助你列出還沒有做出的關鍵決定,再回到本文這條主流程。第一次練習時不需要使用它。

相關說明可以查看 AI Skills for Real EngineersSkills v1.1 更新說明

2.2 創建 GitHub 示例倉庫

先確認終端已經登錄 GitHub:

bash
gh auth status

如果還沒有登錄,再運行:

bash
gh auth login -h github.com

接著創建一個名為 relationship-compass-macos 的公開倉庫,並把當前項目推送上去:

bash
gh repo create relationship-compass-macos \
  --public \
  --source . \
  --remote origin \
  --push

這幾個參數分別表示:倉庫公開、使用當前文件夾、把 GitHub 地址保存為 origin,並立即推送當前代碼。

真實聯繫人數據不要放進公開倉庫

本文為了方便讀者查看完整案例,使用的是公開倉庫和固定假數據。如果你要開發自己的聯繫人管理工具,請改用 --private,並在推送前檢查樣例文件、日誌和 Git 歷史中是否包含真實姓名、郵箱或關係備注。

2.3 準備任務標籤

GitHub 標籤就像貼在任務卡上的彩色便簽。它能告訴 AI 一張 Issue 是否可以開始,以及它有多重要。本例實際使用了下面幾類標籤:

標籤表示什麼
ready-for-agent需求已經寫清楚,AI 可以開始做
priority:P0最先完成,否則後面的功能無法繼續
priority:P1核心功能,但需要等待前置任務
priority:P2收尾、文檔和完整驗證
completed-by-agent已經由 AI 實現並驗證完成

3. 這次要做一個什麼軟件

我們的例子是一個 macOS 聯繫人關係管理工具。它不是用來追蹤銷售業績,而是幫助個人記住:我認識誰、我們是什麼關係、上次聊了什麼、什麼時候適合再次聯繫。

之所以選擇這個例子,是因為它足夠小,可以在一篇教程里走完;同時又包含真實軟件常見的多個環節:界面、數據導入、本地保存、搜索篩選、日期計算和自動化測試。

第一版只做下面這些事情:

  • 內置 6 個假聯繫人,打開應用就能看到效果;
  • 支持搜索聯繫人,並按關係強度和圈子篩選;
  • 可以編輯組織、角色、郵箱、備注和跟進週期;
  • 可以從 UTF-8 CSV 文件導入聯繫人;
  • 可以記錄一次互動,並自動計算下一次跟進日期;
  • 數據保存為本地 JSON 文件,下次啓動時可以恢復。

第一版暫時不做雲同步、AI 人脈評分,也不讀取 macOS 系統通訊錄。這樣可以先把最重要的使用閉環做完整,同時避免一開始就申請敏感權限。

4. 第一步:用 grill-with-docs 把需求聊清楚

grill-with-docs 可以理解為“先把需求問透”。它不會在收到第一句話後馬上寫代碼,而是像一位有經驗的產品和技術夥伴一樣,繼續問你幾個真正會影響結果的問題。

進入新倉庫後,像平時說話一樣描述目標即可,不需要提前寫正式的產品文檔:

🙋 你
/grill-with-docs

我想實現一個 macOS 上的 CRM,可以管理我導入的聯繫人關係,幫助我梳理人脈。可以先使用假數據。

✨ Agent

好,我們先不急著寫代碼。我會和你一起把“第一版做什麼、不做什麼、數據放在哪裡”討論清楚。遇到需要選擇的地方,我會先解釋區別,再給出推薦。

這一步看起來像“多聊了一會兒”,其實是在提前避免返工。比如,要不要讀取系統通訊錄,會影響隱私權限;要不要雲同步,會影響是否需要賬號和服務器。這些問題如果等代碼寫到一半才決定,改動會更大。

4.1 對話如何逐步收斂

下面是本例中最關鍵的幾輪對話。你會發現,用戶不需要懂 SwiftUI、數據庫或測試框架,只需要說清楚自己想要的使用體驗。

✨ Agent

我建議首版採用原生 SwiftUI 和本地優先架構,這樣能獲得真正的 macOS 體驗,又不必先建設賬號和服務器。先確認三件事:是否直接讀取系統通訊錄?是否需要雲同步?首版準備如何導入數據?

🙋 你

首版使用原生 SwiftUI,只導入 UTF-8 CSV,不直接讀取系統通訊錄。數據全部保存在本地,也不需要賬號、聯網和後端。

✨ Agent

明白。那它更像“私人關係維護工具”,而不是銷售漏斗。聯繫人檔案除了姓名、組織、角色和郵箱,還需要哪些關係信息?怎樣才算形成一個最小閉環?

🙋 你

我需要關係強度、圈子、備注和互動記錄;還想看到哪些人該聯繫了。可以按最近一次互動和我設置的跟進週期計算,不需要把私人關係做成銷售評分。

✨ Agent

建議把從未記錄過互動的聯繫人直接放進“待跟進”列表;記錄一次互動後,再按你設置的天數計算下一次日期。首版使用 6 個固定假聯繫人,並為搜索、導入、保存和日期計算編寫自動化測試。這個範圍可以嗎?

🙋 你

可以,就按這個範圍。先不要做雲同步、AI 人脈評分和系統通訊錄權限。我們已經達成共識,可以生成規格了。

在本例中,我們確定了以下範圍:

決策選擇原因
產品形態macOS 14+ 原生 SwiftUI獲得原生文件選擇、鍵盤操作和輔助功能
首版數據6 個確定性的假聯繫人不要求用戶一開始就交出敏感數據
導入格式UTF-8 CSV容易準備、檢查和修復
數據保存本地 JSON簡單、透明、不需要後端
關係強度Close / Active / Dormant避免把私人關係變成銷售評分
核心行為搜索篩選、資料維護、互動記錄、待跟進列表構成可驗證的最小閉環
隱私邊界不讀取系統通訊錄、不聯網首版不申請敏感權限
測試入口RelationshipStore 對外提供的功能測試用戶能看到的結果,不依賴內部寫法

4.2 同步建立項目語言

討論過程中,一些詞很容易產生歧義。比如 Contact 既可以翻譯成“聯繫人”,也可能被 AI 理解成“銷售線索”;Follow-up 可能被理解成任務、提醒或通知。

因此,我們把已經確認的項目用詞寫進 CONTEXT.md。下面這段的意思是:Interaction 專門表示一次有日期的交流記錄,Follow-up 專門表示根據最近交流推算出的下次聯繫日期。

markdown
**Interaction**:
A dated note that records a meaningful exchange with a Contact.
_Avoid_: Activity, event, touchpoint

**Follow-up**:
A suggested next connection date derived from the latest Interaction
and the Relationship Profile's rhythm.
_Avoid_: Task, reminder, notification

這不是為了把文檔寫得更正式,而是為了讓後面的代碼、測試和 Issue 一直使用同一套說法,避免 AI 一會兒寫 Contact,一會兒又改成 LeadCustomer

4.3 只記錄真正重要的 ADR

ADR 是“架構決策記錄”的縮寫。你可以把它理解成一張很短的說明卡:記錄一個重要選擇,以及當時為什麼這樣選。這樣幾個月後再看到代碼,不會疑惑“為什麼沒有用另外一種方案”。

本例只記錄了兩條真正重要的決定:

  • 0001-local-first-private-data.md:關係信息留在本地,不申請通訊錄權限;
  • 0002-native-swiftui-macos.md:使用原生 SwiftUI,而不是 Electron 或 Web 殼。

ADR 不需要很長,也不用為每個小選擇都寫一份。只有那些以後很難改、而且存在明顯取捨的決定,才值得單獨記錄。

4.4 確認共享理解

討論結束時,AI 會問你是否已經達成共識。只有你明確確認後,流程才進入下一步。

這個暫停很重要。此時改一句需求只需要幾秒;如果等 20 個文件都寫完才發現方向錯了,就要花更多時間返工。

完成這一步後,你應該得到什麼?

  • 一份明確的第一版功能範圍;
  • 一份“不做什麼”的清單;
  • 統一的項目用詞;
  • 少量真正重要的技術決定;
  • 你對最終方向的一次明確確認。

這時還沒有開始實現功能,是正常的。

GitHub 在這一步做什麼?

需求討論發生在你和 AI 的對話中,但確認後的結果不能只留在聊天里。本例把統一用詞寫進 CONTEXT.md,把兩項重要技術選擇寫進 docs/adr/,然後提交到 GitHub。這樣下一次會話重新打開倉庫時,AI 可以直接讀取這些決定。

此時 GitHub 負責“保存已經確認的上下文”,還沒有開始創建實現任務。

5. 第二步:用 to-spec 寫成需求文檔

需求已經聊清楚了,下一步是把聊天內容整理成一份以後可以反復查看的正式文檔。這裡的 Spec 就是“需求規格”:它應該講清楚軟件解決什麼問題、用戶可以完成哪些操作、哪些內容不在第一版範圍內,以及最後怎樣判斷功能已經做好。

你只需要告訴 AI:把剛才確認的內容寫下來。

🙋 你
/to-spec

根據剛才的討論生成完整規格,保存到倉庫,併發布到 GitHub Issues,標籤使用 ready-for-agent。

✨ Agent

收到。我會直接整理剛才已經確認的內容,不會再從頭問一遍。完成後,我會把文檔保存進倉庫,並創建一張總的 GitHub Issue 作為入口。

to-spec 會綜合剛才的對話、項目用詞和架構決定,生成一份結構化文檔。本例最終得到的規格包括:

text
要解決的問題
第一版解決方案
24 條用戶故事
已經確認的技術選擇
測試方式
第一版明確不做的內容
其他補充說明

完整規格保存在 specs/relationship-compass-mvp.md,同時發佈為 GitHub Issue #1。以後無論是人還是 AI,都可以從這張總 Issue 找到完整需求。

GitHub 在這一步做什麼?

同一份需求會以兩種方式存在:倉庫中的 Markdown 文件便於版本管理和代碼審查;GitHub Issue #1 則作為項目入口,方便跟蹤狀態和關聯後續任務。

如果需求後來發生變化,應該先修改 Spec 文件並留下提交,而不是只在新聊天里補充一句。這樣 GitHub 會保留“需求為什麼變了、什麼時候變了”的歷史。

5.1 好 Spec 要描述行為,而不是文件

一份好規格應該描述“用戶最後能做到什麼”,而不是過早指定“必須創建哪個文件”。例如,本例有一條用戶故事是:

作為用戶,我希望從未記錄過互動的聯繫人也出現在待跟進列表中,這樣剛導入的人不會被悄悄忘掉。

這句話包含三個信息:誰需要它、希望發生什麼、為什麼有價值。它沒有規定 Swift 文件叫什麼,所以以後即使重構代碼,這條需求仍然成立。

5.2 提前說明怎樣驗證

規格還要提前說明“做完後怎樣證明它是對的”。本項目把 RelationshipStore 對外提供的功能當作主要測試入口,自動檢查:

  • 樣例數據初始化;
  • 搜索與組合篩選;
  • CSV 導入、校驗與去重;
  • JSON 保存和恢復;
  • 關係檔案編輯;
  • 互動記錄的時間順序;
  • 指定日期下的下一次跟進計算。

這些測試只關心用戶最終能觀察到的結果,不關心內部某個小函數被調用了幾次。這樣以後整理代碼結構時,測試不會因為內部寫法變化而全部失效。

完成這一步後,你應該看到什麼?

倉庫中會出現一份可以直接閱讀的 Spec,GitHub 上會出現一張對應的總 Issue。此時你應該能逐條回答:“第一版到底要做什麼?什麼算完成?哪些功能明確不做?”

6. 第三步:用 to-tickets 拆成有順序的任務

一份 Spec 可能包含幾十條要求,直接讓 AI “一次全部實現”仍然很冒險。to-tickets 的作用,就是把大目標拆成幾張能夠單獨完成、單獨檢查的 GitHub 任務卡。

接著輸入:

🙋 你
/to-tickets

根據 Relationship Compass 的第一版需求文檔拆分 GitHub Issues。每張任務都要交付一個可以獨立演示的小功能,並寫清楚優先級、完成標準和前置任務。

✨ Agent

我會先把任務清單和先後順序展示給你。你確認沒有漏項後,我再創建 GitHub Issues,並寫清楚每張任務卡的完成標準和前置任務。

拆任務時,最容易犯的錯誤是按技術類別分工:一張票只建數據模型,另一張票只寫界面,最後一張票才補測試。這樣前幾張票做完時,用戶仍然看不到任何可以使用的功能。

更合適的方法叫 縱向切片。你可以把它想象成切蛋糕:每一塊都同時包含蛋糕胚、奶油和水果。對應到軟件里,就是每張 Issue 都盡量同時包含必要的數據、界面和測試,關閉一張就能多演示一個完整的小功能。

本例拆成 5 張實現票:

Issue優先級完成後可以看到什麼前置任務狀態
#2 Browse sample ContactsP0可啓動的應用、樣例聯繫人、搜索和詳情已關閉
#3 Import and persist private Contact dataP0CSV 導入去重、JSON 打開保存#2已關閉
#4 Organize Relationship ProfilesP1編輯資料、關係強度、圈子與篩選#2已關閉
#5 Record Interactions and plan Follow-upsP1互動歷史與待跟進列表#4已關閉
#6 Polish and verify the MVPP2文檔、錯誤狀態、打包和完整驗證#3、#5已關閉
mermaid
flowchart LR
  T1["P0 · Browse sample Contacts"] --> T2["P0 · Import and persist"]
  T1 --> T3["P1 · Organize Profiles"]
  T3 --> T4["P1 · Interactions and Follow-ups"]
  T2 --> T5["P2 · Polish and verify"]
  T4 --> T5

GitHub 在這一步做什麼?

to-tickets 會把 Spec 中的大目標發佈為獨立 Issues,並給它們添加 priority:P0priority:P1priority:P2。本例還使用了 GitHub 原生的 Blocked by 依賴關係,所以 #6 會明確等待 #3 和 #5,而不是只在正文里寫一句“以後再做”。

這一步之後,GitHub 從“需求檔案室”變成了真正的任務看板。

6.1 任務為什麼要有先後順序

表格里的 Blocked by 表示“必須等待誰先完成”。例如,應用還不能顯示聯繫人時,就不適合先開發聯繫人資料編輯。

流程剛開始時,只有 #2 可以動手。#2 完成後,#3 和 #4 都具備了前置條件;#5 必須等 #4 完成;最後的 #6 則要等導入保存和互動跟進兩條功能線都完成。

Skills 把“所有前置任務已經完成、現在可以開始”的那幾張票稱為 任務前沿。名字聽起來有些抽象,其實就是“當前沒有被卡住的任務”。

優先級和依賴是兩回事:P0 表示很重要,依賴關係則表示現在能不能做。一張很重要的任務,如果依賴的基礎功能還沒完成,也需要先等待。

6.2 不要拆成橫向任務

下面這種按技術層拆分的方法不適合讓 Agent 連續交付:

text
創建所有數據模型 → 創建所有 Store → 創建所有 UI → 最後補測試

因為任何一張中間任務完成後都無法單獨使用,要到最後才知道各層能不能真正連起來。更好的拆法是:

text
先讓“瀏覽樣例聯繫人”從模型到 UI 完整工作並通過測試,
再增加“導入與保存”的完整路徑。

完成這一步後,你應該看到什麼?

GitHub 上會出現 5 張實現 Issue。每張 Issue 都有優先級、驗收標準和前置任務。你不需要自己猜下一步做什麼,只要從當前沒有被阻塞的第一張任務開始。

7. 第四步:用 implement 逐張任務實現

任務已經拆好後,才正式進入寫代碼階段。implement 會讀取 GitHub Issues,找到當前沒有被前置任務卡住、同時優先級最高的那一張,然後只圍繞這張票工作。

輸入:

🙋 你
/implement

根據優先級和依賴關係逐個實現所有 ready-for-agent Issues,從第一個未被阻塞的 Issue 開始。每張票使用 TDD,在完成後運行類型檢查和對應測試並提交。

✨ Agent

我會一次只處理一張可以開始的任務。每張任務都先寫測試,再完成代碼、運行構建並提交。全部完成後,我會繼續檢查代碼質量和需求完成情況。

本例中,每張任務完成後都會留下一個主要提交。這樣如果某一輪出現問題,可以準確知道是哪張任務帶來的修改。

GitHub 任務主要提交
#2 瀏覽樣例聯繫人9d9d7bd
#3 導入並保存聯繫人935750b
#4 維護關係檔案329bd67
#5 記錄互動和跟進83f4af6
#6 打磨、打包和驗證3ae0bbf
審查後修復cbad10211361cad1c83be

GitHub 在這一步做什麼?

Agent 不會隨便挑一項功能開始寫。它先讀取 ready-for-agent、優先級和 Blocked by,找到當前可以執行的 Issue。完成後,把提交哈希和測試結果寫回對應 Issue,移除 ready-for-agent,添加 completed-by-agent,再關閉這張任務。

因此,GitHub 上的 Issue 狀態就是項目的真實進度,而不是一份需要手動維護、很快就會過期的旁觀清單。

7.1 每張任務都先證明“現在還不行”

本例使用 TDD,也就是“測試驅動開發”。這個名字聽起來很專業,但做法並不複雜:先寫一個描述正確結果的測試,確認它現在會失敗;再補上最少的代碼,讓測試變成通過。

以 CSV 導入這張任務為例,Agent 實際按照下面的順序工作:

  1. 先寫一個測試:同一份 CSV 導入兩次,聯繫人數量不能翻倍;
  2. 運行測試,確認當前版本確實還做不到;
  3. 實現 CSV 讀取和去重,讓這個測試通過;
  4. 再補一個測試:CSV 表頭錯誤時,原來的聯繫人不能被破壞;
  5. 修正實現,重新運行這一組測試和完整構建;
  6. 提交代碼,關閉當前 Issue,再領取下一張沒有被阻塞的任務。

本項目使用 Swift Testing:

bash
swift test --filter RelationshipStoreTests
swift build
swift test

swift build 負責確認整個項目可以編譯,swift test 負責運行全部自動化測試。最終共有 13 項行為測試,完整構建和測試都通過。

7.2 打開真實代碼看一眼

下面是本例真正提交到倉庫的 RelationshipStore.importCSV,不是為了截圖臨時寫的示例代碼。

這段代碼做了四件事:讀取 UTF-8 CSV、檢查表頭、尋找重復聯繫人、準備導入結果。它會先在一份候選數據上完成全部處理,只有所有行都合法時才替換當前聯繫人列表。因此,文件中途出錯也不會讓應用留下“只導入一半”的狀態。

Xcode 中的 CSV 導入、表頭校驗與安全去重實現

對應的 RelationshipStoreTests 會把同一份 CSV 連續導入兩次,確認第二次只更新已有聯繫人,而不是再新增一份。測試還覆蓋了重復表頭和帶 UTF-8 BOM 的文件等邊界情況。

Swift Testing 中關於重復導入和異常表頭的公開行為測試

完成這一步後,你應該看到什麼?

GitHub 上的實現 Issues 會按照依賴順序逐張關閉;倉庫里會出現對應提交;應用功能會一塊一塊增加;每輪都能用測試和構建命令確認當前版本仍然可用。

8. 第五步:用 code-review 檢查有沒有遺漏

所有 Issues 都關閉,並不代表工作已經結束。第一次實現時,AI 的注意力主要放在“把當前任務做通”,仍然可能出現兩類問題:代碼越來越難維護,或者有些需求表面上做了、實際還有缺口。

因此,當前流程在實現完成後還會運行 code-review。它分成兩次獨立檢查。

8.1 第一遍:檢查代碼是否健康

第一遍只看代碼本身,不重新討論產品需求。它會檢查:

  • 文件和類型的名字是否容易理解;
  • 同一段邏輯是否在多個地方重復;
  • 一個界面文件是否承擔了太多工作;
  • 修改一個小功能是否需要同時改很多無關位置;
  • 代碼是否遵守倉庫 AGENTS.md 中的約定。

本例第一次檢查時,就發現 SwiftUI 主界面過大,而且“跟進天數”只是一個普通整數,很容易繞過最小一天的校驗。隨後我們拆分了界面職責,並把跟進週期變成一個會主動校驗的數據類型。

8.2 第二遍:逐條檢查需求是否真的完成

第二遍不評價代碼寫得漂不漂亮,而是重新打開 Spec 和所有 Issues,逐條核對:

  • 有沒有遺漏的要求;
  • 有沒有只做了一半的功能;
  • 界面看起來存在,但實際行為是否正確;
  • 有沒有擅自增加不在第一版範圍內的功能。

這次審查並不是走形式,它找出了第一輪測試沒有覆蓋的真實問題:

  • CSV 中出現兩個同名表頭時,應用會報運行時錯誤,而不是安全提示;
  • 沒有郵箱的聯繫人,無法通過“姓名+組織”識別為同一個人;
  • 普通聯繫人列表已經篩選了,但“待跟進”列表沒有使用同樣的篩選條件;
  • 數據雖然能保存,卻不會在下次啓動時自動恢復;
  • 詳情頁沒有明確顯示計算出來的下一次跟進日期。

我們先為這些問題補上測試,再修正代碼,然後重新執行兩遍檢查。最終,代碼質量檢查和需求完成度檢查都通過。

這裡最值得記住的是:測試全部通過,只能證明“已經寫進測試的行為”沒有出錯,不能自動證明最初需求一條都沒有漏。 所以最後仍然需要重新對照 Spec。

完成這一步後,你應該看到什麼?

審查發現的問題會變成新的修復提交;完整測試會再次通過;兩份審查結果都明確給出通過結論。到這裡,才適合把整個 Spec 標記為完成。

GitHub 在這一步做什麼?

審查發現的問題繼續以獨立提交保留在倉庫中。確認全部修復後,#2–#6 的完成評論會寫明主要提交和驗證結果;最後再關閉總需求 Issue #1。這樣打開 Issues 頁面 就能從任務一直追溯到代碼和測試。

9. 最終得到的軟件

經過需求討論、文檔整理、任務拆分、逐張實現和兩輪審查後,我們最終得到了 Relationship Compass

它不是一張界面效果圖,也不是一堆無法運行的示例代碼,而是一個可以編譯、測試、打包並雙擊打開的原生 macOS 應用。

交付項最終結果
GitHub 項目管理1 張總需求 Issue 和 5 張實現 Issues,全部關閉
實現過程9 個小步提交,按照任務依賴逐個完成
自動化驗證13/13 項行為測試通過,完整項目可以編譯
最終審查代碼質量與需求完成度兩項檢查均通過
可運行產物腳本可以生成 Relationship Compass.app
數據邊界數據只保存在本地,不讀取系統通訊錄,也不上傳聯繫人關係

完成後的產品包含:

  • 6 個固定的假聯繫人;
  • 按姓名、組織、角色、郵箱和圈子搜索;
  • 按關係強度和圈子組合篩選;
  • 編輯聯繫人的關係檔案;
  • UTF-8 CSV 導入、表頭校驗與安全去重;
  • 本地 JSON 打開、保存和下次啓動恢復;
  • 互動記錄與按時間排序的歷史;
  • 根據最近互動和跟進週期計算待跟進聯繫人;
  • 原生 macOS .app 打包腳本;
  • 13 項自動化行為測試。

9.1 搜索與組合篩選

在右上角輸入 Founder 後,列表會從 6 位樣例聯繫人縮小到 Maya Chen。左上角還可以繼續選擇關係強度和圈子。普通聯繫人列表與待跟進列表使用同一套篩選規則,不會出現一邊篩選了、另一邊仍顯示全部聯繫人的情況。

按角色搜索聯繫人,只保留匹配 Founder 的 Maya Chen

9.2 編輯關係檔案

選擇聯繫人後,可以修改組織、角色、郵箱、關係強度、圈子、跟進週期和備注。應用會自動清理重復圈子,並檢查跟進週期至少為一天。保存後的內容會立即反映到搜索和篩選結果中。

Relationship Compass 的聯繫人關係檔案編輯界面

9.3 記錄互動並計算下次跟進

為 Maya 記錄一次 2026 年 8 月 9 日的互動後,應用根據 30 天的跟進週期,把下一次聯繫日期更新為 2026 年 9 月 8 日。互動內容會出現在歷史記錄中;日期到期後,這位聯繫人會自動進入“待跟進”區域。

記錄互動後自動計算出的下一次跟進日期

新記錄已經出現在 Interaction History 中

這些界面背後的關鍵行為都有對應測試。例如,同一份 CSV 重復導入不會產生重復聯繫人;錯誤表頭不會破壞原有數據;保存和重新打開後,所有字段仍然一致;保存文件損壞時,應用會安全回到樣例數據;搜索和兩個篩選條件也可以一起使用。

如果你使用 Mac,可以按照下面的順序下載、測試和打包這個項目:

bash
git clone https://github.com/sanbuphy/relationship-compass-macos.git
cd relationship-compass-macos
swift build
swift test
./scripts/package-app.sh
open "dist/Relationship Compass.app"

前兩條命令下載代碼並進入項目目錄;swift buildswift test 分別檢查編譯與測試;打包腳本會在 dist 目錄生成應用,最後一條命令負責打開它。

示例不是生產版通訊錄

示例有意不讀取 macOS 系統通訊錄、不上傳關係數據,也不提供 AI 人脈評分。真實產品如果增加雲同步、聯繫人權限、加密或 AI 分析,需要重新討論隱私邊界,並記錄新的架構決定。

10. 可直接複製的完整流程

如果你想在自己的項目里復現這套流程,可以從下面四段輸入開始。你不必原樣照抄產品名稱,但建議保留“先確認、再寫文檔、按依賴實現、最後審查”這些約束。

10.1 需求討論

🙋 你 · 可直接複製
/grill-with-docs

我想實現一個 macOS 上的 CRM,可以管理我導入的聯繫人關係,幫助我梳理人脈。可以先使用假數據。

請和我繼續討論第一版要做什麼、不做什麼、數據放在哪裡、採用什麼技術,以及最後怎樣驗證。每次只問當前最關鍵的問題;遇到選擇時先解釋區別並給出推薦。在我明確確認之前,不要開始寫代碼。

10.2 生成 Spec

🙋 你 · 可直接複製
/to-spec

把剛才已經確認的討論整理成一份完整需求文檔,保存到倉庫,併發布為一張 GitHub 總 Issue,添加 ready-for-agent 標籤。

不要重新問已經確認的問題。文檔要寫清楚用戶能完成哪些操作、怎樣驗收、第一版明確不做什麼;技術部分記錄穩定決定,不要堆容易過期的文件路徑。

10.3 拆分 Issues

🙋 你 · 可直接複製
/to-tickets

根據剛才的需求文檔拆分 GitHub Issues。不要把數據、界面和測試完全分開;每張任務都要盡量交付一個可以獨立演示的小功能。

每張 Issue 寫清楚優先級、完成標準和前置任務。先把任務清單與依賴圖展示給我,確認後再發佈到 GitHub。

10.4 自動實現

🙋 你 · 可直接複製
/implement

根據優先級和前置任務,實現所有 ready-for-agent Issues。每次只處理一張當前可以開始的任務;先寫描述正確結果的測試,再完成實現,並經常運行測試和完整構建。每張任務完成後單獨提交。

所有 Issues 完成後,分別檢查代碼質量和需求完成度。修復發現的問題,重新運行全部測試,直到兩項檢查都通過。

11. 什麼時候適合“梭哈”

這裡的“梭哈”不是指完全不看過程,而是指:當需求和安全邊界已經確認後,讓 AI 沿著任務清單連續工作,不必每寫一個函數都停下來等待指令。

這條流程比較適合:

  • 範圍可以通過討論收斂的 MVP;
  • 有明確用戶行為和驗收標準的後台、App 或網站;
  • 可以通過測試或構建命令驗證的倉庫;
  • 希望 Agent 跨多個會話持續工作的項目。

它不太適合那些需求每小時都在變化、無法通過測試或構建驗證,或者會直接操作生產數據的任務。

即使讓 AI 連續實現,下面幾個節點仍然應該由你親自確認:

  1. 需求討論結束時,確認第一版範圍沒有理解錯;
  2. 創建 Issues 前,確認任務沒有漏項,先後順序合理;
  3. 涉及付費、生產部署、刪除數據、賬號權限和隱私時,確認具體外部操作;
  4. 完成後親自打開真實界面,檢查構建產物和審查結果。

真正可靠的自動開發,不是把所有決定都交出去,而是你負責目標、邊界和最終驗收,AI 負責把已經確認的事情穩定地執行下去。

總結

到這裡,我們已經從一句模糊想法出發,完成了需求討論、正式文檔、GitHub 任務拆分、逐張實現、測試、審查和應用打包。

這套方法最重要的不是記住幾個斜槓命令,而是把開發過程變成一條隨時可以查看、暫停和繼續的路線:

text
模糊想法
  ↓ grill-with-docs
明確範圍 + 統一用詞 + 重要技術決定
  ↓ to-spec
可以逐條驗收的需求文檔
  ↓ to-tickets
有優先級和先後順序的 GitHub 任務
  ↓ implement
逐張任務實現、測試和提交
  ↓ code-review
檢查代碼質量 + 檢查需求完成度

可構建、可驗證的軟件

當一段聊天結束後,需求文檔、Issues、依賴關係、提交和測試仍然留在 GitHub 中。下一次繼續開發時,AI 不需要從頭猜測你想做什麼,而是可以沿著這些記錄繼續往前走。

你可以把這條流程遷移到網站、後台系統、移動應用或自己的工作工具中。先選一個範圍不大的真實需求,完整走通一次,再逐漸把它用到更複雜的項目里。

參考資料