Skip to content

指令 ​

Blueprint 支援 Node ^18.18.0 || ^20.9.0 || >=21.1.0。不必安裝全域指令,直接透過套件 執行:

bash
npx @kekkai/blueprint <command>

根指令與每個子指令都支援 --help;--version 會顯示套件版本。支援 --json 的指令會 保留與文字報告相同的事實,讓自動化程式與程式撰寫 Agent 不必解析說明文字。

init ​

init 用來導入 Blueprint、修復既有整合,或啟動受保護的拓樸轉換。它會根據專案證據與 明確指定的目標,選擇三種流程之一:

  1. 建置或修復:替經量測確認沒有原始碼的應用程式建立框架預設設定(layer-first,
    或沒有任何模組的 module-first 起點)、替規模小的 layer-first 專案建立預設設定,
    或依既有有效設定檔更新產生的整合內容。
  2. 架構編寫指南:適用於尚無有效設定檔的既有原始碼,包含以 module-first 導入既有原始碼。
  3. 拓樸轉換指南:既有有效設定檔已確立另一種專案拓樸時使用。

第一次導入一定要明確選擇拓樸:

bash
npx @kekkai/blueprint init --topology layer-first
npx @kekkai/blueprint init --topology module-first

先預覽完整動作,不寫檔、不安裝、不啟動 Agent:

bash
npx @kekkai/blueprint init --topology layer-first --dry-run

旗標 ​

  • --topology layer-first|module-first — 第一次導入專案時必填。
    在沒有原始碼的 React 或 Vue 應用程式上,module-first 會以預設設定建立空的模組起點;已有原始碼時則產生架構編寫指南。
    已導入的專案若指定相同目標,會修復現有拓樸;指定相反目標,則啟動全專案轉換。
  • --preset — 跳過架構編寫,使用偵測到的 Vue、React 或 Next 預設設定。
    這只是 layer-first 的導入方式;指定 module-first、已是 module-first 的專案,以及已有自訂設定檔的應用程式都會拒絕執行。
    沒有原始碼的 module-first 應用程式不需要這個旗標,只下 --topology module-first 就會建立起點。
  • --authoring — 即使少於 10 個原始碼檔案,或是沒有原始碼的 module-first 應用程式,也強制產生架構編寫指南;後者的指南結論會帶你回到模組起點。不能與 --preset 並用。
  • --agent claude|codex — 編寫或轉換流程會在指南安全寫入後啟動指定的本機 Agent CLI;預設設定流程不啟動 Agent,只縮小要產生的 Agent 守則目標。
  • --framework vue|react — 框架證據不明確時指定。一般 Vue、React 會自動偵測;Next.js 會使用能辨識路由器的預設設定。
  • --no-install — 不執行偵測到的套件管理工具,並在計畫裡列出待安裝內容。
  • --dry-run — 只顯示計畫,不修改檔案,也不啟動 Agent。
  • --recover-transformation — 從 Git 保留的權威記錄還原遺失的 LF→MF 待完成證據與復原指南,保留既有決策與指南;不執行導入、產生架構檔案或完成轉換。請單獨使用,或搭配 --dry-run。復原要求目前 HEAD 與原始記錄一致,且應用程式與來源範圍安全。若決策檔曾遭刪除,必須重新審查並記錄遺失的決策,才能驗證完成。詳見產出檔案。

可能修改的內容 ​

完成建置時,可能建立 blueprint.config.mjs、Blueprint 管理的 ESLint 設定或參考設定、 指定路徑的架構手冊、所選 Agent 守則,以及全新 layer-first 預設設定缺少的分層資料夾;
module-first 起點不會建立任何模組資料夾。 它也可能更新別名接線、一般 lint 指令、.gitignore,並透過偵測到的套件管理工具更新 相依套件。完整清單與管理權責見產出檔案。

既有 ESLint 設定絕不會被覆寫。除非 Blueprint 能辨識出自己產生並管理的設定檔,否則 只會建立 eslint.config.blueprint.mjs 供你整合。重複執行 init 應得到相同結果。

重要邊界 ​

  • 原始碼形狀只是證據,不是拓樸權威。同一個專案內的有效設定檔必須解析成同一種拓樸。
  • 多應用程式範圍未確定時,任何寫入前就會停止;編寫階段必須明確選擇應用程式的原始碼根目錄。
  • Blueprint 絕不自行發明領域模組。沒有原始碼的 React 或 Vue 應用程式,
    可以從預設設定的空模組起點開始 module-first;已有原始碼時,模組圖一定要先由人或 Agent 編寫。
  • 拓樸轉換要求 Git 專案、乾淨工作目錄與可復原的已提交 HEAD。Blueprint 會記錄量測到的 搬移證據,但領域命名、擺放位置、衝突處理與匯入改寫仍由 Agent 判斷,並以 git mv 執行。
  • Next.js App Router 會保留。遇到不支援的 Pages Router 或不明確路由器轉換時,流程會停止, 不會暗中改變路由架構。
  • Nuxt 的自動匯入讓 Blueprint 無法提出可信的靜態分析結果,因此目前不支援。

