跳至主要内容

文件解析遷移:設計類

狀態:P2-3 設計已通過審閱(20261017-docs-resolve-p2-3,第 2 輪,受審 revision r2-ed0145d21ad1c955;2 條意見均處置);P2-3 實作已通過審閱(20261017-docs-resolve-p2-3-impl,第 2 輪,受審 revision r2-e0da1ddeec030484,2026-10-19;2 條 minor 均處置),實作中確認的修訂見 §7 依據:ADR-023 的 D4 與實作分期 P2;文件解析與索引規格(P2-1);規格類遷移(P2-2,已實作);追蹤項目 FU-142 本頁定義:設計類 4 個 skill(/domain-model、/api-spec、/system-context、/persona)改用 docs.py resolve/register 時的類型欄位與 skill 改寫方式。共用契約沿用 P2-2 的 /docs-site references/doc-locations.md,本頁只寫設計類特有的部分。

1. 範圍​

做不做
為 domain-model、api-spec、persona、system-context 加上範本欄位data-model(目前沒有產出者,P2-5 一併盤點)
把 domain-model 拆成單檔與多檔兩個類型(§2.2);新增 api-spec-draft(§2.3)Bruno 測試集(位於 server 模組,不在 docs 模組的 registry 範圍;/api-spec 維持現行)
4 個 skill 改用 resolve/--list 取得路徑,建立或搬移頁面後執行 register;/domain-model 舊路徑遷移不再直接改 llms.txt改寫各 skill 的文件內容、提問、source 維度與 Domain Model 的拆分門檻
doc-locations.md 的「已遷移的類型」表加入本頁的類型/domain-model 模式 E 的程式碼 retarget、project.json 的 description 同步、module-inventory.md 的生成(不是 docs 模組文件)
/persona 的文檔模組偵測方式(與 m-skill-execution.md 的偵測規則不同,屬另一議題)

2. 類型欄位​

2.1 範本​

{G} 代表 {docsRoot}/docs/design。kebab 為 ^[a-z0-9]+(-[a-z0-9]+)*$。

類型template其他 locateparamskeyexample
domain-model(單檔){G}/domain-model.md{docsRoot}/docs/specs/domain-model.md(legacy)———
domain-model-part(多檔,新){G}/domain-model/{part}.md{docsRoot}/docs/specs/domain-model/{part}.md(legacy)part ^(overview|epic-[0-9]+|domain-[a-z0-9]+(-[a-z0-9]+)*)$partepic-2
api-spec{G}/api-specs/{resource}.md—resource kebabresourceorders
api-spec-draft(新){G}/api-specs/{resource}.generated.md—resource kebabresourceorders
persona{G}/personas/{persona}.md—persona kebabpersonashop-owner
system-context{G}/system-context.md————

api-specs/README.md、personas/README.md、design/README.md 是目錄頁(section-index),屬內容,不加範本。

2.2 拆分 domain-model​

