# Schedule Doc Generator

> 為 Spring Boot 專案中的排程工作（Scheduled Jobs）產生標準化的說明文件。支援 DDD、Axon Framework、Spring Modulith 等架構。所有文件以繁體中文撰寫，輸出為 Markdown 格式，儲存於 docs/schedule 目錄下。適用於使用者提供排程工作的程式碼、設定檔或口頭描述，自動產生完整的排程工作說明文件。

- Skill: `elliotchen/schedule-doc-generator` (Agent Skill)
- Install (CLI): `npx skillmds@latest add elliotchen/schedule-doc-generator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/elliotchen/schedule-doc-generator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: ElliotChen (https://skillmd.com/u/elliotchen)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/elliotchen/schedule-doc-generator

---


# 排程工作說明文件產生器（Schedule Job Documentation Generator）

## 概述

本技能用於為 Spring Boot 專案中的排程工作產生標準化的技術說明文件。文件涵蓋業務目的、執行邏輯、依賴關係、錯誤處理、冪等性分析、監控告警與維運操作等面向。

## 使用時機

當使用者提出以下需求時，觸發本技能：

- 「幫我寫排程的說明文件」
- 「產生 scheduled job 的文件」
- 「記錄這個 cron job 的規格」
- 「建立排程工作文件」
- 提供排程相關的程式碼（如帶有 `@Scheduled`、`@Saga`、`DeadlineManager`、Quartz 設定等）並要求產生文件

## 輸入來源

Claude 應嘗試從以下來源蒐集排程工作的資訊：

1. **程式碼**：使用者提供的 Java/Kotlin 原始碼，包含排程設定、業務邏輯
2. **設定檔**：`application.yml`、`application.properties` 或 Quartz 設定
3. **口頭描述**：使用者以自然語言描述排程的用途與行為
4. **既有文件**：需要更新或補充的既有說明文件

如果資訊不足，Claude 應主動詢問以下關鍵問題：

- 排程的業務目的是什麼？
- 排程的觸發頻率（Cron Expression）？
- 涉及哪些資料來源與外部服務？
- 是否在多實例環境中部署？如何避免重複執行？
- 失敗時的處理策略？

## 輸出規範

### 檔案結構

所有文件儲存於專案根目錄下的 `docs/schedule/` 目錄：

```
docs/schedule/
├── README.md                          # 排程工作總覽（多份文件時必須產生）
├── SCH-001-每日對帳處理.md             # 個別排程說明文件
├── SCH-002-月結報表產生.md
└── SCH-003-過期訂單清理.md
```

### 檔案命名規則

- 格式：`SCH-{序號}-{排程名稱簡述}.md`
- 序號使用三位數字，從 001 開始
- 名稱簡述使用繁體中文，簡潔描述排程用途
- 如果使用者已有既定的編號規則，遵循使用者的規則

### 語言

- **所有內容使用繁體中文**
- 技術專有名詞（如 Event Sourcing、Saga、Cron Expression）保留英文
- 程式碼片段保留原文

---

## 文件模板

每份排程工作說明文件必須包含以下章節。Claude 應依據蒐集到的資訊填寫各章節，若資訊不足則標記為 `[待補充]` 並提醒使用者。

### 完整模板結構

```markdown
# {排程工作名稱}

| 項目 | 內容 |
|------|------|
| **文件編號** | SCH-XXX |
| **排程名稱** | {名稱} |
| **所屬模組 / Bounded Context** | {模組名稱} |
| **負責人** | {姓名或團隊} |
| **排程類型** | Cron Job / Fixed Rate / Fixed Delay / Saga Deadline / Event-Driven |
| **排程表達式** | `{cron expression}` |
| **執行頻率說明** | {人類可讀的頻率描述，例如：每日凌晨 02:00 執行} |
| **預估執行時間** | {正常情況下的執行耗時} |
| **最後更新日期** | {日期} |

---

## 1. 業務目的

{說明此排程存在的業務原因，解決什麼問題，帶來什麼價值。}

## 2. 執行邏輯

### 2.1 處理流程

{以文字或流程描述排程的主要處理步驟。}

### 2.2 資料流向

