Skip to content

Frontmatter 規格協調

本提案建立一套標準化的 frontmatter 模式,用於協調規格系統中的 Markdown 文件。透過標準化的 YAML frontmatter 元數據,AI 代理和工具可以發現文件關係、驗證一致性,並在複雜的規格層級中導航,無需自訂解析器或外部資料庫。

核心洞見: Markdown frontmatter 是規格文件的天然協調層。當組織內部統一標準化後,frontmatter 便成為可查詢的關係圖譜,讓 AI 代理能夠遍歷規格、偵測衝突並維護一致性,無需專有工具。

問題陳述

現況:不一致的元數據

文件挑戰的證據

挑戰影響
無標準模式每個團隊發明自己的 frontmatter 欄位
缺失關係AI 無法發現相關文件
無驗證無效參照未被偵測
僅靠內容發現必須讀取整個文件才能理解結構
手動交叉引用人工維護的連結逐漸偏離同步

根本問題

沒有標準化的 frontmatter:

  • AI 代理無法建立文件圖譜
  • 驗證需要解析散文,而非元數據
  • 一個文件的變更無法自動通知相依者
  • 搜尋需要全文比對而非結構化查詢
  • 工具必須為每個專案客製化建置

提議方案:Frontmatter 協調模式

目標架構

核心原則

  1. 模式優先元數據:所有 frontmatter 欄位遵循定義的模式
  2. 明確關係:文件連結在 frontmatter 中宣告,而非散文中
  3. 機器可讀發現:工具可以在不解析內容的情況下建立圖譜
  4. 人類可讀編寫:人類可以撰寫和審查的標準 YAML
  5. 提交時驗證:CI 驗證模式合規性和參照完整性

Frontmatter 模式規格

必要欄位

每個規格文件必須包含這些欄位:

yaml
# 識別(必要)
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

關係欄位

文件應使用這些標準化欄位宣告關係:

yaml
# 層級關係
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: 視訊串流需要動作式端點

範圍與分類欄位

yaml
# 範圍
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 | confidential

AI 指引欄位

yaml
# AI 特定元數據
ai_hints:
  - 所有列表端點使用游標分頁
  - 設備狀態必須使用 DeviceStatus 列舉
  - 設備操作前一律檢查權限

ai_context:
  priority: high                     # AI 讀取的重要性
  summary: |                         # AI 脈絡 (Context) 的簡短描述
    設備管理 API 合約,定義站點內設備的 CRUD 操作。
    使用游標分頁。

ai_exclude: false                    # 設為 true 以排除於 AI 脈絡 (Context)

關係類型

繼承(inherits

子文件延伸父文件的層級關係。

語意:

  • 子文件繼承父文件的所有需求
  • 子文件可延伸但不可矛盾父文件(除非宣告 overrides
  • 父文件變更自動影響子文件

範例:

yaml
id: web-device-management
inherits:
  - products/vsaas/features/device-management/requirement
  - org-specs/shared/components/design-system

相依(depends_on

實作順序約束。

語意:

  • 相依規格在相依項存在前無法實作
  • 循環相依是驗證錯誤
  • 工具可計算實作順序

範例:

yaml
id: device-management
depends_on:
  - features/authentication      # 同產品
  - shared/integrations/sso      # 共享基礎設施

非層級的脈絡 (Context) 關聯。

語意:

  • 文件共享脈絡 (Context) 但不繼承
  • 變更可能需要審查相關文件
  • 慣例上雙向(若 A 關聯 B,B 應關聯 A)

範例:

yaml
id: device-management
related:
  - features/video-playback       # 經常一起使用
  - features/device-monitoring    # 共享設備概念

跨產品參照(cross_product_refs

跨越產品邊界的參照。

語意:

  • 不同產品或共享領域的文件
  • 變更需要跨團隊協調
  • AI 代理必須讀取參照文件以獲得完整脈絡 (Context)

範例:

yaml
id: device-management
product: vsaas
cross_product_refs:
  - vortex/features/device-sync      # 另一產品的相關功能
  - shared/domains/user-identity     # 全域領域概念
  - shared/domains/permissions       # 權限模型

覆寫(overrides

明確修改繼承的需求。

yaml
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 定義

json
{
  "$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 驗證管線

yaml
# .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

參照完整性驗證

typescript
// 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 代理整合

文件圖譜建構

typescript
// 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 資源提供者

typescript
// 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 整合

markdown
# Frontmatter 導航 - AI 指引

## 理解 Frontmatter

所有規格文件使用標準化 YAML frontmatter。
使用 frontmatter 導航關係,而非散文內容。

## 讀取任何規格前

1. 先解析 frontmatter
2. 檢查 `inherits` 取得父脈絡 (Context)
3. 檢查 `depends_on` 取得前置條件
4. 檢查 `cross_product_refs` 取得相關產品
5. 然後在完整脈絡 (Context) 下讀取內容

## 建立脈絡 (Context)

對於產品 Y 的功能 X:

  1. 找到:products/{Y}/features/{X}/requirement.md
  2. 讀取 frontmatter.inherits[] -> 追蹤至組織原則
  3. 讀取 frontmatter.depends_on[] -> 理解前置條件
  4. 讀取 frontmatter.cross_product_refs[] -> 相關產品
  5. 現在在完整關係脈絡 (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 實際受影響文件
發現延遲<100msfrontmatter 查詢

應避免的反模式

1. 關係僅在散文中

問題: 在內容中寫「另見:device-management」而非 frontmatter。

為何失敗: AI 和工具無法偵測關係。

應該: 在 frontmatter 中使用 related:cross_product_refs:

2. 重複資訊

問題: 在子規格中重複繼承的內容。

為何失敗: 內容漂移;更新遺漏重複項。

應該: 透過 inherits: 參照,僅延伸新內容。

3. 隱含相依

問題: 假設實作順序而未宣告。

為何失敗: 平行工作失敗;AI 建議錯誤順序。

應該: 明確宣告於 depends_on: 陣列。

4. 未版本化變更

問題: 修改規格而未更新版本/更新欄位。

為何失敗: 無法追蹤變更;快取提供過時內容。

應該: 始終更新 version:updated: 欄位。

5. 過度巢狀繼承

問題: 建立 10 層以上的繼承鏈。

為何失敗: 難以追蹤;繼承解析變慢。

應該: 繼承深度保持在 5 層以下;使用 related: 進行橫向連結。

範本

規格文件範本

markdown
# 識別(必要)
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 實作指引在此。

相關: 全域需求倉庫 | 多產品規格管理 | 代理友善知識庫

參考資料