現行 domain-model 類型同時涵蓋單檔(domain-model.md)與多檔目錄(domain-model/*.md)。兩者識別不同:單檔是唯一一份文件(key 為空),多檔以分檔名稱識別(overview、epic-{N}、domain-{D})。一個類型只能有一個範本,且 key 必須出現在每條 locate(R12),因此拆成兩個類型:

類型pathslegacy
domain-model{G}/domain-model.md{docsRoot}/docs/specs/domain-model.md
domain-model-part{G}/domain-model/*.md{docsRoot}/docs/specs/domain-model/*.md

其他特性(persistent、page、writer /domain-model)與現行相同。拆分也讓 /domain-model 現行的「完整盤點四個候選、兩個以上並存即停止」直接對應到 resolve 的結果(§3.1)。

2.3 新增 api-spec-draft​

/api-spec 在既有規格存在時,可讓使用者選擇「產生為 {resource}.generated.md 草稿」。草稿與正式規格並存是正常狀態,若同屬 api-spec 類型、以 resource 為 key,就會被判定為重複。因此另設類型(priority 5,比 api-spec 的 *.md 更精確),以同一個 resource 識別。

2.4 以 fleet 實際檔案驗證​

以 P2-1 的 resolve.Locator 對 fleet 9 個 workspace 的全部檔案驗證:R12 全部通過,沒有無法解析的檔案,也沒有重複 key。

workspace可解析
參考實作、florae-g1domain-model-part 8、api-spec 26~27、api-spec-draft 1(僅參考實作)、persona 6、system-context 1
nbsosdomain-model-part 4(含 domain-{D})、api-spec 33、system-context 1
almanac-g1、ict、tms、tts-v1domain-model(單檔)各 1、api-spec、persona、system-context 依專案
tps-g1、crm-v2依專案(crm-v2 尚無設計文件)

所有下游都不需要專案層設定或改名。

3. skill 改寫​

各 skill 依 doc-locations.md 的共用契約(只對已遷移類型呼叫、讀取來源與建立成果分開、直接路徑、部分參數、篩選結果的完整性、類型目錄、連結、站台索引),以下只列各 skill 特有的部分。查無時的處置一律維持現行。

3.1 /domain-model​

位置偵測(現行「完整盤點四個候選」):

候選以 resolve 判定
新單檔/舊單檔resolve --type domain-model:exists: true 時依 legacy 區分新舊;RS-AMBIGUOUS 即新舊單檔並存
新多檔/舊多檔resolve --type domain-model-part --list:items 中 legacy: false 者為新多檔、legacy: true 者為舊多檔

候選數為 0 → 無模型;恰 1 → 依類型決定單檔或多檔模式;2 個以上(含 RS-AMBIGUOUS,以及同位置單檔與多檔並存)→ 停止,列出各候選由人決定(現行規則)。恰 1 且在舊位置時,依現行分兩種讀取方:

  • /domain-model:先建議遷移,拒絕則停止,不在舊路徑寫入。
  • 其他讀取方(/api-spec、/us 的 depends_on、/assess、/analyze 等):照常讀取並提示執行 /domain-model 遷移,不阻擋;產生引用時指向 resolve 回傳的舊位置檔案(它就是當下實際存在的檔案),由遷移統一改寫。新多檔以「有任何分檔」判定,比現行「有 overview.md」更嚴:只有分檔、沒有 overview.md 的目錄也算候選,不會被當成沒有模型而另建單檔。

其他:

  • 新檔路徑:單檔 resolve --type domain-model;多檔各分檔 resolve --type domain-model-part --param part={overview|epic-N|domain-D}。自動拆分(單檔 → 多檔)刪除單檔、建立分檔後執行 register。
  • 舊路徑遷移:git mv、改寫 docs/ 內引用、等價紀錄照現行;手動側欄(sidebars*.ts)與 design/README.md 是內容,照現行更新。llms.txt 分兩部分處理:
    1. 受管區塊:不手改,搬移後以 register 重建(新位置的頁面列入、舊位置的頁面移除)。
    2. 區塊外的手寫條目:register 只接管現存頁面的條目,指向舊網址的手寫條目會留在區塊外,且 register --check 仍為 exit 0,因此須定向清理。對象只限 - {permalink} - {描述} 形式、permalink 在舊模型路由下(/specs/domain-model、/specs/domain-model/…,含 baseUrl)的條目:以引用改寫的同一路由對應算出新 permalink,新 permalink 已在 register 後的受管區塊中才算確認指向該模型,刪除該行;手寫描述與區塊內自動描述不同時,改寫區塊內該條目的描述以保留原文(區塊內允許改描述)。新 permalink 不在區塊中的條目、以及在說明文字中提到舊網址的行,列入未完成清單,不猜測。其他內容一律不動。
    • 完成條件在現行條件之外再加兩項:llms.txt(區塊內外)沒有指向舊模型路由的條目;register --check exit 0。
  • 模式 A、D 讀取 Epic、US、SBE、Roadmap 改用 P2-2 的 resolve/--list(取代 epics/epic-{N}-*.md、user-stories/epic-{N}/US-*.md、sbe/epic-{N}/US-*/ 等固定樣式)。
  • 其他 skill 的 depends_on 錨點(design/domain-model.md#{Entity}、design/domain-model/epic-{N}.md#{Entity})由對應類型的 resolve 結果轉為相對於 docs/ 的路徑。

3.2 /api-spec​

  • 既有規格判定(寫入前讀 source):resolve --type api-spec --param resource={resource}。選擇產生草稿時:resolve --type api-spec-draft --param resource={resource}。
  • 補建(backfill)列出既有規格:resolve --type api-spec --list,取代 Glob api-specs/*.md。
  • 正向模式讀 US、SBE:改用 P2-2 的 resolve --type us/sbe --list(現行樣式 **/user-stories/... 未錨定 {docsRoot});讀 Domain Model 依 §3.1 的偵測。
  • 建立新規格或草稿後執行 register。
  • Bruno({serverModule}/bruno/**)、deploy.json、application.yml 等 server 模組檔案維持現行。

3.3 /system-context​

  • 文件:resolve --type system-context(exists 決定建立或修訂,現行)。
  • 來源:persona --list、resolve --type roadmap、feature-list、api-spec --list。
  • depends_on 的 Persona 路徑由 persona 的 resolve 結果計算。
  • 新建時執行 register。project.json 與 module-inventory.md 維持現行。

3.4 /persona​

  • 列出:resolve --type persona --list(README.md 屬目錄頁,不在結果中)。
  • 檔案 ID 與名稱分開:persona 參數是檔名的 {personaId},只接受 kebab-case(^[a-z0-9]+(-[a-z0-9]+)*$);使用者輸入的多半是顯示名稱(可能是中文或含空白)。輸入不符合 ID 格式時不傳給 resolve,否則得到的是 RS-PARAM(參數錯誤),不是「查無」,也到不了現行的建立流程。
  • 以名稱查詢(模式 B,現行「檔名或 frontmatter 匹配」):
    1. 以 resolve --type persona --list 取得全部 Persona,逐份讀 frontmatter,以輸入比對 name(即 {personaId})與 display_name;輸入符合 ID 格式時另比對檔名的 params.persona。
    2. 命中 1 份 → 顯示摘要(現行);命中多份 → 列出由使用者選擇(現行);0 份 → 照現行詢問是否建立。
    3. 輸入符合 ID 格式時,比對與 resolve --type persona --param persona={輸入} 的結果一致;兩者不同時列出差異,不猜。
  • 新建:{personaId} 由名稱轉 kebab-case(現行);轉換結果不符合 ID 格式(例如中文名稱無法直接轉換)時,向使用者確認 {personaId},不以拼音或編號自行猜測。以 resolve --type persona --param persona={personaId} 取得新路徑;已存在時照現行詢問覆寫或取消。personas/README.md 為 Persona 類型目錄的 README.md(doc-locations.md 第 5 節),內容照現行更新。新建後執行 register。

3.5 查無處置(維持現行)​

skill/情境現行處置
/domain-model 無 Roadmap/Epic進入模式 B,不報錯
/domain-model 指定 Epic 不存在報錯並列出可用 Epic(resolve --type epic --list)
/domain-model 舊路徑、使用者拒絕遷移停止,不寫入
/api-spec 指定 Epic 無目錄或無 US報錯
/api-spec 部分 US 沒有 SBE詢問;沒有任何 SBE 時只用 US
/api-spec 評估摘要不存在繼續
/system-context --sync-only 沒有文件提示先執行 /system-context
/persona 目錄不存在或為空提示 --suggest/--create
/persona --suggest 沒有 Roadmap報錯

4. 測試​

類別測試
範本六個類型(含兩個新類型)R12 通過;以實際路徑 resolve 既有文件與新路徑
拆分domain-model.md 歸 domain-model、domain-model/epic-2.md 歸 domain-model-part;新舊單檔並存時 RS-AMBIGUOUS;多檔 --list 區分 legacy
草稿orders.md 歸 api-spec、orders.generated.md 歸 api-spec-draft,兩者並存時都不報重複 key
走查以可重跑的腳本(記錄命令、exit code、斷言)對參考實作與隔離 workspace 執行:四候選偵測的 0/1/2 個情境、草稿路徑
舊路徑遷移隔離 workspace 的 llms.txt 區塊外放一筆指向 /specs/domain-model 的手寫條目與一行提到舊網址的說明文字:遷移後區塊內有新位置、區塊內外都沒有舊模型路由的條目、手寫描述保留在區塊內、說明文字列入未完成、其他區塊外內容逐位元組不變、register --check exit 0;另以「區塊外條目的新 permalink 不存在」驗證該條目不被刪除且列入未完成
Persona中文顯示名稱與含空白名稱:不呼叫 resolve --param(不出現 RS-PARAM),以 frontmatter display_name 命中;以 ID 查詢命中;兩份同名時列為多筆;查無時進入建立流程;建立時中文名稱無法轉為 ID 而要求確認 ID,確認後 resolve 回傳新路徑
fleet§2.4 的驗證腳本納入證據,送審時以 canonical registry 重跑

5. 會修改的檔案​

檔案變更
/docs-site 的 docs-registry.json、測試四類型範本;拆分 domain-model;新增 api-spec-draft
/docs-site 的 references/doc-locations.md「已遷移的類型」表加入本頁類型
/domain-model、/api-spec、/system-context、/persona 的 SKILL.md§3
m-depends-on.md已遷移類型清單加入設計類(行為不變)
參考實作 app-docs投影更新

6. 待決與審閱重點​

待決:

  1. domain-model 拆成單檔與多檔兩個類型(§2.2),或維持一個類型、改以其他方式表達兩種佈局。
  2. .generated.md 草稿另設 api-spec-draft 類型(§2.3)。
  3. 新多檔以「有任何分檔」判定候選(§3.1),比現行「有 overview.md」更嚴。

請特別看:

  1. §3.1 的四候選偵測是否與 /domain-model 現行規則完全對應(特別是新舊並存、拒絕遷移時的處置)。
  2. /domain-model 舊路徑遷移:受管區塊由 register 重建,區塊外指向舊模型路由的手寫條目定向清理(§3.1)。
  3. Bruno 維持在 registry 之外是否合適。

7. 實作修訂​

項目原設計修訂理由
多檔目錄中有無法解析的檔案(§3.1)未明訂resolve --type domain-model-part --list 回 RS-UNPARSED(例如 domain-model/notes.md)時,/domain-model 停止並列出該檔,依 DR-UNPARSED-LOCATION 處理,不略過略過會讓候選盤點少算一個分檔,等於靜默擇一
/api-spec 其他讀取點(§3.2)只列既有規格判定、補建列舉、US/SBE另改:Step 0.5 的 Domain Model 評估摘要改用 resolve --type assess-summary --param target=domain-model;--adopt-legacy 的候選盤點改用 api-spec --list;反向萃取的規格路徑改用 resolve,建立新規格後 register同一 skill 中殘留固定路徑會與已遷移的類型不一致
/system-context 來源查無(§3.3)「來源」只列 resolve 呼叫補一句:來源 exists: false 或清單為空時照現行略過該來源,不把新路徑當成要建立的文件對應共用契約第 2 節「讀取來源」
/persona 列出與目錄頁(§3.4)未明訂模式 A 與「目錄為空」的提示都以 --list 的 items 判定;personas/README.md 位置為 Persona 類型目錄(尚無 Persona 時為新路徑的目錄)對應共用契約第 5 節「類型目錄」
共用契約與索引(§5)只列 doc-locations.md 的類型表doc-locations.md 另補:參數值須符合類型格式,使用者輸入的名稱不是參數值;第 1 節「其他類型」的舉例移除已遷移的 Domain Model、API Spec。m-docs-site.md、m-methodology.md 的已遷移類型清單同步;/docs-site 1.6.0R1-01 的教訓適用所有以名稱查詢的情境,不只 /persona
skill 版本—/domain-model 3.7.0、/api-spec 5.12.0、/system-context 1.1.0、/persona 1.2.0路徑取得方式改變;/persona 名稱比對另加 display_name
讀取設計類文件的其他 skill未列入範圍本輪不改:/analyze、/assess、/us、/impl 等讀取 Domain Model 時依 /domain-model「位置、解析與舊路徑遷移」,該節已改用 resolve;讀 API Spec、System Context、Persona 的固定路徑與範本路徑相同且沒有舊位置,行為不變。位置字樣更新已明列在文件解析與索引規格 §1 的 P2-5 範圍,包含 /assess 的「Domain Model 沿用現行規則」實作審閱 R1-01:維持本輪 4 個產出 skill 的範圍,延後工作有明確落點
多檔缺少 overview.md以任何分檔判定已有多檔模型,未明訂概覽缺檔的讀寫讀取時略過缺檔、載入既有分檔並維持 multi;/domain-model 在產出階段依已載入分檔及本輪確認內容建立概覽,報告註明新建與來源,不足處列待補;唯讀讀取方只提示,不建立文件。多檔寫入表改為「建立或更新」實作審閱 R1-02:補齊新狀態的處置,避免讀不存在的來源或另建單檔模型