遭拒或執行失敗時會以非零狀態結束。若明確要求的 Agent 啟動失敗,先前產生的指南與檔案 仍已保存在磁碟上,可改走手動流程。

init 何時算完成導入 ​

Blueprint 會把「已經寫入專案、可以證明由 Blueprint 擁有的內容」和「這次導入是否真的完成」分開記錄。

如果 init 執行到一半失敗,已經落地的 Blueprint 內容仍會保留所有權紀錄,但不會因此建立已完成的生命週期檢查點。

以下情況也還不算完成導入:

  • 使用 --no-install 跳過了目前仍需要安裝的 Blueprint 或相關工具相依套件;
  • brownfield authoring 目前只建立了 blueprint-authoring.md 與 Agent 交接內容,還沒產生並採用最後的 blueprint.config.mjs。

等缺少的工作補完後,再次執行 init。Blueprint 會保留前一次已記錄的所有權事實,並在這次導入真正完成時建立生命週期檢查點。

brownfield authoring 中,當 Agent 已經完成設定檔,而後續的 init 成功採用這份設定時,就代表 Blueprint 的導入已完成,可以建立檢查點。blueprint-authoring.md 可能仍會暫時保留到 Agent 執行最後的清理步驟;只要這類尚未完成的 workflow 檔案仍存在,upgrade 仍會拒絕開始新的升級。

全新專案與既有專案的導入姿態 ​

第一次導入時,空的應用程式跟已有原始碼的應用程式走不同路線。
決定路線的是量測到的原始碼,不是旗標。

  • 全新專案(經量測確認為空) — survey 在 React 或 Vue 應用程式裡數到 0 個原始碼檔案。
    init 會直接建立框架預設設定的完整標準治理:分層職責、框架所有權、命名、核心信念、
    元件形狀軸線、工作指南,以及各規則的等級。
    • --topology layer-first 寫出 reactPreset() 或 vuePreset()。
    • --topology module-first 寫出同一份預設設定,再加上 modules: []。
      這個起點已經宣告了拓樸、套用同一套治理,
      但不建立任何模組資料夾,也不發明任何領域模組 —— 沒有 shared、core、app,什麼都沒有。
      模組根目錄佔 container 的位置,重複的內部分層保留各自的框架職責,
      路由組合等實際出現路由後,再交給保留的 app 模組。
    • Next.js 應用程式不走 module-first 起點:
      即使專案是空的,--topology module-first 也會進入架構編寫指南。
  • 既有專案(已有原始碼) — init 產生架構編寫指南。
    Agent 會轉譯專案原有的意圖與門檻、先量測影響,
    再把已理解的既有債務記進各自的帳本:架構問題記進 Blueprint 基準線,lint 命中記進 ESLint suppressions。
    它不會替專案打開原本沒有的選用檢查。

Layer-first 在原始碼少於 10 個檔案時,也會直接建立預設設定。
既有專案產出的設定檔是真實、安全的導入結果 —— 是下限,不是 Blueprint 建議的上限。

讓 module-first 起點長出模組 ​

Module-first 設定產出的架構手冊與 Agent 守則,都帶有一份模組成長流程。
當 owner 要求的產品功能需要一個現有模組都不擁有的邊界時,Agent 會先用暫時的 layer-first 投影來推理:
先看路由/頁面怎麼組合,再找出它組合的 container/use case 職責,最後找出每項職責需要的單元。
這些職責就是模組的種子:相關的種子合併、只有真正獨立的才拆開,
有明確領域擁有者的程式碼就留在擁有者身上。
決定好擁有權之後,才建立 Module → Layer → Unit,並依實際匯入推出 dependsOn。
它絕不會一個畫面、hook/composable、service、entity 或需求名詞就開一個模組,也絕不會開一個什麼都塞的 shared。

這個投影只是分析。
它不會把專案說成 layer-first、不會寫出 layer-first 設定檔,也不會啟動拓樸轉換。

收緊既有專案的設定檔 ​

要不要把既有專案的設定往標準預設設定收緊,是 owner 在導入之後的決定。
動手之前先量測,一次只恢復一項更嚴格的守則,
每一步只記錄「在那一步之前就存在」的債務。
絕不為了變綠而降低目標。

決定收緊時,把下面這段 prompt 交給你的程式撰寫 Agent:

text
請把這個專案的 Blueprint 治理,往標準 <React|Vue> 預設設定收緊。

1. 比對 blueprint.config.mjs 與標準預設設定。用下面這行印出標準預設設定:
   `node --input-type=module -e "import { reactPreset } from '@kekkai/blueprint'; console.log(JSON.stringify(reactPreset(), null, 2))"`
   (Vue 專案改用 `vuePreset`;設定檔是 module-first 時傳入 `{ modules: [] }`)。
   執行 `npx blueprint rules --json` 看設定檔宣告了哪些檢查,
   再列出分層、所有權、命名、核心信念與規則等級的每一項差異。
2. 動手之前先量測:執行 `npx blueprint inspect --json` 與 `npx blueprint impact --json`,
   把兩份輸出留作起始證據。