| 方向 | 來源/目標 | 說明 |
|------|-----------|------|
| 讀取 | {資料來源} | {讀取什麼資料} |
| 寫入 | {目標} | {寫入什麼資料} |
| 呼叫 | {外部服務} | {呼叫目的} |
| 發送 | {Event/Message} | {發送什麼事件} |

### 2.3 資料量預估

| 指標 | 預估值 |
|------|--------|
| 每次處理筆數 | {數量} |
| 資料成長趨勢 | {說明} |

## 3. 執行條件與依賴

### 3.1 前置條件

{列出必須滿足的前置條件。}

### 3.2 外部依賴

| 依賴項目 | 類型 | 必要性 | 不可用時的影響 |
|----------|------|--------|----------------|
| {名稱} | DB / API / MQ / File | 必要 / 選用 | {影響描述} |

### 3.3 執行環境

| 項目 | 說明 |
|------|------|
| **部署模式** | 單實例 / 多實例 |
| **併發控制** | {ShedLock / Quartz Cluster / Leader Election / 無} |
| **鎖定機制** | {具體設定，如 lockAtMostFor, lockAtLeastFor} |
| **時區** | {使用的時區，例如 Asia/Taipei} |

## 4. 冪等性與可重複執行分析

> ⚠️ 此章節為關鍵分析項目，評估排程在異常後能否安全地重複執行。

### 4.1 冪等性評估

| 評估項目 | 結果 | 說明 |
|----------|------|------|
| **可重複執行** | ✅ 是 / ❌ 否 / ⚠️ 有條件 | {整體結論} |
| **資料讀取冪等** | ✅ / ❌ | {讀取操作是否受重複執行影響} |
| **資料寫入冪等** | ✅ / ❌ | {寫入操作是否使用 UPSERT 或唯一鍵約束} |
| **外部呼叫冪等** | ✅ / ❌ | {外部 API 呼叫是否支援冪等} |
| **事件發送冪等** | ✅ / ❌ | {是否可能產生重複事件，消費端是否能處理} |

### 4.2 重複執行風險

{詳細描述如果重複執行，可能發生的問題：}

- **資料面**：是否會產生重複記錄？金額是否會重複計算？
- **事件面**：是否會發送重複事件？下游是否有去重機制？
- **外部服務面**：是否會重複呼叫產生副作用（如重複發送通知、重複扣款）？

### 4.3 安全重複執行的條件

{如果可以重複執行，列出必須滿足的條件。如果不能重複執行，說明原因與替代方案。}

### 4.4 手動重跑指引

| 項目 | 說明 |
|------|------|
| **是否可安全重跑** | {是/否/有條件} |
| **重跑前檢查事項** | {需要確認的項目} |
| **重跑方式** | {API 端點 / 管理介面 / 指令} |
| **重跑後驗證** | {如何確認重跑結果正確} |

## 5. 錯誤處理

### 5.1 重試策略

| 項目 | 設定 |
|------|------|
| **自動重試** | 是 / 否 |
| **重試次數** | {次數} |
| **重試間隔** | {間隔策略，如 Exponential Backoff} |
| **最終失敗處理** | {Dead Letter Queue / 人工介入 / 告警} |

### 5.2 補償邏輯

{說明失敗後的補償機制，特別是在 Saga 模式下的回滾步驟。}

### 5.3 部分失敗處理

| 策略 | 說明 |
|------|------|
| **處理方式** | 整批回滾 / 跳過失敗項繼續 / 記錄後人工處理 |
| **失敗記錄** | {如何記錄失敗的項目} |

### 5.4 超時處理

| 項目 | 設定 |
|------|------|
| **超時時間** | {時間} |
| **超時處理** | {中斷 / 告警 / 等待完成} |

## 6. 監控與告警

### 6.1 日誌規範

| 時機 | Log Level | 內容 |
|------|-----------|------|
| 排程開始 | INFO | 排程啟動，參數資訊 |
| 批次進度 | INFO / DEBUG | 處理進度（每 N 筆） |
| 業務警告 | WARN | {具體場景} |
| 執行錯誤 | ERROR | 錯誤詳情與堆疊 |
| 排程結束 | INFO | 執行結果摘要（耗時、筆數、成功/失敗） |

