Communitygithub.com

gustavorana25/c4-plan

架構的視覺層(C4 風格)以可導覽圖表呈現,包含逐步流程。兩種用途:(1) 實作計畫:在計畫存在後、執行前,讓人類檢視計畫如何影響現有架構,提問並在聊天中批准前要求修改。(2) 從程式碼記錄現有系統,用於入職或理解儲存庫。當使用者要求「顯示計畫架構」、「我想驗證結構」、「產生 C4」、「計畫圖表」、「記錄架構」、「解釋系統如何運作」、「系統地圖」、「儲存庫入職」,或貼上 C4 Plan 檢視器連結(包含「#v1.」)時啟用。

c4-plan 是什麼?

此技能為 AI 代理(如 Claude Code、Cursor、Codex)提供結構化的方式,為實作計畫或現有系統建立並維護 C4 架構圖。它圍繞一個 YAML 檔案 (`arch.yaml`) 運作,該檔案定義元件、關係、步驟和流程。然後,一個 Python 腳本將此 YAML 編碼為一個 URL,指向一個靜態網頁檢視器,人類可以在其中導覽圖表並添加註釋。關鍵創新在於非同步的聆聽循環:如果代理有內嵌瀏覽器,它可以打開檢視器並積極監聽人類的註釋事件。這讓代理能在聊天中即時回覆回饋、更新 YAML,並將變更推送回圖表,無需手動複製貼上。此技能支援兩種模式:`plan` 模式用於在執行前可視化和驗證實作計畫,以及 `system` 模式用於在沒有計畫的情況下記錄現有架構。它確保執行嚴格遵循已批准的架構,並在偵測到偏差時提示人工審查。

相容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/gustavorana25/c4-model-skill/tree/HEAD

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

C4 Plan

人類理解計畫的結構和邊界;AI 在聊天中獲得批准後再執行。此技能不會取代計畫:它產生計畫的視覺層和一個執行摘要。

它也可以記錄現有系統 (kind: system):使用相同的圖表和流程,沒有狀態、步驟或批准。請參閱第 5 節。

聊天是事實來源。 檢視器僅顯示計畫:人類不會在那裡編輯任何內容。疑問和修改請求以註釋(或貼到聊天中)的形式送達,您在聊天中回覆,所有變更都透過 YAML 進行。

您永遠不會手動編寫 HTML 或建構 URL。您編寫一個 YAML;腳本驗證、產生連結並產生摘要。

計畫 ─► arch.yaml ─► encode ─► link ─► 人類檢視並評論 ─► 您調整 YAML ─► 聊天中確認 ─► 摘要 ─► 執行

腳本:python3 <技能目錄>/scripts/arch_url.py(僅 stdlib + PyYAML;jsonschema 可選)。

1. 從計畫產生 arch.yaml

將它儲存在計畫旁邊,命名為 <計畫名稱>.arch.yaml。結構:schema/arch.v1.json。完整範例:examples/pix.arch.yaml。

規則:

  • 這是計畫的架構,不是整個系統的。 包含計畫建立、更改或移除的內容,以及理解所需的最小上下文(誰呼叫、誰被呼叫)。不要對整個系統建模。
  • status:new / changed / removed / unchanged(預設)。上下文元素保持 unchanged。
  • C4 層級:根層級為 person、system、external;system(或根層級)內為 container、database、queue;container、database(表格、遷移)或 queue(事件)內為 component;component 內只能有 code。
  • 計畫建立或更改的所有內容都會展開到程式碼層級。 每個 status 為 new/changed 的 system、container、database、queue 和 component 都有 children,向下展開到 code(validate 會在缺少時發出警告)。不變的內容保持折疊:這是上下文。
  • 第 4 層 (code):計畫建立或更改的檔案、類別、模組或函數,並填寫 path。已經存在且會更改的檔案為 status: changed。列出更改的內容,而不是元件的所有程式碼(每個元件 2 到 4 個通常就夠了)。
  • 關係連接最具體的元素(存在時為 code → code)。檢視器會為上層層級彙總。
  • steps:計畫每個步驟一個,順序和標題相同。touches = 該步驟建立或更改的元素。
  • flows:系統在計畫後如何運作(steps 說明建置順序;flows 說明執行順序)。1 到 3 個流程:主要路徑和最重要的失敗路徑(例如:「客戶使用 PIX 付款」、「QR Code 過期」)。每個 hops[] 是 {from, to, label},需要遵循現有關係的方向,或相反方向用於回應。使用最具體的元素 (code) 並將 label 寫成所發生的事情(「在呼叫 PSP 前儲存 txid」),而不是關係名稱。檢視器會自動下降到每個跳躍的層級。
  • constraints:實作必須遵守的事項,例如可驗證的規則(「透過 txid 達到冪等性」、「加法遷移,無表鎖定」),而不是描述。在重要的決策點放置:合約、與外部系統的邊界、安全性、資料、遷移、核心業務邏輯。沒有約束的內容由您在執行時自行決定。
  • 如果合約存在於儲存庫中,請在 relations[].contract 中引用。

2. 驗證並提供連結

python3 scripts/arch_url.py encode <計畫名稱>.arch.yaml
  • 錯誤:修正 YAML 並重新執行。未通過驗證前不要提供連結。
  • 警告:如果合理就修正(例如:有新內容但未展開到程式碼層級)。
  • 在一行中向人類提供連結,並附上一個簡短的摘要,說明計畫更改了什麼(例如:「3 個新元素,2 個已更改」)。告知他們可以按 C(或評論),點擊卡片並提問或要求修改,並且批准是在此聊天中進行。

檢視器:encode 產生指向已發布版本的連結,https://gustavorana25.github.io/c4-model-skill/(靜態;計畫位於 #hash 中,不會到達伺服器)。$C4PLAN_VIEWER_URL 用於切換主機,--local 使用本地建置 viewer/dist/index.html(僅用於測試檢視器本身的變更)。

2b. 如果您有內嵌瀏覽器:監聽頁面

如果您有瀏覽器工具(Claude Code 的瀏覽器面板、Cursor 的瀏覽器、Chrome 中的 Claude),請在那裡開啟連結,而不僅僅是提供連結,並在人類檢視計畫時監聽頁面。

聊天是事實來源。 頁面只是一個快捷方式:人類指出一個或多個卡片並評論,您在聊天中回覆,絕不在頁面上回覆。您唯一在頁面上更改的是計畫,使用 load(),當對話改變結構時。

像這樣開啟 encode 產生的連結:它已經是 https://。(使用 --local 時,透過 http:// 提供 viewer/dist/ 服務,例如:python3 -m http.server;某些內嵌瀏覽器會丟棄 file:// 連結的 #hash。)

頁面暴露 window.c4plan(使用瀏覽器的 JavaScript 工具執行):

呼叫作用
await c4plan.next(30000)等待最多 30 秒的下一個事件。返回事件或 null。最大值為 40 秒(工具會在大約 45 秒時切斷)。
await c4plan.state()當前狀態:url、plan、focus(開啟的層級)、selected(人類正在查看的內容)、idleMs(人類多久沒有操作頁面)、doc。
c4plan.load(urlOuHash)在不重新載入頁面的情況下,用新版本替換圖表。
c4plan.stop()通知頁面您已停止監聽。

next() 的事件:

  • {event:"comment", targets:[{id,name}], view, text}:人類對這些元素發表了評論(可能沒有、一個或多個;view 是開啟的層級)。在聊天中回覆,以名稱開頭:「關於 API Pix 和 清算佇列:…」。如果是修改請求,請更改 YAML,執行 encode,呼叫 load(新連結),並在聊天中說明更改了什麼。然後繼續監聽。
  • {event:"stop", reason:"idle"}:人類 10 分鐘沒有操作頁面,監聽自動結束。說出停止語句(步驟 3)並離開迴圈。

迴圈:

  1. 在開始之前,在聊天中用一行說明:「我已瀏覽器中打開圖表,並在您操作它時監聽。按 C(或評論),點擊卡片並寫下內容:我在這裡回覆。當一切正常時,請在這裡告訴我您批准。」 如果沒有這個警告,人類會操作頁面,聊天中不會顯示任何內容,他們不知道發生了什麼。
  2. 重複 await c4plan.next(30000) 並處理每個事件。null 僅表示「還沒有任何事件」:再次呼叫,不要在聊天中評論。監聽會持續,只要人類與頁面互動(每次點擊、按鍵或滾動都會重置時鐘);結束由頁面決定,使用 stop。
  3. 當 stop 到達時停止。在 stop 時,在聊天中說:「我停止監聽圖表,因為它處於閒置狀態。當您需要時請在聊天中評論,或要求我再次監聽。」 如果您因其他原因需要提前停止,請呼叫 c4plan.stop() 並說同樣的話。
  4. 如果您在監聽時人類在聊天中發送訊息,迴圈結束:回覆該訊息。然後讀取 (await c4plan.state()).idleMs:如果小於 10 分鐘,他們仍在頁面上,因此返回迴圈,無需再次警告。如果他們批准,呼叫 c4plan.stop() 並按照第 3 節進行。
  5. 如果人類在聊天中詢問關於「這個」或「這個元素」,請讀取 state().selected 以了解他們在說什麼。
  6. 在您沒有監聽的情況下,評論按鈕會複製一段文字,例如「關於圖表中的 "API Pix" (pix-api):…」,讓人類貼到聊天中。括號中的 ID 是 YAML 中的 ID。

3. 當人類在聊天中批准時

只有他們批准,並且只在聊天中(「已批准」、「可以繼續」、「好,執行」)。沉默、監聽結束或沒有評論不等於批准。

  1. 在 <計畫名稱>.arch.yaml 中標記 approved: true,並從檔案產生摘要:
    python3 scripts/arch_url.py brief <計畫名稱>.arch.yaml -o <計畫名稱>.arch.md
    
  2. 用幾行文字總結由於對話而與第一個連結相比發生了什麼變化(約束、結構、流程)。
  3. 在計畫中新增對 <計畫名稱>.arch.md 的引用,然後繼續執行。

如果人類貼上檢視器的連結(例如,在普通瀏覽器中開啟),它僅供查看:有效版本是您的 <計畫名稱>.arch.yaml。

4. 執行時遵守摘要

<計畫名稱>.arch.md 在執行期間是強制性的:

  • 遵循結構(元素、關係、流程)和所有約束。如果實作要求更改結構或違反約束,請停止並詢問。
  • 被引用的合約 (contract) 未經詢問不得更改。
  • 在約束之外,選擇最簡單的方法並遵循現有程式碼的模式。
  • 人類在聊天中要求的內容優先於您最初的提案。
  • 最後,將實作的內容與 YAML 進行比較,並報告差異(未預料的新元件、關係之外的依賴項、已更改的合約)。

5. 記錄現有系統 (kind: system)

當請求是理解或記錄已存在的內容時(「記錄架構」、「這個系統如何運作」、入職),沒有計畫:您閱讀儲存庫並產生相同的 YAML,但使用 kind: system。完整範例:examples/loja.arch.yaml。

version: 1
kind: system
title: 線上商店
description: 關於系統功能的一兩句話。

如何建構:

  • 先閱讀再寫。 入口點(路由、處理器、消費者、工作)、清單 (package.json、docker-compose、基礎設施)、遷移和外部服務的客戶端會告訴您有哪些容器、資料庫、佇列和外部服務。不要發明程式碼中沒有的部分;如果不確定,請在聊天中提出。
  • 沒有 status、steps 和 approved。 一切都是系統當前的樣子(validate 會在遺留任何內容時發出警告)。
  • 流程是主要的。 2 到 4 個:對業務最重要的路徑、主要的後台任務以及最常見的失敗案例。新進人員透過這些來理解系統。
  • 深度: 僅在流程經過的地方下降到 code,並使用真實的 path(確認檔案存在)。其餘的保持在 container 或 component 層級,並保持折疊。
  • constraints 變成開發者需要知道的規則(冪等性、誰可以寫入哪個表格、不變的合約)。
  • 關係和流程遵循與計畫相同的規則(第 1 節)。

交付:encode 像計畫一樣產生連結。用一行說明系統包含什麼(「5 個容器、2 個外部服務、2 個流程」),並且可以在「流程」選項卡中追蹤流程並使用 C 提問。如果有瀏覽器,請監聽頁面(第 2b 節):評論是問題,您在聊天中回覆,或是對文件的更正,您將其應用到 YAML 並使用 load() 重新載入。

對於儲存庫中可版本化的文字,brief 會產生 Markdown 格式的文件(元素、關係和流程):

python3 scripts/arch_url.py brief docs/arquitetura.arch.yaml -o docs/arquitetura.md

稍後,針對此系統的計畫可以從此 YAML 開始:複製它,將 kind 更改為 plan,並用 status 標記更改的內容。

相關技能