YiBi Dev Docs
架構決策 (ADR)

Spectra 五尺度約束升級與 Upstream Drift 防護

Context

背景

yibi-mvp 使用 Spectra CLI(spectra-app)管理 spec-driven 開發流程,搭配專案自訂的 spectra-amplifier 方法論 skill 做「Spec Kit 五層展開」:

Layer名稱內容
L1User StoriesPersona + Acceptance Criteria
L2QA 邊界FS-NNN 五維度、等價類別/邊界值/狀態轉移速檢
L3衝突偵測Entity 命名、API endpoint、共用資料表、權限模型衝突
L4結構化設計Assumptions 列表、Hard Constraints 列表
L5Done 定義Smoke Tests、QA 技術建議

觀察到的問題

  1. 五層展開缺少粒度約束:L1 User Story 的大小差異懸殊,導致 spec 深度不一——有 的 spec 把 Epic 級需求當 Story 描述,有的把 micro-task 混進 FS-NNN。開發者在 估時和測試切入點上各說各話。

  2. Upstream template/skill drift:yibi-mvp 高度客製化了 spectra 的 task template 和 spec 格式(GIVEN/WHEN/THEN 寫法、[ADDED]/[MODIFIED]/[REMOVED] marker、 五層展開 prompt 風格)。當 upstream Spectra CLI 升版時(v2.2.5 → v2.3.x 月更 頻率),本地客製內容與 upstream 預設產生 drift,沒有機制偵測。

  3. CI 無法阻擋 spec-task divergencespectra analyze 0002-rpi-gemini-live-chatbot-poc 發現 22 個 WARNING(requirements 有 task 對應,design decisions 沒有追蹤), 但這種問題在 PR review 時不可見,直到手動跑 spectra analyze 才被發現。 (附記:0001 與 0002 均為尚未啟動的 POC changes,已在本 PR 以 spectra park 移入 parked 清單,停止追蹤但內容保留;0002 的 22 個 WARNING 是選擇 park 的 直接依據之一。)

決策觸發

Teddy Chen(5xCamp,台灣 BDD/Agile 推廣者)的「五尺度故事切割法」提供了一套 粒度語言,可以疊加在 spectra-amplifier 的 L1 之上,解決 Story 大小不一的問題。 同期,upstream Spectra CLI 高速迭代(月更),需要在「客製深度」與「升版成本」間 建立明確的防護機制。


Decision

結論:分兩條平行路徑升級 spectra 工作流程——五尺度約束(Phase 1)與 Drift 防護(Phase 5)——兩者互不依賴,可並行落地。

Phase 說明:Phase 編號來自 spectra upgrade roadmap(尚未建立獨立文件)。Phase 1 = BDD-scaffold 與粒度規則;Phase 2 = E02 等積壓 spec 補充五尺度標記;Phase 3 = spectra-amplifier skill prompt 更新;Phase 4 = development-dod spec 補 DoD 定義;Phase 5 = Drift 防護三層落地。Phase 1 與 Phase 5 選擇並行的理由見下方第三節。

一、Teddy 五尺度約束疊加在 spectra-amplifier

將 Teddy 的五層粒度語言導入 spectra change 的 proposal 和 spec 撰寫規範:

尺度對應概念在 Spectra 中的對應位置
需求(Requirement)業務目標、使用者痛點proposal.md ## Why 段落
大(Epic/Feature)可交付的完整功能群proposal.md ## What Changes 段落
中(User Story)單一 Actor 一個 Goal,3-5 天可完成specs/<cap>/spec.md User Stories(L1)
小(Scenario)BDD 可執行情境,1 個 Story 含 3-7 個 Scenariospecs/<cap>/spec.md Scenarios(GIVEN/WHEN/THEN)
微(Micro Task)最小實作單元,不超過 4 小時tasks.md 單一 task 行

導入方式(Phase 1)

  1. BDD-scaffold template:更新 spectra new 使用的 task/spec template,在 L1 User Stories 旁加入「尺度標記」欄位,提示 RD 確認每個 Story 是否符合「3-5 天 可完成」的「中」尺度。
  2. spectra validate --strict 粒度規則:在 spectra validate --strict 加入粒度檢查:若一個 spec 的 User Story 沒有對應任何 Scenario,視為 WARNING;若單一 task 估時 超過 8 小時,視為 SUGGEST。
  3. spectra-amplifier skill 更新:在 L1 展開步驟加入五尺度自我檢查問句,引導 撰寫者確認 Story 粒度。

二、三層 Upstream Drift 防護架構

針對「客製 template 與 upstream Spectra CLI 之間的 drift」,建立三層防護:

┌──────────────────────────────────────────────────────────────────┐
│  Layer 3:三時機偵測(When to detect)                           │
│  時機 A:/newjob 啟動時偵測 spectra --version 是否升版          │
│  時機 B:/spectra-apply 執行前偵測 template 是否被 overwrite     │
│  時機 C:PR merge 後 /spectra-archive 時比對 vendored baseline   │
└──────────────┬───────────────────────────────────────────────────┘