3. 一次只恢復一項更嚴格的守則:一項分層職責、一條所有權規則,或一個規則等級。
   每一步之後執行 `npx blueprint init`、`npx blueprint impact --json` 與
   `npx blueprint inspect --json`,並把每個新結果分類為「這一步揭露的既有債務」或「退步」。
4. 先修好退步,再把已理解的既有債務記進各自的帳本:
   架構問題用 `npx blueprint inspect --update-baseline`,lint 命中用 `npx eslint . --suppress-all`
   (ESLint 的 suppressions 檔;只有專案自己的 lint 指令已經通過時才跳過這一步,
   因為 `impact` 只計算架構 glob 涵蓋到的檔案,範圍外的測試檔和其他檢查的檔案都不會算進去)。
5. 絕不為了變綠而降低目標規則、門檻或邊界。某一步的代價若大於價值,
   停下來把量測到的影響回報給 owner,而不是把它放寬。
6. 最後執行 `npx blueprint inspect --baseline`、`npx blueprint doctor`,以及專案自己的
   lint、typecheck、test、build 指令。回報每一項恢復的守則、每一步記錄的債務,
   以及所有留給 owner 決定的事項。

survey ​

survey 在設定檔建立前蒐集可重現的客觀證據,包括原始碼資料夾與形狀、重複子資料夾 模式、資料夾匯入矩陣、同資料夾別名匯入、測試命名慣例、原始碼根目錄接線檔案,以及套件 使用集中度。

bash
npx @kekkai/blueprint survey
npx @kekkai/blueprint survey --source-root apps/web/src --json
  • --alias <name> — TypeScript/JavaScript 設定找不到別名時,由使用者提供。
  • --source-root <path> — 在多應用程式工作區中選擇一個原始碼根目錄。
  • --json — 輸出機器可讀的證據。

這是唯讀指令,只回報事實,不替你決定分層、模組、所有權或依賴方向。

inspect ​

inspect 會拿設定過的原始碼樹與架構比對,找出未宣告資料夾、模組或分層流向違規、非 標準別名、深入匯入、相對路徑逃逸、套件所有權違規、selfOnly 再匯出、缺少公開入口, 以及尚未落地的模組/分層提示。只有在 rules.cycles 已宣告且層級不是 off 時,它才會 回報單元循環。關卡未宣告或為 off 時,沒有循環 finding 只代表 Blueprint 未啟用循環 偵測,不能證明相依圖中沒有循環。

bash
npx @kekkai/blueprint inspect
npx @kekkai/blueprint inspect --update-baseline
npx @kekkai/blueprint inspect --baseline --json
  • --framework vue|react — 框架證據不明確時指定。
  • --json — 輸出結構化報告。
  • --update-baseline — 將目前 error/warn 記錄進 .blueprint-baseline.json;info 不會列入,沒有債務時不建立檔案。匯入分析若為降級或失敗,會拒絕更新並以 1 結束,避免把不完整的相依圖寫成基準線。
  • --baseline — 只讓基準線以外的新問題造成失敗,形成既有專案的棘輪。

任何未列入基準線的 error 都會讓指令以 1 結束;warn 與 info 不會。解析失敗也會以 1 結束:只要有一個檔案解析失敗,匯入分析就是降級;若所有掃描檔案都解析失敗,則是失敗。 報告會把解析狀態與架構規則涵蓋的原始碼檔案數、已啟用的選用關卡數分開呈現,避免把結構 涵蓋率誤當成相依圖完整性的證明。

architecture.testFiles 是唯一的結構性測試檔豁免來源。靜態匯入與再匯出會進入相依圖; 動態匯入只有在目標可化約成確定字串時才會納入。無法判定的動態目標會揭露;若 module-first 專案需要檢查來源目錄外的範圍,這些目標可能跨越邊界,因此範圍證據會標示為不完整,Inspect 不會判定驗證完成,也不允許更新基準線。只分析受管來源與 layer-first 的行為維持不變。 解析失敗可能隱藏相依邊,因此會讓驗證失敗。

Module-first 報告一律包含 moduleDependencies,即使沒有設定 moduleDependencySync 或設為 off 也一樣。它比對宣告的直接相依(D)與原始碼確認的直接相依(O),並分開 呈現間接匯入權限(P)。結果包含吻合、缺少、未使用及待確認的宣告,各模組的涵蓋情況與 不確定性,以及整體 synchronized、drift、indeterminate 或 runway 狀態。 已確認的差異不會因分析不完整而消失。

啟用 rules.moduleDependencySync 後,Inspect 會依模組配對彙整 module-dependency-missing、module-dependency-unused,並為每個分析不完整的匯入模組 產生一筆 module-dependency-unverified,採用此規則自己的 warn/error 層級。 已有間接權限的參照仍可能缺少直接宣告;禁止的參照則保留原有流向違規。 調整原始碼或 dependsOn 前,應先確認預期架構。

inspect --baseline 用來防止已知債務增加,不是精確相等的證明。基準線可以讓已記錄的 同步問題不影響結束狀態,但不會改變文字、JSON 或 runInspect() 中完整的 moduleDependencies 狀態、差異清單、涵蓋情況與不確定性。 相依圖納入型別參照與可靜態確認的動態匯入,排除設定指定的測試檔,仍納入 layerFilesIgnore 與看似自動產生的受管原始碼。執行時才能決定的目標、解析失敗,以及 無法解析的專案內參照只影響所屬匯入模組。完整規則見 來源範圍與啟用方式。