### 6.2 監控指標

| 指標名稱 | 類型 | 說明 |
|----------|------|------|
| {metric_name} | Counter / Gauge / Timer | {說明} |

### 6.3 告警規則

| 條件 | 嚴重度 | 通知管道 | 處理方式 |
|------|--------|----------|----------|
| {條件描述} | Critical / Warning | {Slack / Email / PagerDuty} | {處理建議} |

## 7. 維運操作

### 7.1 手動觸發

{說明如何手動觸發此排程，例如 API 端點、Actuator Endpoint、管理介面等。}

### 7.2 暫停與恢復

| 操作 | 方式 | 注意事項 |
|------|------|----------|
| 暫停 | {方式} | {注意事項} |
| 恢復 | {方式} | {是否需要補跑} |

### 7.3 常見問題排除

| 問題 | 可能原因 | 排除步驟 |
|------|----------|----------|
| {問題描述} | {原因} | {步驟} |

## 8. 變更紀錄

| 日期 | 版本 | 變更內容 | 變更者 |
|------|------|----------|--------|
| {日期} | 1.0 | 初始版本 | {人員} |
```

---

## README.md 模板

當 `docs/schedule/` 目錄下有多份排程文件時，必須產生或更新 `README.md` 作為總覽索引。

```markdown
# 排程工作說明文件總覽

## 概述

本目錄包含所有排程工作的標準化說明文件。

## 排程工作清單

| 編號 | 排程名稱 | 所屬模組 | 執行頻率 | 可重複執行 | 文件連結 |
|------|----------|----------|----------|------------|----------|
| SCH-001 | {名稱} | {模組} | {頻率} | ✅ / ❌ / ⚠️ | [連結](SCH-001-xxx.md) |

## 排程相依關係

{如果排程之間有先後相依關係，在此繪製說明。}

## 重複執行安全性總覽

| 編號 | 排程名稱 | 可重複執行 | 風險等級 | 備註 |
|------|----------|------------|----------|------|
| SCH-001 | {名稱} | ✅ / ❌ / ⚠️ | 低 / 中 / 高 | {簡要說明} |

> **風險等級定義：**
> - 🟢 **低風險**：完全冪等，可隨時安全重跑
> - 🟡 **中風險**：有條件冪等，重跑前需確認狀態
> - 🔴 **高風險**：非冪等，重跑可能造成資料異常

## 共用基礎設施