┌──────────────▼───────────────────────────────────────────────────┐
│  Layer 2:Vendored Baseline(What changed from upstream)         │
│  在 docs/openspec/.spectra/vendor/ 存一份 upstream 原始 template │
│  每次 spectra 升版時,diff vendor/ vs 客製版,確認客製內容仍有效  │
└──────────────┬───────────────────────────────────────────────────┘

┌──────────────▼───────────────────────────────────────────────────┐
│  Layer 1:Marker Block(Where customization lives)               │
│  在每個客製 template/skill 的自訂段落前後加:                     │
│  <!-- CUSTOM:BEGIN scope=yibi-mvp -->                            │
│  <!-- CUSTOM:END -->                                             │
│  Marker 讓 diff 工具可以準確對齊「哪些是客製,哪些是 upstream」   │
└──────────────────────────────────────────────────────────────────┘

Layer 1 — Marker Block

  • 格式:<!-- CUSTOM:BEGIN scope=yibi-mvp reason="..." -->
  • 作用:讓 spectra drift 指令和 review 工具能精準識別客製段落
  • 原則:Marker 之外的區塊視為 upstream 可覆蓋範圍

Layer 2 — Vendored Baseline

  • 路徑:docs/openspec/.spectra/vendor/實作時路徑調整為 docs/openspec/spectra-vendor/(無 dot),見 Postscript
  • 內容:task-template.mdspec-template.mdproposal-template.md 的 upstream 原始版本
  • 更新時機:確認升版安全(diff 完成、客製 marker 驗證過)後手動更新
  • 版本記錄:vendor/VERSION(記錄對應的 spectra CLI 版本)

Layer 3 — 三時機偵測

時機觸發點偵測內容動作
A — Startup/newjob hookspectra --version vs vendor/VERSION有差異 → 印 WARN,提示 spectra drift
B — Apply 前/spectra-apply Step 1template 是否有 CUSTOM:BEGIN marker無 marker → 印 WARN,引導補標記
C — Archive 後/spectra-archive 收尾新 archived spec 與 vendor baseline 的 diff有 upstream 覆蓋客製段落 → 印 ERROR

三、Phase 1 與 Phase 5 並行落地的理由

兩個 Phase 選擇並行而非序列的原因:

  1. 互不依賴:五尺度約束修改的是 template 的「撰寫指引」部分;Drift 防護修改的是 template 的「版本追蹤」部分。兩者在 marker block 內分別佔用不同段落,不衝突。

  2. 提早驗收 Drift 防護的有效性:若 Drift 防護在 Phase 5 才上線,中間 Phase 2-4 的升版事件就沒有防護機制。並行可以讓 Layer 1 marker 在 Phase 1 template 就位時 一起寫入,Phase 5 完成時已有完整的 marker coverage。

  3. 風險隔離:五尺度約束是「方法論層」的修改,失敗頂多讓 spec 寫不好,不影響 生產系統。Drift 防護是「工具層」的修改,若有誤報可以關掉。兩條路徑互相不會因 對方的問題而阻塞。


Alternatives Considered

  • 只做五尺度約束,不做 Drift 防護:考慮過。短期可行,但 Spectra 的月更頻率意味 着 2-3 個月後客製 template 就會出現無人知曉的 drift。0002 的 22 個 WARNING 是 當前已有的 drift 問題,不處理會繼續累積。

  • 完全放棄客製化,跟著 upstream 走:考慮過。但 yibi-mvp 的五層展開結構(Spec Kit) 和 BDD GIVEN/WHEN/THEN + [ADDED]/[MODIFIED]/[REMOVED] marker 風格,是在多個 change 實戰中驗證有效的,丟棄這些等於倒退回 PR #378 之前的狀態。

  • 用 git submodule 追蹤 upstream:考慮過。spectra-app 的 template 不是一個獨立 repo,且 macOS app bundle 不適合 submodule 管理。vendored baseline(Layer 2)是 更輕量的替代方案:只保存 template 文字,不追蹤 binary。

  • 序列執行(先做五尺度再做 Drift 防護):考慮過。主要問題是 Drift 防護延後上線 會讓中間的升版窗口沒有保護。並行的額外成本只有需要同時管理兩個 branch,可接受。

  • spectra validate --strict 取代 Drift 防護:考慮過。spectra validate 驗證的是 change 的結構有效性(schema),不是 template 與 upstream 的版本一致性。 兩者目標不同,不可相互替代。


Consequences

  • 五尺度語言讓 Story 大小有公共標準,估時討論有共同參照
  • Drift 防護讓 spectra 升版從「不知道有沒有問題」變成「有 CI-level 可見性」
  • Marker Block 強制讓客製內容自我標記,降低新 RD 理解成本
  • 並行落地讓 Drift 防護提早 1-2 個 sprint 開始保護,而非等到 Phase 5 才有

壞 / 代償

  • Vendor baseline 需要在每次 spectra 升版時手動更新(預計 2-4 次/季)
  • Marker block 語法需要 RD 學習,初期有遺漏風險(靠 Phase 5 的 spectra-apply Step 1 偵測兜底)
  • 並行管理兩條 branch 增加 merge 複雜度(可用各自獨立 spectra change 隔離)