inspect 不接受位置參數路徑。請在應用程式根目錄執行,掃描範圍由 architecture.sourceRoot 決定;額外傳入路徑會被拒絕,不會默默忽略。

Module-first 專案中,sourceRoot 外的原始碼與受管原始碼相依時, uncovered-application-source 仍屬於錯誤。如果外部匯入者確實是工具或其他外部使用端, 負責人可以在 architecture.consumerFiles 宣告 相對於應用程式根目錄的精確模式;若它其實是應用程式原始碼,就應擴大或重新整理受管範圍, 或移除相依。資料夾名稱不會自動取得豁免,模式應盡量限縮,避免掩蓋真正的應用程式原始碼。

外部使用端宣告只會移除「外部匯入內部」的範圍證據。若受管原始碼反向匯入使用端,仍須移除 該相依,或把目標搬入受管架構並正確宣告。雙向相依時,反向那條仍會阻擋。這個角色不賦予 拓樸身分,也不證明目標 API 或公開入口的使用正確。testFiles 維持獨立且優先的雙向豁免; layerFilesIgnore 不會隱藏範圍證據。省略或清空使用端宣告、layer-first 專案,以及 sourceRoot: '.' 都維持既有行為。允許的使用端相依不新增訊息,也不改變結束碼。基準線用來 記錄債務,不能取代外部使用端的角色宣告。

Module-first 的完整分析只收集一次來源目錄外的證據,Doctor 與轉換驗證共用這份結果。 在 Git 工作目錄中,候選範圍包含此應用程式內已追蹤的檔案、尚未追蹤且未被忽略的檔案, 再加上 consumerFiles 明確指定的搜尋根目錄,以及受管原始碼匯入的外部目錄。 無關且被忽略的輸出不會被解析;已追蹤的原始碼即使符合忽略規則,仍會被納入。 明確搜尋範圍也會納入同目錄內其他角色的檔案,因此過寬的使用端模式會增加掃描成本。 測試檔會在讀取與解析外部檔案前排除,既有的掃描器排除規則仍然適用。

外部證據會區分 not-requested(未要求)、not-applicable(不適用)、complete(完整)、 partial(部分完成)與 unavailable(無法取得)。Layer-first 與 sourceRoot: '.' 不分析外部範圍;deps、survey、rules 等只需要受管來源的指令,不會盤點、讀取或解析 外部檔案。無法取得 Git 檔案清單時,會改用完整的檔案系統掃描,並揭露可能增加的成本。 即使 finding 已列入基準線,部分完成或無法取得的證據仍會阻擋完整驗證。JSON 會提供共用的 範圍證據與檔案操作次數。「完整」指依設定的收集政策完成,並不代表已證明那些被忽略、 且未被宣告或受管相依觸及的檔案沒有問題。

impact ​

impact 會在正式接線前,只預覽 Blueprint 產生的規則將新增哪些 lint 問題。它使用專案 自己的 ESLint,依規則統計命中次數並列出問題最多的檔案。

bash
npx @kekkai/blueprint impact
npx @kekkai/blueprint impact --json

唯一旗標是 --json。執行時需要已編寫的 blueprint.config.mjs、ESLint 9 或 10,以及專案 技術組合需要的解析器與外掛;init 會安裝支援的相依套件。若專案仍使用 ESLint 8, impact 會明確回報不可用並指向 ESLint 9/10 遷移,不會曝露 flat config API 原始錯誤, 也不會把未量測結果寫成零命中。

這是資訊指令:即使有 lint 命中也維持成功狀態。解析錯誤、未使用的停用註解與非 Blueprint 規則會另外列出,不會灌進 Blueprint 總數;這些仍須回到專案平常的 lint 驗證。 支援 Vue JSX/TSX script 區塊。若有檔案無法解析,JSON 會回報 status: "partial", 文字報告也會說明命中數只是已觀察到的下限,並非完整總數。請先修正來源或解析器設定, 重新執行 Impact,再決定規則層級或記錄 suppressions。

deps ​

deps 讀取與 inspect 相同的受管理匯入圖。指定單元時會列出它匯入什麼、哪些單元匯入 它;省略單元則輸出被引用數排行榜。

bash
npx @kekkai/blueprint deps hooks/useCart
npx @kekkai/blueprint deps src/orders/components/OrderRow.tsx --json
npx @kekkai/blueprint deps
  • --framework vue|react — 框架證據不明確時指定。
  • --json — 輸出結構化相依圖結果。

只有架構涵蓋的單元會進圖;被略過的資料夾與匯入分析限制都會明列。Folder layout 以單元 為粒度,file layout 則收斂成分層粒度。設定為測試檔的匯入不會增加影響範圍,且只有別名 與相對匯入會形成邊。

