# 從結構化事實產生三語 Release Notes

以一個封閉事實來源產生 zh、zh-hant、en 三份發佈說明，並用不變項和 SHA-256 阻止事實漂移。

發佈說明經常需要多語言，但不能因為翻譯而改變版本、配額、介面或產品邊界。這個 Recipe 使用同一個結構化事實檔案產生簡體中文、繁體中文和英文 Markdown，並對每份產物執行確定性驗證。

## 事實來源

預設輸入 `examples/soyaos-cloud-v0.2.0.json` 來自官方 v0.2.0 Release，記錄產品、版本、發佈時間、狀態、官方連結，以及每條事實的唯一 ID、類型、原文與必須逐字保留的不變項。

SoyaOS Cloud 只能翻譯標題、摘要和事實正文，不能加入 URL、數字或新事實。版本、日期和連結由渲染器直接取自事實檔案。

## 準備和執行

安裝 Node.js 22 或更新版本，並依照 [Cloud 快速開始](/zh-hant/docs/cloud-quickstart)建立 API Key。Key 是 opaque string，只放在目前終端的環境變數中。

```bash
git clone https://github.com/soyaos/cloud-recipes.git
cd cloud-recipes
export SOYA_API_KEY='your-soyaos-api-key'
npm run run:multilingual-release-notes
```

預設產物目錄：

```text
output/soyaos-cloud-v0.2.0-release-notes/
├── zh.md
├── zh-hant.md
├── en.md
└── manifest.json
```

## 為什麼使用封閉事實集

一般的「請幫我寫 Release Notes」會讓模型同時負責發現事實、判斷和翻譯，錯誤很難定位。此案例先由人或可信自動化將事實固化成 JSON，再讓 Cloud 處理語言工作。

驗證器要求 locale 必須恰好為 `zh`、`zh-hant`、`en`；三個語種必須包含相同且順序一致的事實 ID；每條不變項必須逐字存在；模型不得加入未核准的數字或 URL；英文不能混入中文正文，繁體中文必須具有繁體文字特徵。

第一次輸出不合格時只允許修復一次，第二次仍失敗就關閉式終止。

## Manifest 與品質閘門

`manifest.json` 記錄版本身分、事實清單、Cloud `requestIds`，以及三個 Markdown 檔案各自的 SHA-256。寫入後修改任何正文都會造成雜湊驗證失敗。

五類閘門分別檢查內容、Markdown 結構、語種、Manifest 完整性和安全。全部通過後，Recipe 才把暫存目錄原子重新命名為最終目錄，不會留下半成品。

## 產生新版本

複製範例 JSON，依相同 schema 寫入新版本的官方事實，再執行：

```bash
node recipes/multilingual-release-notes/run.mjs \
  --input examples/your-release.json \
  --output output/your-release-notes
```

不要把未核實的行銷文案直接當作事實，也不要把 API Key 寫入輸入檔案。

## 常見錯誤

- `invalid_facts`：輸入結構錯誤、URL 帶憑證，或事實 ID 重複。
- `locale_mismatch`：模型沒有回傳完整的三個語種。
- `invariant_changed`：技術標識、配額或其他不變項被改寫。
- `invented_number` / `invented_url`：模型加入事實集以外的數字或連結。
- `quality_gate_failed`：語言、結構、雜湊或安全驗證失敗。

原始碼與測試：[soyaos/cloud-recipes](https://github.com/soyaos/cloud-recipes)

---

Canonical HTML: https://soyaos.ai/zh-hant/docs/cloud-recipes/multilingual-release-notes