中性

  • spectra drift 指令(Spectra CLI 內建,本專案由 /spectra-drift skill 封裝)已存在, Layer 3 偵測可以復用其輸出格式,不需自行實作 diff 邏輯
  • 五尺度約束只是「寫作指引」,不改變 spec 的機器可讀格式,既有 change 不需 migrate
  • development-dod/spec.md 後續會加入五尺度的 DoD 定義(獨立 PR,不在本 ADR 範圍)

Postscript — 2026-05-19 Follow-up

發現:Layer 3A 假陽性 Checkbox

2026-05-19 系統性回顧 change 0017 執行成果時,發現 tasks.md task 8.1 標記為 [x],但實際的 ~/.claude/commands/scripts/newjob-validate.sh 並未包含 Step 3g(Spectra version drift check)。驗證指令:

grep -q "Spectra version drift" ~/.claude/commands/scripts/newjob-validate.sh
# → exit 1(檔案存在但缺少該字串)

Layer 3A 的邏輯存在於 ADR-0006 文字與任務計畫中,但未落地成可執行程式碼。Layer 3B(/spectra-apply)與 Layer 3C(/spectra-archive)均正確實作。

補救:Layer 3A 補丁將在後續 PR(Wave A1)補實,修改 ~/.claude/commands/scripts/newjob-validate.sh(install source:yibi-stack/commands/scripts/newjob-validate.sh),在 Step 3g 加入讀取 docs/openspec/spectra-vendor/VERSION 並與 spectra --version 比對、輸出 [OK][WARN] 的邏輯。本 PR(#403)不含此修改。

發現:Phase 2 Backfill 覆蓋率 77%(59/76 spec)

Phase 2 任務標記為「完成」,但 17 份 spec 仍缺五尺度 marker。2026-05-19 本 follow-up PR 補齊:

類型數量處理方式
TBD stub(無 ### Requirement: 段落)8<!-- five-scale: exempt reason="TBD stub..." --> 備註
Epic 索引 spec(Requirements 在 F-spec 層)3<!-- five-scale: exempt reason="Epic index spec..." --> 備註
F-spec(使用 ### User Story N 格式)6<!-- five-scale: exempt reason="F-spec format..." --> 備註

F-spec 使用 ### User Story N 格式,每個 User Story 已是「中」尺度(Teddy Chen 五層定義),與 ### Requirement: 語意等同,無需逐段加 CUSTOM:BEGIN marker。

學到的事:Task 驗收必須跑 Grep 證據

此次假陽性暴露了一個流程缺口:任務標記 [x] 時沒有驗證「產物是否真的存在」。

後續改進(已建議補入 /spectra-archive 的 pre-flight 清單):

  • 涉及「修改腳本 / skill」的 task,archive 前必須執行 grep 驗證關鍵字在目標檔案中存在
  • 若有 CI-detectable 的驗收條件,應補充為 ## Acceptance Criteria 的可執行測試

ADR 決策鏈(後續相關 ADR)

  • ADR-0007(accepted,本 PR #403,2026-05-19):Sub-agent Context Boundary — 補中尺度約束(agent role taxonomy + path-scope)
  • ADR-0008(proposed,Change 0018,2026-05-19):BDD Test Traceability — 補 spec Scenario ↔ pytest 測試 trace 機制
  • Wave D(A/B/C 完成後):將整套方法論(五尺度 + drift 防護 + agent boundary + BDD trace)抽出為 .claude/skills/spectra-scale-constraints/ 可重用 skill

related.subsequent 見 frontmatter。

Postscript — 2026-07-03 Layer 2 擴充:CI OSS OpenSpec pin(ADR-0021 / issue #665)

ADR-0021 新增一道 ubuntu CI spec-consistency gate,跑開源 @fission-ai/openspec CLI(macOS-only Spectra binary 的 upstream)。此舉在 Layer 2 vendored baseline 之外 新增第二個需追蹤的 upstream 版本:

  • 新增 docs/openspec/spectra-vendor/CI_OPENSPEC_VERSION(記錄 CI pin,如 @fission-ai/openspec@1.5.0),與既有 VERSION(Spectra macOS CLI 版本)並列。
  • Layer 2 vendor-drift 審查納入 CI pin:升 Spectra 或升 CI OSS pin 時,除了 diff vendor template,另需重新量測 OSS ↔ Spectra 的 validate 規則分歧並更新 spectra-vendor/README.md 的「CI OpenSpec pin」段。

首次量測(2026-07-03,openspec 1.5.0 vs spectra 2.3.1):OSS 為 stricter superset (強制 requirement body 含 SHALL/MUST、每 requirement 至少一個 Scenario、更嚴的 delta 結構),對 6 個 active change 判定不同於 Spectra。這是 ADR-0021 gate 採「diff-scoped + Phase 1 report-only」rollout 的直接理由。詳見 ADR-0021 與 spectra-vendor/README.md

On this page