Module-first 未指定目標時,會在單元排行榜之前列出直接宣告、間接權限、觀察到的相依及其 參照次數與固定排序的範例,再呈現比對結果、涵蓋情況與不確定性。 指定目標時,文字報告仍保留整個專案的狀態,另顯示目標所屬模組。 JSON 與 runDeps() 永遠保留完整、未篩選的 moduleDependencies,並另外標示目標模組; 指定目標不會縮小整體判定範圍。JSON 包含每一組不重複的證據路徑與匯入字串,順序固定。 Layer-first 的 moduleDependencies 為 null,文字報告省略此區段。

模組資料與 Inspect 共用受管來源分析,不需要盤點來源目錄外的檔案。 型別參照會計算,設定指定的測試檔不計算;layerFilesIgnore 與自動產生風格的檔名不構成 豁免。無法判定的動態目標與專案內參照保留為不確定性,不猜測相依,也不當成宣告未使用的 證據。詳見範圍與狀態定義。

rules ​

rules 說明可用的 lint 與 Inspect 檢查。它會區分一定產生的結構性規則、由 blueprint.rules 啟用的選用關卡,以及只寫入文件的規則識別碼。有設定檔時,還會顯示每個 關卡的 tier/數值、在目前技術組合是否生效,以及實際結構限制。

bash
npx @kekkai/blueprint rules
npx @kekkai/blueprint rules --json

唯一旗標是 --json。此指令唯讀,也不要求設定檔。需要理解真實結果時,應使用它,而不是 反向推測產生後的 flat config;規則設定總表見設定。

moduleDependencySync 會列出宣告層級、可用性、啟用狀態,以及執行來源 inspect (module dependency reconciliation)。它僅適用於 module-first,不是 lint 規則; 與 cycles 一樣,必須執行 Inspect 才會檢查,也不受 emit.lint.severity 控制。

doctor ​

若 ESLint 無法為規則存續檢查的探測路徑提供設定,Doctor 會列出路徑並標為未驗證。 應檢查全域忽略規則與檔案匹配,不能據此斷言規則遭到覆蓋;其他位置若確實遺失規則, 仍會判定失敗。Suppressions ledger 會同時檢查應用程式與實際 ESLint 設定所在目錄。

doctor 評估目前設定下的導入證據,包括設定檔、殘留的暫存/Agent 檔案、ESLint 接線、 package.json 一般 lint 入口能否安全到達並實際跑完 ESLint、別名接線、結構性規則在合併後 的 flat config 是否仍存在、架構狀態,以及停用規則帳本。

Doctor 不會替 moduleDependencySync 檢查 ESLint 接線,也不證明 CI 有執行 Inspect。 啟用同步關卡後,專案的檢查流程仍須實際呼叫 Inspect。

別名證據會依可辨識的 TypeScript、bundler/runtime、套件 imports 子路徑與 test runner 分開回報。單一 consumer 的證據不會產生涵蓋整個工具鏈的綠燈:缺少對應會讓該項失敗; 應適用但無法讀取時會標示為尚未驗證;不存在或不適用的 consumer 也會明確標示。

bash
npx @kekkai/blueprint doctor
npx @kekkai/blueprint doctor --json

唯一旗標是 --json。公開的 runDoctor() 回傳值與 JSON 都以 assessment 作為評估依據, 分成四個獨立面向:

  • gates:適用的可執行檢查已通過、失敗,或仍未驗證。
  • conformance:新增違規、基準線保留的既有債務,以及不阻擋執行的觀察。 這些計數可能重疊,不能相加;基準線略過違規不會抹去證據。
  • reach:已涵蓋、部分涵蓋與僅宣告的位置。無法取得的來源目錄外證據會計入 partial, 但項目證據仍保留原始狀態。有意保留的 modules: [] 起步狀態屬於宣告,不代表導入失敗。
  • review:仍需審查或沒有已知審查項目,並分別列出待審查與已記錄的數量。 沒有已知項目只代表 Blueprint 未產生待審查項目,不代表產品模型已證實正確。

共用的 assessment.headline 依序優先呈現:檢查失敗、可執行與來源證據同時未驗證、 只有可執行證據未驗證、只有必要來源證據未驗證、仍需語意審查、尚未實際驗證的宣告, 最後才是沒有已知審查項目。檢查通過不能掩蓋必要來源證據不完整。每個項目保留穩定的 來源識別、型別化證據、限制、審查訊號與既有退出碼政策;引用該模組的模組數量不能決定它是否應歸為共用模組。

gateVerdict 保留原本只反映檢查結果的 complete | unverified | incomplete。 verdict 在 4.2 保留為已棄用的相容別名;兩者都不是導入結論。 ok 與退出碼維持相容:Doctor 沒有失敗項目時退出碼為 0,即使有跳過檢查也一樣; 有失敗項目才是 1。要求完整證據的自動化流程應讀取 assessment,不能只看退出碼。 不安全或語意不明的 lint 指令會跳過,不會交給 shell 執行。

inspect 與公開的 runInspect() 使用相同評估模型,提供架構範圍的子集。 Doctor 彙整目前設定的證據;兩者都不證明模組歸屬、分層與根目錄責任、呈現責任, 也不能證明過去的拓樸轉換已完成。生命週期升級與拓樸轉換維持各自範圍及決策紀錄。 靜態產出的守則只說明這些界線,不會快取即時評估結果。