| 項目 | 技術 | 說明 |
|------|------|------|
| 併發控制 | {ShedLock / Quartz Cluster} | {簡述} |
| 監控平台 | {Grafana / Prometheus / etc.} | {簡述} |
| 告警管道 | {Slack / PagerDuty / etc.} | {簡述} |
```

---

## 冪等性分析指引

在撰寫「第 4 節 冪等性與可重複執行分析」時，Claude 應依照以下邏輯進行分析：

### 分析步驟

1. **識別所有副作用（Side Effects）**
   - 資料庫寫入（INSERT / UPDATE / DELETE）
   - 事件發送（Domain Event / Integration Event）
   - 外部 API 呼叫
   - 檔案寫入
   - 通知發送（Email / SMS / Push）

2. **逐一評估每個副作用的冪等性**
   - INSERT：是否有唯一鍵約束？是否使用 UPSERT？
   - UPDATE：是否基於狀態機？是否有樂觀鎖？
   - DELETE：是否使用軟刪除？重複刪除是否安全？
   - 事件發送：消費端是否有去重機制（Idempotent Consumer）？
   - 外部呼叫：API 是否支援冪等鍵（Idempotency Key）？

3. **評估時間窗口影響**
   - 如果排程基於時間範圍查詢（如「處理昨天的資料」），重複執行是否會處理到不同的資料集？
   - 是否有明確的處理狀態標記（如 processed flag）？

4. **綜合判定**
   - ✅ **可重複執行**：所有副作用皆冪等，重複執行不會產生任何負面影響
   - ⚠️ **有條件可重複執行**：部分副作用冪等，但需滿足特定條件（明確列出）
   - ❌ **不可重複執行**：存在非冪等副作用，需要手動介入才能重跑

### 常見的冪等性問題模式

| 模式 | 問題 | 建議 |
|------|------|------|
| 無狀態標記的批次處理 | 重複執行會重複處理同一批資料 | 加入 processed flag 或使用 UPSERT |
| 累加型計算（如加總金額） | 重複執行導致金額翻倍 | 改為全量重算或使用冪等寫入 |
| 發送通知後無記錄 | 重複執行導致重複發送通知 | 記錄發送狀態，發送前檢查 |
| Saga 中間狀態 | 部分步驟完成後重跑 | 利用 Saga 框架的恢復機制 |
| Event Sourcing Replay | Projection 重建可能觸發副作用 | 區分 Replay 與 Live 事件 |

---

## 技術框架特殊處理

### Spring Boot @Scheduled

- 記錄 `@Scheduled` 的 cron / fixedRate / fixedDelay 設定
- 檢查是否搭配 `@SchedulerLock`（ShedLock）

### Axon Framework

- **Saga Deadline**：記錄 DeadlineManager 的使用方式與 Deadline Name
- **Event Handler 排程**：如果使用 `@EventHandler` 搭配時間條件觸發
- **Replay 影響**：分析 Replay 時是否會重新觸發排程相關的副作用

### Quartz Scheduler

- 記錄 Job 與 Trigger 的設定
- 記錄 Cluster 模式的設定（`org.quartz.jobStore.*`）
- 記錄 Misfire 策略

### Spring Modulith

- 記錄模組間的事件訂閱關係
- 分析跨模組事件發送的冪等性

---

## 智慧更新模式

本技能支援兩種模式，**請於每次任務開始時，針對「每一個」要產生文件的排程工作執行模式偵測**：

- **生成模式（Generate）**：該排程尚未有對應的 `docs/schedule/SCH-XXX-*.md` 文件 → 從零產生完整文件，並分配下一個未使用的 SCH 編號。
- **更新模式（Update）**：該排程已有對應文件 → 切換為「智慧增量更新」，僅修改差異段落，保留其餘內容與使用者自訂修改。

### 模式偵測流程

對每一個待文件化的排程工作：

```
1. 列出現有文件：ls docs/schedule/SCH-*.md
2. 嘗試以下列任一方式匹配既有文件：
   a. 表頭表格中的「排程名稱」或「所屬模組 / Bounded Context」
   b. Cron 表達式
   c. @Scheduled 方法的完整類別 / 方法名稱（或 Saga Deadline Name、Quartz Job 名稱）
   d. 使用者明確指定的編號或檔名
3. 若找到匹配文件 → 進入「更新模式」
4. 若無匹配文件 → 進入「生成模式」，分配下一個未使用的 SCH 編號
```

並向使用者顯示偵測結果，例如：

> 偵測到 `SCH-002-月結報表產生.md` 對應此排程，將進入**更新模式**並執行智慧增量更新。

或：

> 未偵測到對應文件，將分配編號 SCH-004 並進入**生成模式**。

若使用者明確要求「重做」、「全部重新生成」、「regenerate」等，可由使用者覆寫為生成模式（會覆蓋既有文件，建議先 Git commit）。

### 智慧增量更新原則

進入更新模式後遵循以下原則：

1. **永遠先讀後寫**：使用 view / Read 完整讀取既有文件，再決定要改什麼，禁止盲目覆寫
2. **以差異為單位**：比對「最新原始碼 / 設定 / 口頭描述」與「既有文件描述」，列出差異點清單後才動工
3. **只改必要段落**：使用 `str_replace` 精確替換，**不重寫整份文件**，未受影響的章節保持原樣
4. **保留使用者自訂**：辨識並保留 `<!-- 自訂內容開始 -->` ~ `<!-- 自訂內容結束 -->` 區塊；對於明顯人工撰寫的段落（如團隊備註、實際維運經驗），優先保留，必要時提示使用者再次確認
5. **同步更新 README**：若排程屬性（名稱、頻率、可重複執行性、風險等級）有變動，須同步更新 `README.md` 的對應列
6. **必填變更紀錄**：在文件「## 8. 變更紀錄」表格新增一筆，包含日期、新版本號、變更內容、變更者
7. **更新表頭日期**：將表頭表格的「最後更新日期」改為當日

### 比對與差異識別流程

```
1. 讀取既有文件（view docs/schedule/SCH-XXX-*.md）
2. 收集最新輸入：
   - 使用者描述的變更
   - 必要時讀取程式碼（@Scheduled 方法、@SchedulerLock、application.yml、Quartz 設定等）
