Frontmatter 規格協調
本提案建立一套標準化的 frontmatter 模式,用於協調規格系統中的 Markdown 文件。透過標準化的 YAML frontmatter 元數據,AI 代理和工具可以發現文件關係、驗證一致性,並在複雜的規格層級中導航,無需自訂解析器或外部資料庫。
核心洞見: Markdown frontmatter 是規格文件的天然協調層。當組織內部統一標準化後,frontmatter 便成為可查詢的關係圖譜,讓 AI 代理能夠遍歷規格、偵測衝突並維護一致性,無需專有工具。
問題陳述
現況:不一致的元數據
文件挑戰的證據
| 挑戰 | 影響 |
|---|---|
| 無標準模式 | 每個團隊發明自己的 frontmatter 欄位 |
| 缺失關係 | AI 無法發現相關文件 |
| 無驗證 | 無效參照未被偵測 |
| 僅靠內容發現 | 必須讀取整個文件才能理解結構 |
| 手動交叉引用 | 人工維護的連結逐漸偏離同步 |
根本問題
沒有標準化的 frontmatter:
- AI 代理無法建立文件圖譜
- 驗證需要解析散文,而非元數據
- 一個文件的變更無法自動通知相依者
- 搜尋需要全文比對而非結構化查詢
- 工具必須為每個專案客製化建置
提議方案:Frontmatter 協調模式
目標架構
核心原則
- 模式優先元數據:所有 frontmatter 欄位遵循定義的模式
- 明確關係:文件連結在 frontmatter 中宣告,而非散文中
- 機器可讀發現:工具可以在不解析內容的情況下建立圖譜
- 人類可讀編寫:人類可以撰寫和審查的標準 YAML
- 提交時驗證:CI 驗證模式合規性和參照完整性
Frontmatter 模式規格
必要欄位
每個規格文件必須包含這些欄位:
# 識別(必要)
id: unique-document-identifier # kebab-case,全域唯一
title: 人類可讀標題 # 顯示名稱
type: spec | principle | guideline | decision | proposal
# 生命週期(必要)
status: draft | review | approved | deprecated | archived
version: 1.0.0 # 語意版本
created: 2025-01-15 # ISO 8601 日期
updated: 2025-11-28 # ISO 8601 日期
# 所有權(必要)
owner: team-name | email@company.com關係欄位
文件應使用這些標準化欄位宣告關係:
# 層級關係
inherits: # 繼承的父規格
- org-specs/principles/api-design
- products/vsaas/domains/device
# 對等關係
related: # 非層級的相關文件
- features/video-playback
- features/device-monitoring
# 相依性
depends_on: # 必須先存在/實作
- shared/integrations/sso
- features/authentication
# 跨產品參照
cross_product_refs: # 其他產品的規格
- vortex/features/device-sync
- shared/domains/user-identity
# 覆寫
overrides: # 被修改的上層規格
- principle: org-specs/principles/api-design
requirement: REQ-API-001
justification: 視訊串流需要動作式端點範圍與分類欄位
# 範圍
scope: organization | product | feature | platform | implementation
level: 0 | 1 | 2 | 3 | 4 # 多層級位置
product: vsaas | vortex | cloud-portal
feature: device-management
platform: web | ios | android | backend
# 分類
tags:
- api
- device
- core-feature
domain: device | video | user | billing
# 受眾
audience:
- ai-agent
- developer
- product-manager
visibility: public | internal | confidentialAI 指引欄位
# AI 特定元數據
ai_hints:
- 所有列表端點使用游標分頁
- 設備狀態必須使用 DeviceStatus 列舉
- 設備操作前一律檢查權限
ai_context:
priority: high # AI 讀取的重要性
summary: | # AI 脈絡 (Context) 的簡短描述
設備管理 API 合約,定義站點內設備的 CRUD 操作。
使用游標分頁。
ai_exclude: false # 設為 true 以排除於 AI 脈絡 (Context)關係類型
繼承(inherits)
子文件延伸父文件的層級關係。
語意:
- 子文件繼承父文件的所有需求
- 子文件可延伸但不可矛盾父文件(除非宣告
overrides) - 父文件變更自動影響子文件
範例:
id: web-device-management
inherits:
- products/vsaas/features/device-management/requirement
- org-specs/shared/components/design-system相依(depends_on)
實作順序約束。
語意:
- 相依規格在相依項存在前無法實作
- 循環相依是驗證錯誤
- 工具可計算實作順序
範例:
id: device-management
depends_on:
- features/authentication # 同產品
- shared/integrations/sso # 共享基礎設施相關(related)
非層級的脈絡 (Context) 關聯。
語意:
- 文件共享脈絡 (Context) 但不繼承
- 變更可能需要審查相關文件
- 慣例上雙向(若 A 關聯 B,B 應關聯 A)
範例:
id: device-management
related:
- features/video-playback # 經常一起使用
- features/device-monitoring # 共享設備概念跨產品參照(cross_product_refs)
跨越產品邊界的參照。
語意:
- 不同產品或共享領域的文件
- 變更需要跨團隊協調
- AI 代理必須讀取參照文件以獲得完整脈絡 (Context)
範例:
id: device-management
product: vsaas
cross_product_refs:
- vortex/features/device-sync # 另一產品的相關功能
- shared/domains/user-identity # 全域領域概念
- shared/domains/permissions # 權限模型覆寫(overrides)
明確修改繼承的需求。
id: vsaas-api-contract
overrides:
- principle: org-specs/principles/api-design
requirement: REQ-API-001
justification: 視訊串流需要動作式端點
approved_by: architecture-guild@company.com
approved_date: 2025-10-15語意:
- 必須參照特定原則和需求
- 必須提供理由
- 記錄核准鏈
- 沒有明確覆寫時,繼承優先
模式驗證
JSON Schema 定義
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://company.com/schemas/spec-frontmatter.json",
"title": "Spec Frontmatter Schema",
"type": "object",
"required": ["id", "title", "type", "status", "version", "created", "updated", "owner"],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
"description": "kebab-case 的唯一識別碼"
},
"title": {
"type": "string",
"minLength": 3,
"maxLength": 100
},
"type": {
"enum": ["spec", "principle", "guideline", "decision", "proposal"]
},
"status": {
"enum": ["draft", "review", "approved", "deprecated", "archived"]
},
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$"
},
"inherits": {
"type": "array",
"items": { "type": "string" }
},
"depends_on": {
"type": "array",
"items": { "type": "string" }
},
"related": {
"type": "array",
"items": { "type": "string" }
},
"cross_product_refs": {
"type": "array",
"items": { "type": "string" }
},
"overrides": {
"type": "array",
"items": {
"type": "object",
"required": ["principle", "requirement", "justification"],
"properties": {
"principle": { "type": "string" },
"requirement": { "type": "string" },
"justification": { "type": "string" },
"approved_by": { "type": "string" },
"approved_date": { "type": "string", "format": "date" }
}
}
}
}
}CI 驗證管線
# .github/workflows/validate-frontmatter.yml
name: 驗證規格 Frontmatter
on:
pull_request:
paths:
- '**/*.md'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 驗證 frontmatter 模式
run: |
npx frontmatter-validator \
--schema .schema/spec-frontmatter.json \
--glob "specs/**/*.md" \
--glob "products/**/features/**/*.md"
- name: 驗證參照完整性
run: |
npx spec-ref-validator \
--check-inherits \
--check-depends-on \
--check-related \
--check-cross-product-refs
- name: 檢查循環相依
run: |
npx spec-graph-validator \
--detect-cycles \
--relationship depends_on參照完整性驗證
// scripts/validate-refs.ts
interface ValidationResult {
valid: boolean;
errors: RefError[];
warnings: RefWarning[];
}
interface RefError {
source: string;
field: string;
target: string;
error: 'not_found' | 'circular' | 'invalid_format';
}
async function validateReferences(specPath: string): Promise<ValidationResult> {
const spec = await parseSpec(specPath);
const errors: RefError[] = [];
// 驗證 inherits 參照
for (const ref of spec.inherits || []) {
if (!await specExists(ref)) {
errors.push({
source: specPath,
field: 'inherits',
target: ref,
error: 'not_found'
});
}
}
// 驗證 depends_on 參照
for (const ref of spec.depends_on || []) {
if (!await specExists(ref)) {
errors.push({
source: specPath,
field: 'depends_on',
target: ref,
error: 'not_found'
});
}
}
// 檢查循環相依
const cycles = await detectCycles(specPath, 'depends_on');
for (const cycle of cycles) {
errors.push({
source: specPath,
field: 'depends_on',
target: cycle.join(' -> '),
error: 'circular'
});
}
return {
valid: errors.length === 0,
errors,
warnings: []
};
}AI 代理整合
文件圖譜建構
// AI 代理可從 frontmatter 建構文件圖譜
interface SpecNode {
id: string;
path: string;
frontmatter: SpecFrontmatter;
children: SpecNode[]; // 繼承此文件的文件
parents: SpecNode[]; // 此文件繼承的文件
dependencies: SpecNode[]; // 此文件相依的文件
dependents: SpecNode[]; // 相依於此文件的文件
related: SpecNode[]; // 相關文件
}
async function buildSpecGraph(rootPath: string): Promise<Map<string, SpecNode>> {
const specs = await glob(`${rootPath}/**/*.md`);
const graph = new Map<string, SpecNode>();
// 第一輪:解析所有 frontmatter
for (const specPath of specs) {
const frontmatter = await parseFrontmatter(specPath);
if (frontmatter.id) {
graph.set(frontmatter.id, {
id: frontmatter.id,
path: specPath,
frontmatter,
children: [],
parents: [],
dependencies: [],
dependents: [],
related: []
});
}
}
// 第二輪:建立關係
for (const [id, node] of graph) {
// 連結繼承
for (const parentId of node.frontmatter.inherits || []) {
const parent = graph.get(resolveId(parentId));
if (parent) {
node.parents.push(parent);
parent.children.push(node);
}
}
// 連結相依
for (const depId of node.frontmatter.depends_on || []) {
const dep = graph.get(resolveId(depId));
if (dep) {
node.dependencies.push(dep);
dep.dependents.push(node);
}
}
// 連結相關
for (const relId of node.frontmatter.related || []) {
const rel = graph.get(resolveId(relId));
if (rel) {
node.related.push(rel);
}
}
}
return graph;
}MCP 資源提供者
// MCP 伺服器公開規格圖譜
const specGraphServer = {
resources: {
// 列出所有規格及其 frontmatter
'spec://list': async () => {
const graph = await buildSpecGraph(SPEC_ROOT);
return Array.from(graph.values()).map(node => ({
uri: `spec://${node.id}`,
name: node.frontmatter.title,
mimeType: 'text/markdown',
metadata: {
type: node.frontmatter.type,
status: node.frontmatter.status,
version: node.frontmatter.version,
parentCount: node.parents.length,
childCount: node.children.length,
dependencyCount: node.dependencies.length
}
}));
}
},
tools: {
// 取得完整繼承鏈
getInheritanceChain: async ({ specId }) => {
const graph = await buildSpecGraph(SPEC_ROOT);
const spec = graph.get(specId);
if (!spec) return { error: '找不到規格' };
const chain = [];
let current = spec;
const visited = new Set();
while (current.parents.length > 0 && !visited.has(current.id)) {
visited.add(current.id);
for (const parent of current.parents) {
chain.push({
id: parent.id,
title: parent.frontmatter.title,
level: parent.frontmatter.level
});
}
current = current.parents[0]; // 追蹤主要繼承
}
return { chain };
},
// 分析變更影響
analyzeImpact: async ({ specId }) => {
const graph = await buildSpecGraph(SPEC_ROOT);
const spec = graph.get(specId);
if (!spec) return { error: '找不到規格' };
const impacted = {
directChildren: spec.children.map(c => c.id),
directDependents: spec.dependents.map(d => d.id),
transitiveImpact: []
};
// BFS 遍歷間接影響
const queue = [...spec.children, ...spec.dependents];
const visited = new Set([specId]);
while (queue.length > 0) {
const node = queue.shift();
if (visited.has(node.id)) continue;
visited.add(node.id);
impacted.transitiveImpact.push(node.id);
queue.push(...node.children, ...node.dependents);
}
return impacted;
},
// 依條件查詢規格
querySpecs: async ({ type, status, product, tags }) => {
const graph = await buildSpecGraph(SPEC_ROOT);
return Array.from(graph.values())
.filter(node => {
if (type && node.frontmatter.type !== type) return false;
if (status && node.frontmatter.status !== status) return false;
if (product && node.frontmatter.product !== product) return false;
if (tags && !tags.every(t => node.frontmatter.tags?.includes(t))) return false;
return true;
})
.map(node => ({
id: node.id,
title: node.frontmatter.title,
path: node.path
}));
}
}
};CLAUDE.md 整合
# Frontmatter 導航 - AI 指引
## 理解 Frontmatter
所有規格文件使用標準化 YAML frontmatter。
使用 frontmatter 導航關係,而非散文內容。
## 讀取任何規格前
1. 先解析 frontmatter
2. 檢查 `inherits` 取得父脈絡 (Context)
3. 檢查 `depends_on` 取得前置條件
4. 檢查 `cross_product_refs` 取得相關產品
5. 然後在完整脈絡 (Context) 下讀取內容
## 建立脈絡 (Context)對於產品 Y 的功能 X:
- 找到:products/{Y}/features/{X}/requirement.md
- 讀取 frontmatter.inherits[] -> 追蹤至組織原則
- 讀取 frontmatter.depends_on[] -> 理解前置條件
- 讀取 frontmatter.cross_product_refs[] -> 相關產品
- 現在在完整關係脈絡 (Context) 下讀取內容
## 驗證變更
修改規格時:
1. 檢查 frontmatter.version -> 適當遞增
2. 更新 frontmatter.updated -> 今天日期
3. 若新增相依 -> 加入 depends_on[]
4. 若覆寫父項 -> 加入 overrides[] 並說明理由
## 查詢圖譜
使用 MCP 工具查詢規格關係:
- `getInheritanceChain(specId)` -> 追蹤至根原則
- `analyzeImpact(specId)` -> 找出受影響文件
- `querySpecs({type, status, product})` -> 找出相關規格實作工作流程
文件建立流程
遷移策略
第一階段:模式定義(第 1 週)
- [ ] 定義 frontmatter JSON schema
- [ ] 建立驗證工具
- [ ] 撰寫模式規格文件
- [ ] 建立文件範本
第二階段:試點遷移(第 2-3 週)
- [ ] 選擇試點產品/功能
- [ ] 為現有規格加入 frontmatter
- [ ] 驗證參照完整性
- [ ] 團隊模式培訓
第三階段:工具整合(第 4-5 週)
- [ ] 實作 CI 驗證管線
- [ ] 建立 MCP 資源提供者
- [ ] 建置規格圖譜視覺化
- [ ] 整合 AI 代理工作流程
第四階段:全面推廣(第 6-8 週)
- [ ] 遷移剩餘產品
- [ ] 更新 CLAUDE.md 檔案
- [ ] 監控驗證指標
- [ ] 根據回饋迭代模式
成功指標
| 指標 | 目標 | 測量方式 |
|---|---|---|
| 模式合規性 | 100% | 所有規格通過驗證 |
| 參照完整性 | 100% | frontmatter 無斷連 |
| 關係覆蓋率 | >80% | 具明確關係的規格比例 |
| AI 導航準確率 | >90% | 正確的脈絡 (Context) 遍歷 |
| 變更影響準確率 | >95% | 預測 vs 實際受影響文件 |
| 發現延遲 | <100ms | frontmatter 查詢 |
應避免的反模式
1. 關係僅在散文中
問題: 在內容中寫「另見:device-management」而非 frontmatter。
為何失敗: AI 和工具無法偵測關係。
應該: 在 frontmatter 中使用 related: 或 cross_product_refs:。
2. 重複資訊
問題: 在子規格中重複繼承的內容。
為何失敗: 內容漂移;更新遺漏重複項。
應該: 透過 inherits: 參照,僅延伸新內容。
3. 隱含相依
問題: 假設實作順序而未宣告。
為何失敗: 平行工作失敗;AI 建議錯誤順序。
應該: 明確宣告於 depends_on: 陣列。
4. 未版本化變更
問題: 修改規格而未更新版本/更新欄位。
為何失敗: 無法追蹤變更;快取提供過時內容。
應該: 始終更新 version: 和 updated: 欄位。
5. 過度巢狀繼承
問題: 建立 10 層以上的繼承鏈。
為何失敗: 難以追蹤;繼承解析變慢。
應該: 繼承深度保持在 5 層以下;使用 related: 進行橫向連結。
範本
規格文件範本
# 識別(必要)
id: feature-name
title: 功能名稱
type: spec
# 生命週期(必要)
status: draft
version: 0.1.0
created: {{DATE}}
updated: {{DATE}}
# 所有權(必要)
owner: team-name
# 範圍
scope: feature
level: 2
product: product-name
feature: feature-name
# 關係
inherits:
- products/{{product}}/principles/domain
- org-specs/principles/api-design
depends_on:
- features/authentication
related:
- features/related-feature
cross_product_refs:
- shared/domains/user-identity
# 分類
tags:
- tag1
- tag2
# AI 指引
ai_hints:
- AI 實作提示
ai_context:
priority: medium
summary: AI 脈絡 (Context) 的簡短描述
# 功能名稱
## 概述
功能的簡短描述。
## 需求
### REQ-001: 需求名稱
系統應當...
#### Scenario: 成功案例
- **WHEN** 條件
- **THEN** 預期結果
## AI 實作備註
@ai-hint 實作指引在此。相關: 全域需求倉庫 | 多產品規格管理 | 代理友善知識庫
參考資料
- YAML Frontmatter - 標準 frontmatter 格式
- JSON Schema - 模式驗證規格
- Model Context Protocol (MCP) - AI 工具整合協定
- OpenSpec - 規格驅動開發框架