Doctor 會辨識 lint 指令;未宣告 lint 時,則辨識 eslint 指令。兩者都無法辨識時, 這項檢查會標成未驗證,而不是斷言接線錯誤。對可執行的 JavaScript 別名設定,無法判讀的 運算式或匯入的別名表也會標成未驗證。只有靜態證據足以確認缺少或目標不符時,才會回報 對應的別名有問題;建置成功本身也不能證明每個別名都正確。

upgrade ​

upgrade 負責把已導入 Blueprint 的專案升級到較新的版本。

要升級到哪一版,就用那一版的 Blueprint 執行:

bash
npx @kekkai/blueprint@latest upgrade --dry-run
npx @kekkai/blueprint@latest upgrade
npx @kekkai/blueprint@4.1.0 upgrade

正在執行的 @kekkai/blueprint 套件就是唯一的目標版本來源,因此沒有另外的 --to 旗標。

upgrade 不會用來降版。它也會同時確認專案目前實際安裝的 Blueprint 版本與生命週期檢查點;只有兩者都已經位於正確的目標狀態時,才會回報目前不需要升級。

如果只是要重新產生 Blueprint 管理的內容,請使用 blueprint init;如果只是要確認目前狀態,請使用 blueprint doctor。

為什麼只執行 npm update 不夠 ​

Blueprint 的版本升級不只包含 npm 套件本身。

新版本可能同時需要:

  • 更新專案中的 @kekkai/blueprint 相依套件;
  • 執行 Blueprint 可以安全確定的設定或整合遷移;
  • 重新產生 Blueprint 管理的輸出;
  • 執行需要人或程式撰寫 Agent 判斷的語意工作;
  • 驗證所有已導入的應用程式是否真的完成升級。

因此,單獨執行 npm update、pnpm update 或 yarn upgrade 並不等於完成 Blueprint 的升級生命週期。

upgrade 會依序處理完整流程:

  1. 確認起始狀態並產生計畫。 讀取 .blueprint-lifecycle.json 中已完成的生命週期版本與升級紀錄。 如果專案是在生命週期狀態功能加入之前就已經導入 Blueprint,只能使用當時實際安裝、可精確證明的套件版本建立起始檢查點。舊版設定格式橫跨受支援與不受支援的 3.x 版本,不能單獨證明來源版本;若較新的套件已覆蓋這項證據,必須先建立已知的 3.2 檢查點再升級。 接著一次收集 (source, target] 區間內所有版本的結構化升級操作,先處理 requires、cancels、supersedes 與適用條件,算出最終有效計畫,之後才開始修改專案。

  2. 記錄尚未完成的升級。 在執行其他修改之前,先把本次升級的來源版本、目標版本與有效計畫寫進生命週期狀態。 如果流程中斷,之後可以從同一份 pending state 接續,不會重複已完成的操作。

  3. 把專案相依套件更新到目標版本。 Blueprint 會使用偵測到的 npm、pnpm 或 Yarn,更新真正宣告 @kekkai/blueprint 的 package.json 與 lockfile。 更新完成後,後續流程會改由專案剛安裝好的 Blueprint 執行,確保設定檔載入、遷移與產出全部使用目標版本。

  4. 執行可由程式確定完成的遷移。 Blueprint 會透過既有的 init 與其他既有 owner,執行可以安全自動完成的設定與整合遷移,不把可確定的工作丟給 Agent 判斷。

  5. 處理仍需要語意判斷的工作。 如果最終有效計畫還有語意操作,Blueprint 會產生一份 blueprint-upgrade.md。 Agent 只執行這份已解析完成的計畫,不直接執行歷史 CHANGELOG 或 release note。 每完成一項操作後,使用:

    bash
    npx blueprint upgrade --complete <operation-id>

    Blueprint 會先執行該操作可以量測的驗證,再記錄完成狀態。

  6. 完成最後驗證。 所有語意操作完成後,再執行:

    bash
    npx blueprint upgrade

    Blueprint 會重新對齊每個已導入的應用程式,並執行 blueprint inspect --baseline 與 blueprint doctor。 只有所有必要驗證都成功,生命週期檢查點才會移到目標版本。

    最後仍應執行專案自己的 lint、typecheck、test 與 build 指令。

套件更新途中中斷 ​

升級開始前,Blueprint 會先記錄這次 pending upgrade,再更新各個已導入應用程式實際使用的 Blueprint 套件。

如果 repository 有多個套件宣告位置,而更新途中只有部分應用程式成功到達目標版本,下一次執行 upgrade 會從已記錄的 pending upgrade 接續:

  • 已經位於目標版本的應用程式不會重複安裝;
  • 還停在這次升級起始版本的應用程式會繼續更新到目標版本;
  • 如果出現不屬於這次升級起始版本或目標版本的其他版本,Blueprint 會停止,不會猜測如何修正這個狀態。

因此,由 Blueprint 自己造成的「部分套件已更新」狀態是可接續的升級中間態,而不是要求使用者自行修復的混合版本錯誤。