3. 列出「差異清單」：
   - Cron 表達式或執行頻率改了嗎？
   - 業務邏輯（流程、資料流向、副作用）改了嗎？
   - 依賴項目（DB / API / MQ / File）增刪了嗎？
   - 冪等性結論是否需要重新評估？
   - 重試策略、超時設定、監控指標、告警規則有異動嗎？
   - 部署模式（單實例 / 多實例、ShedLock / Quartz Cluster）改了嗎？
4. 將差異清單對映到「受影響章節」（例如 §2.1、§4.1）
5. 與使用者確認差異清單後，才開始執行 str_replace
```

### 常見更新情境與影響章節

| 變更類型 | 影響章節 |
|---------|---------|
| Cron 表達式或頻率調整 | 表頭「排程表達式」「執行頻率說明」、§2.1、§8 變更紀錄 |
| 新增 / 移除外部依賴 | §3.2、（若為共用）README「共用基礎設施」 |
| 重試策略調整 | §5.1、§5.4、可能連動 §4 冪等性結論 |
| 新增冪等性保護（UPSERT、processed flag、Idempotency Key） | §4 全章節、README「重複執行安全性總覽」 |
| 監控 / 告警新增或調整 | §6.1、§6.2、§6.3 |
| 部署模式改變（單實例 → 多實例） | §3.3、§4 風險評估，必要時新增 ShedLock / Leader Election 設定 |
| Saga Deadline 調整 | 表頭「排程類型」「排程表達式」、§2、§4 |
| 維運操作流程改變 | §7.1、§7.2、§7.3 |

### 保留使用者自訂內容

建議使用者在文件中以下列註解標記團隊自訂段落，本技能更新時會完整保留：

```markdown
<!-- 自訂內容開始 -->
這裡是維運團隊累積的實際操作經驗、特例處理…
<!-- 自訂內容結束 -->
```

更新時，本技能會：
- 識別並保留 `<!-- 自訂內容開始 -->` 和 `<!-- 自訂內容結束 -->` 之間的內容
- 僅更新標記之外的自動生成內容
- 提醒使用者檢查自訂內容是否仍然適用

---

## 執行流程

1. **偵測模式**：對每個待文件化的排程，依「智慧更新模式」章節判斷進入生成或更新模式（必執行的第一步）
2. **蒐集資訊**：從使用者提供的程式碼、設定檔或描述中擷取排程相關資訊
3. **分析程式碼**：如有原始碼，分析排程邏輯、副作用、冪等性
4. **產生 / 更新文件**：
   - 生成模式：依照模板產生完整的排程說明文件
   - 更新模式：依「比對與差異識別流程」執行精確的 `str_replace`，不重寫全文，並保留 `<!-- 自訂內容 -->` 區塊
5. **冪等性分析**：依照分析指引，完成或重新評估第 4 節的冪等性評估
6. **儲存檔案**：將文件儲存至 `docs/schedule/` 目錄
7. **更新 README**：依模式同步 `README.md`
   - 生成模式：新增對應的索引列與「重複執行安全性總覽」列
   - 更新模式：若屬性（名稱、頻率、可重複執行性、風險等級）有異動，更新對應列
8. **更新變更紀錄**（更新模式必填）：在文件「## 8. 變更紀錄」新增一筆，並把表頭「最後更新日期」改為當日
9. **提示使用者**：標記所有 `[待補充]` 的項目，提醒使用者補充

## 注意事項

- 所有文件內容使用**繁體中文**
- 技術專有名詞保留英文
- 如果資訊不足，以 `[待補充]` 標記，不要自行編造
- 冪等性分析必須基於實際的程式碼或邏輯，不能假設
- 儲存路徑固定為 `docs/schedule/`
- 每次產生或更新文件時，同步更新 `README.md`

