第十二章:正確性保證

12.1 概述

協定透過形式化的正確性屬性(Correctness Properties)定義系統應滿足的不變量。這些屬性是人類可讀規範與機器可驗證正確性保證之間的橋樑,透過屬性測試(Property-Based Testing)進行驗證。

12.2 正確性屬性列表

屬性 1:技能描述符結構完整性

對於任意有效的 SkillDescriptor 物件,它必須包含所有必要欄位:protocol(含 version)、idnameversioncapability_typedescriptionproviderendpointinputsoutputauthaccess。缺少任何必要欄位的物件不應通過驗證。

屬性 2:列舉欄位值域約束

對於任意有效的 SkillDescriptor 物件:

  • capability_type 的值必須是 ["plugin", "api", "knowledge", "task"] 之一
  • access 的值必須是 ["public", "restricted", "private"] 之一
  • auth.type 的值必須是 ["api_key", "oauth2", "custom", "none"] 之一

屬性 3:序列化/解析往返一致性

對於任意有效的 SkillDescriptor 物件,將其序列化為 JSON 文件後再解析回物件,所得結果應與原始物件語意等價:

parse(serialize(descriptor)) == descriptor

屬性 4:Schema 驗證正確性

  • 對於任意符合 Schema 的 JSON 文件,Schema Validator 應成功解析並回傳結構化物件
  • 對於任意不符合 Schema 的 JSON 文件,Schema Validator 應回傳包含具體違規欄位名稱和錯誤原因的錯誤資訊

屬性 5:技能識別碼唯一性

對於任意技能索引中的技能描述符集合,所有技能的 id 欄位值必須互不相同。

屬性 6:技能索引正確性與存取控制

對於任意包含 N 個技能的提供者域,當未認證請求存取 Well-Known URI 時:

  • 回傳的技能索引應包含所有 access 不為 "private" 的技能
  • 不包含任何 access"private" 的技能
  • 索引中每個條目的 descriptor_url 應指向有效的技能描述符

屬性 7:能力類型篩選正確性

對於任意技能集合和任意 CapabilityType 篩選值:

  • 篩選後的結果集中,每個技能的 capability_type 等於篩選值
  • 原始集合中所有符合該類型的技能都出現在結果中

屬性 8:呼叫訊息結構完整性

  • 對於任意有效的 InvocationRequest,必須包含 caller(含 idtype)、skill_idinputs 欄位
  • 對於任意有效的 InvocationResponse,必須包含 execution_idstatusskill_idtimestamps 欄位

屬性 9:協定版本 SemVer 格式

對於任意有效的 ProtocolVersion 物件,其 version 欄位必須符合 MAJOR.MINOR.PATCH 格式,其中 MAJOR、MINOR、PATCH 均為非負整數。

屬性 10:版本不相容偵測

對於任意技能描述符的協定版本和消費者支援的協定版本:

  • 當描述符的主版本號(MAJOR)大於消費者支援的主版本號時,回傳版本不相容錯誤
  • 當主版本號相同時,正常處理

屬性 11:TypeScript 與 JSON Schema 語意一致性

  • 對於任意由 TypeScript 型別定義產生的有效 SkillDescriptor 實例,該實例應通過 JSON Schema 驗證
  • 對於任意通過 JSON Schema 驗證的 JSON 文件,它應能被 TypeScript 型別系統接受

12.3 測試策略

雙軌測試方法

方法目的工具
單元測試驗證具體範例、邊界情況和錯誤條件vitest
屬性測試驗證跨所有輸入的通用屬性fast-check

屬性測試設定

  • 每個屬性測試最少執行 100 次迭代
  • 使用 fast-check 函式庫產生隨機測試資料
  • 每個正確性屬性由單個屬性測試實作
  • 測試標籤格式:Feature: skill-sharing-protocol, Property {N}: {description}

測試範例

import fc from 'fast-check';

fc.assert(
  fc.property(
    skillDescriptorArbitrary,
    (descriptor) => {
      // Feature: skill-sharing-protocol, Property 3: round-trip consistency
      const serialized = serialize(descriptor);
      const parsed = parse(serialized);
      expect(parsed).toEqual(descriptor);
    }
  ),
  { numRuns: 100 }
);