跨版本的累積升級計畫 ​

一個 Blueprint 版本可以新增零到多項結構化升級操作。

每項操作都有固定 id、加入它的版本、適用條件與驗證方式,也可以宣告與較早操作的關係:

  • requires:這項操作必須排在另一項操作之後。
  • cancels:如果較舊的操作在這個 repository 還沒執行過,就從本次直接升級的有效計畫中移除。取消不等於還原;已經執行過的歷史不會被假裝成沒發生過。
  • supersedes:由新的操作接手最終狀態。無論舊操作以前已經執行過,還是直接跨版本而從未執行,新操作都必須把專案收斂到同一個受支援的目標狀態。

因此:

text
3.2 → 4.1

直接升級,和:

text
3.2 → 4.0 → 4.1

分段升級,可以有不同的歷史執行紀錄,但最後必須收斂到同一個 Blueprint 目標狀態。

Agent 不會自行重播每一版的 CHANGELOG 或 release note,只會收到 Blueprint 已經解析完成的最終有效計畫。

選項 ​

  • --dry-run — 顯示起始版本、起始版本的證據、目標版本、所有已導入的應用程式與實際安裝版本、套件更新指令、確定性遷移、最終有效的語意計畫,以及開始升級前必須滿足的安全條件。完全不修改專案。
  • --complete <operation-id> — 在某項待完成的語意操作通過自己的驗證後,記錄這項操作已完成。不能與 --dry-run 同時使用。

升級邊界 ​

支援的升級起點目前從 3.2.0 開始。更早的 Blueprint 導入,必須先依該版本原本支援的方式到達 3.2.0,再進入目前的 upgrade lifecycle。

目前執行的目的版本只負責自己宣告的升級支援範圍,也就是 supportedFrom 到目前版本。

已經完成、而且隨著支援範圍前移而退出可執行範圍的舊升級操作,可以只保留辨識歷史所需的最小紀錄;它們不會重新進入新的 pending upgrade,也不需要永久保留舊版的執行指示、適用條件或驗證方式。

換句話說,最新版 Blueprint 不需要理解所有歷史版本彼此之間的升級路徑。已完成的生命週期檢查點會結束它之前的可執行升級義務,之後的 resolver 只處理目前檢查點到目的版本之間仍受支援的區間。

開始新的升級之前,必須位於 Git repository,而且工作目錄不能有未提交的變更,讓整次升級可以完整檢視與還原。已經有 pending upgrade 時,則依既有紀錄接續,不要求把升級本身造成的修改先清掉。

Blueprint 的 lifecycle 是 repository-wide。所有已導入的應用程式都必須維持一致且可證明的 Blueprint 套件狀態;只有每個必要應用程式都完成驗證,repository 的生命週期才能推進。

如果還有未完成的架構編寫或拓樸轉換流程,必須先完成或明確處理,不能同時開始新的 upgrade lifecycle。

如果 .blueprint-lifecycle.json 損壞、內容無法驗證,或 Git 歷史能證明它曾經存在但目前檔案已遺失,upgrade 會停止,不會依目前的設定或已安裝套件自行重建 lifecycle history。若不在 Git repository 內,或 shallow clone 無法提供完整歷史,也同樣停止。請先從版本控制或其他可信來源還原 lifecycle state;無法還原時,交由 owner 決定後續處理。

如果 .blueprint-lifecycle.json 目前不存在,而且完整 Git 歷史中所有目前可追溯的 ref 都找不到曾包含這個檔案的 commit,Blueprint 不會把它視為「遺失的 lifecycle state」,因為現有版本控制證據無法證明 lifecycle 曾經成立。這種 repository 只能由實際安裝、可精確定年的舊版套件建立起始檢查點;若 Renovate、Dependabot 或 npm update 已把套件升到較新版本,舊版設定格式本身無法區分 3.1 與 3.2,Blueprint 會拒絕猜測,並要求先建立已知的 3.2 檢查點。請把 .blueprint-lifecycle.json 提交進版本控制,讓後續遺失時有可恢復的歷史依據。

remove ​

remove 用來安全地把 Blueprint 從專案中移除。

請在解除安裝 @kekkai/blueprint 之前執行:

bash
npx blueprint remove --dry-run
npx blueprint remove

Blueprint 會先算出完整的 repository-wide 移除計畫,確認每一項內容的所有權證據與可逆性。只要有任何共用內容無法安全判定,整次移除都會在實際修改之前停止。

Blueprint 可以移除哪些內容 ​

  • Blueprint 自己的檔案 例如 blueprint.config.mjs、.blueprint-lifecycle.json、.blueprint-baseline.json、受支援的設定備份,以及未完成的 Blueprint workflow 檔案。

  • Blueprint 產生的輸出 例如架構手冊、Blueprint 完整管理的 Agent 規則檔與 Blueprint 產生的 ESLint 設定。 要刪除整個檔案,必須有足夠證據證明整份檔案都由 Blueprint 擁有;如果檔案後來已改由專案自行管理,就會保留並回報。

  • 共用 Agent 文件中的 Blueprint 區塊CLAUDE.md、AGENTS.md 等共用文件只會移除 <!-- BLUEPRINT:START --> 到 <!-- BLUEPRINT:END --> 之間的 Blueprint-managed section。 只有能證明整個檔案原本就是 Blueprint 建立時,才可以在移除區塊後刪除整個檔案;原本就存在的 user-owned file 必須保留。

  • Blueprint 對共用檔案做過的修改.gitignore、package.json scripts、TypeScript / JavaScript paths、Vite alias 等內容,只有在 lifecycle provenance 與目前檔案內容能共同證明「這一段就是 Blueprint 當初做的修改」時才會自動還原。 如果 Blueprint 插入的內容已經不在檔案裡,或 script 已經變回原本的值,就視為已經還原,不會擋下移除。 如果應用程式原始碼仍需要某段一般性接線,例如 import alias,該接線會保留。

  • Blueprint 建立的資料夾 Blueprint 能證明由自己建立,而且目前沒有專案內容的資料夾可以移除。若資料夾已經放入實際專案檔案,就會保留並回報。

  • 相依套件@kekkai/blueprint 一定最後才解除安裝。Blueprint 有完整 provenance 證明由自己加入的相關工具套件,也只會在其餘專案內容不再使用時一起移除。

有衝突時,整次移除會先停止 ​

以下情況不能直接進行破壞性清理:

  • package.json script 目前的值既不是 Blueprint 寫入的,也不是原本的值;
  • 同一段曾由 Blueprint 插入的內容現在出現多次,無法判斷哪一段才是原本的修改;
  • lifecycle 雖然記得 Blueprint 做過修改,但目前證據不足以精確還原;
  • Blueprint-managed section 的 marker 已損壞或不完整;
  • 會留下來的設定、script 或其他檔案仍引用 @kekkai/blueprint、Blueprint CLI,或即將刪除的 blueprint.config.mjs。

這些情況都會在任何刪除或改寫之前停止,並指出衝突的位置。處理完之後,再重新執行:

bash
npx blueprint remove --dry-run

確認新的完整計畫。

多應用程式 repository ​

從 repository root 執行 remove,會移除範圍內所有已導入的應用程式。

如果只在其中一個應用程式範圍執行,Blueprint 可以只移除該應用程式,但必須保持 repository-wide lifecycle 一致。其他仍採用 Blueprint 的 sibling application,其 lifecycle/provenance 與共用 Blueprint 套件都必須保留。

如果 repository 目前還有尚未完成的 upgrade lifecycle,而只移除其中部分應用程式會讓 pending plan 失效,Blueprint 必須先停止,而不是留下仍引用已移除應用程式的 stale upgrade plan。

在生命週期紀錄出現之前就已導入的專案 ​

較舊的 Blueprint 導入沒有完整 provenance 可以證明所有共用檔案修改。

這種情況下,remove 只會自動刪除能從檔名、Blueprint marker 或其他可靠內容證據證明屬於 Blueprint 的項目。

無法證明的內容會保留並明確列出,例如可能由 Blueprint 加入的 alias wiring、lint script、只剩 .gitkeep 的舊分層資料夾,或無法證明由 Blueprint 安裝的工具套件。

對於生命週期紀錄出現之前就已經導入 Blueprint 的共用 Agent 文件,Blueprint 可能可以從 BLUEPRINT:START / BLUEPRINT:END marker 證明其中一個區塊屬於 Blueprint,但沒有足夠證據證明整份檔案都是由 Blueprint 建立。

這種情況下,remove 只會移除可證明由 Blueprint 管理的區塊。即使移除後整份檔案變成空檔,也會保留該檔案,並列在需要使用者確認的保留項目中;是否刪除整份檔案由使用者自行決定。

Blueprint 不會因為某個值「看起來很像預設值」就把它當成自己的修改。

移除完成後,範圍內不應再留下任何能證明仍由 Blueprint 擁有或管理的設定、生命週期狀態、產出、managed section 或相依套件。

remove 的目標是乾淨地移除 Blueprint 的 ownership 與 tooling footprint,不是為了追求位元組層級的回復,而去改寫仍由應用程式本身需要的程式碼或設定。

可執行的分層限制 ​

Rules 的人類可讀與 JSON 輸出依宣告順序列出共用的 mustNot 計畫:review-only/executable 模式、active/partial/unavailable 可用性、精確檢查與限制、lint 嚴重程度、檔案範圍、 豁免與實測涵蓋狀態。靜態宣告不會宣稱原始碼已違規。Inspect 提供相同事實與目前的 covered/vacuous/runway 範圍,不執行第二套偵測器,也不新增退出碼政策。見 設定契約。

Doctor 驗證最後合併的 ESLint 設定是否完整保留必要載體,空位置也會使用合成檔案探測。 載體缺失、停用、替換或過期是 failed;無法檢查設定,或必要 parser/框架支援不可用, 則是 unverified。兩者都阻擋導入完成,但 unverified 不自動改變既有退出碼相容性。 原始碼 error 是失敗關卡;warn 仍是可見的符合性觀察,affectsExit: false,不把彙總 關卡升為 failed。混合情況會分別保留 failed 與 unverified 證據。