Community寫作與編輯github.com

mariagorskikh/product-changelog

撰寫並發送定期的產品更新電子報給用戶,然後自動撰寫並發布對應的 X 貼文、LinkedIn 貼文和社群(Discord 或 Slack)公告,並可選擇產出動畫更新影片。

product-changelog 是什麼?

這是一個專為 AI 代理開發的技能,可自動化端到端的產品變更日誌流程。它會基於 Git 提交紀錄、合併請求 (Pull Requests) 和發布說明來挑選用戶可見的變更項目,然後撰寫一封口吻人性化、格式經過精心調整的 HTML 或純文字電子郵件,並嵌入截圖。該技能會先透過自我審查閘門來確保內容品質與連結有效性,然後向測試收件者發送測試信,並透過供應商 API 驗證送達狀態與退訂機制。接著,它會建立受眾清單、執行試發送(空跑),並透過 Resend 的廣播或逐次發送功能進行正式發送,同時嚴格遵守退訂名單(opt-out list)並監控配額上限。發送後,它會將電子郵件內容轉寫成適合 X(Twitter)、LinkedIn 和 Discord/Slack 等社群平台的貼文,並歸檔整期內容。此技能支援兩種模式:**自主模式**為預設模式,在資金相關事項外的所有步驟皆自動執行;**審查模式**則會在草稿、測試和正式發送等關鍵階段請求使用者核准。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mariagorskikh/product-changelog/tree/HEAD

Installed? Explore more 寫作與編輯 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

產品變更日誌

一個定期發送的電子郵件,用於告知用戶產品有哪些變更。它以人性化的口吻撰寫,安全地發送,然後再被重複用於社群貼文。對於每一期內容,電子郵件是唯一的權威來源;所有其他管道都是從它摘錄而成。

此技能的運作方式

  • 只問一次,且問在前面。 在第一次執行時(或當設定缺失、必要值為空白時),以一個簡短的批次一次性詢問設定問題,寫入 config.yaml,然後繼續執行,不再提問。
  • 然後自動完成所有後續步驟。 在 autonomy.mode: autonomous(預設值)模式下,你會自動挑選項目、起草、檢查、自我審查、截圖、測試發送、讀取測試結果、建立受眾、試發送、發送給所有人、驗證、拉取退訂名單、撰寫並發布社群貼文,以及歸檔。中間不需要任何核准步驟。每個對外的動作都會先通過一個自我審查閘門。
  • 只有花錢的事才需要核准。 任何需要花費金錢的動作,都必須在對話中獲得使用者明確的「好」才能執行,這在所有模式下都適用:例如發送量會超過供應商方案內含配額 (provider.monthly_quota)、升級供應商方案、購買網域、付費工具或授權(例如付費的 Remotion 公司授權)。除此之外,其他任何動作都不需要使用者說「好」。
  • 強制停止不是核准。 它只是中止這一個動作。繼續完成其他安全的任務,然後回報。請參閱強制停止。
  • 最後回報。 提供一份摘要:包含已發送的主旨和完整內文、各項統計數字(佇列中、已發送、失敗、排除、已退訂)、送達樣本、測試回讀結果、每則貼文及其連結,以及任何被跳過的項目及其原因。
  • review 模式 會保留舊有的逐動作核准閘門。請參閱審查模式。

每個腳本預設都是試發送。真正的發送需要明確加上參數(--send、--yes-send-to-everyone、--yes-send-broadcast)。在自主模式下,由你自行加上這些參數,並且必須在對應的自我審查閘門通過之後。切勿使用腳本之外的方式臨時發送郵件,因為只有這些腳本會強制檢查退訂名單。

步驟 0:載入設定

  1. 在目前專案的根目錄下尋找 config.yaml,然後在這個技能所屬的資料夾中尋找(或使用 $CHANGELOG_CONFIG 環境變數指定的路徑)。
  2. 如果找不到,將 config.example.yaml 複製到專案根目錄下的 config.yaml,並在一則訊息中詢問以下事項:
    • 產品名稱、網站、儀表板和文件網址
    • 寄件者名稱、職稱、寄件地址、回覆地址
    • 測試收件者(姓名和電子郵件地址)
    • 供應商:Resend 的受眾 ID、儲存 API 金鑰的環境變數名稱,以及方案的每月包含郵件數量(如果他們知道的話)(provider.monthly_quota,選擇性)
    • 退訂模式(broadcast 或 own_endpoint)
    • 圖片託管:截圖的存放位置及其公開的基礎網址
    • 選擇性項目:發送頻率、品牌連結顏色,以及每個社群管道的發布方式(social.post_via) 請不要猜測任何資訊。將答案寫入 config.yaml,然後繼續。
  3. 如果任何值仍設定為大寫的佔位符或類似 yourproduct.example 的地址,則視為遺失。
  4. 讀取 autonomy.mode(預設為 autonomous)、voice.notes 和 voice.banned_phrases。語音設定會覆蓋參考文件中的預設值。
  5. 機密資訊絕不能放在設定檔或對話中。API 金鑰和退訂簽章密碼必須儲存在環境變數中。

之後的期數則無需再詢問。唯一一個選擇性問題是:「這次有沒有透過 Git 以外的方式上線的變更(例如定價、合作關係、文件)?」如果使用者不在,請跳過這個問題,直接從 Git 和發布說明中取得資料。

步驟 1:挑選要納入的項目

首先閱讀 references/voice-and-format.md。

  • 在 paths.issues_dir 資料夾中尋找上一期的目錄(目錄命名格式為 NNN-YYYY-MM-DD-slug)。最新的一期將作為下一期的範本。
  • 從上一期日期之後收集可能的候選項目:git log --since=<date> --no-merges --oneline、已合併的拉取請求、發布說明,以及使用者提到的任何內容。
  • 只保留使用者可見的變更。3 到 5 個項目,並根據對讀者的實用性進行排序。以最有用的變更開頭,也就是最多讀者今天就能使用的變更。
  • 核對每一項宣稱,確認與實際產品和網站一致。絕對不能憑空創造功能、數字或日期。如果某項宣稱無法驗證,就刪除該項目。
  • 將列表和順序寫入該期目錄下的 NOTES.md 檔案,然後繼續。

步驟 2:起草電子郵件

建立路徑 paths.issues_dir/NNN-YYYY-MM-DD-slug/ 並寫入以下檔案:

  • subject.txt:以利益為導向且產品優先(「您現在可以將報表匯出到 Sheets」)。絕對不能使用「Changelog #N」。
  • email.html:從 templates/email.html(或上一期)複製,並根據設定和內容填入每一個 [[...]] 標記。
  • email.txt:與 HTML 版本相同的文字內容,但使用純文字格式,並直接顯示網址。

保留 {{NAME}} 和 {{UNSUB_URL}} 作為文字佔位符;發送腳本會在發送時針對每位收件者填入實際資料。

核心規則(詳細內容請參考文件):

  • Hi {{NAME}}, 開頭,接著是設定檔中的一行開場白,然後直接進入最重要的項目。
  • 每個項目:先說明變更了什麼,然後說明為什麼重要,使用流暢的句子。不要使用標籤式條列。
  • 使用簡短的句子、平實的詞彙,用「您現在可以」取代「我們打造了」。
  • 每個段落最多只能有一個粗體強調。
  • 每個項目最多一張截圖;最重要的項目一定會有一張,而且圖片要連結到該功能。
  • 風格簡潔的 HTML:600px 寬的容器、系統字型、內嵌樣式,沒有按鈕或橫幅。
  • 不能使用「興奮地宣布」以及其他禁用詞彙清單中的詞句。如果 voice.no_dashes 設定為開啟,則不能使用長破折號或短破折號。
  • 可選的輕鬆附註(「BTW, ...」)。
  • 使用設定檔中的署名。退訂提示行為最後一行,字型要小且顏色柔和。

步驟 3:截圖

遵循 references/screenshots.md 中的步驟:在演示帳號上設定真實狀態(不能是客戶資料),使用 Playwright 以 2 倍解析度進行截圖,裁剪到面板範圍,將檔案命名為 <issue>-<slug>.png,上傳到 paths.image_base_url 路徑,並在進行任何發送前,確認每個網址都能回傳 200 狀態碼。

步驟 4:檢查與自我審查(閘門 1:內容)

python3 scripts/lint_email.py ISSUE_DIR --check-links

修正每個錯誤,然後逐一核對此檢查清單。修正並重新執行,直到每個項目都通過。

  • lint_email.py --check-links 以狀態碼 0 結束。
  • 以一個忙碌的客戶的角度從頭到尾閱讀:最有用的變更能在 5 秒內清楚呈現。
  • 每個項目都是使用者今天就能看到或使用的功能。
  • 每項宣稱、數字和連結都與實際產品和網站相符。
  • 內容讀起來不像新聞稿;聽起來像是寄件者在說話。
  • 主旨不超過 60 個字元、以利益為導向,不能是「Changelog #N」。
  • 每張圖片都有替代文字,且其託管網址回傳 200 狀態碼(或在步驟 7 之前會準備好)。

步驟 5:測試發送與回讀(閘門 2:送達的副本)

python3 scripts/send_test.py ISSUE_DIR --send      # 只發送給 test_recipients,加上 [TEST] 前綴
python3 scripts/send_test.py ISSUE_DIR --readback  # 一分鐘後

測試副本只發送給 test_recipients,如果圖片尚未部署,則會內嵌圖片。--readback 會從供應商 API 拉取每封送達的郵件,檢查最後的事件、主旨、渲染後的問候語和退訂提示行,並確認沒有遺漏任何佔位符。同時,你自己也要親手閱讀一次回傳的 HTML 內容。如果有任何問題,修正後重新檢查並重新測試。

在 own_endpoint 模式下,點擊測試副本中的退訂連結,確認退訂已被記錄,然後重新訂閱測試用的電子郵件地址。

步驟 6:建立受眾

詳細內容請參閱 references/sending.md。

  • 根據使用者的資料庫全新建立 ISSUE_DIR/audience.jsonl(每行包含 {"email", "name"})。不要重複使用舊的清單。
  • 根據退訂資料表建立 ISSUE_DIR/unsubs.txt。在廣播模式下,首先執行 python3 scripts/broadcast_unsubs.py --out <issues_dir>/unsubs.txt 並將結果複製進去。
  • 設定檔 exclude 中的創辦人、測試帳號和演示帳號,會收到測試副本而非正式發送。

步驟 7:發送給所有人(閘門 3:受眾)

根據 unsubscribe.mode 選擇發送路徑。首先執行試發送並檢查統計數字。

廣播模式(供應商主機處理退訂):

python3 scripts/broadcast_sync.py ISSUE_DIR/audience.jsonl            # 計畫
python3 scripts/broadcast_sync.py ISSUE_DIR/audience.jsonl --apply    # 新增或更新聯絡人
python3 scripts/broadcast_create.py ISSUE_DIR --create                # 僅建立草稿
python3 scripts/broadcast_create.py --send BROADCAST_ID               # 顯示收件者數量,並拒絕
python3 scripts/broadcast_create.py --send BROADCAST_ID --yes-send-broadcast

自有端點模式(使用簽名連結導向你自己的頁面):

python3 scripts/blast.py ISSUE_DIR                                    # 試發送並顯示統計
python3 scripts/blast.py ISSUE_DIR --send --yes-send-to-everyone

受眾檢查清單,在傳遞發送參數前必須全部通過:

  • 閘門 1 和 2 已在此精確副本上通過(自回讀後無任何變動)。
  • 退訂名單在此次執行中被拉取或建立,且如果產品曾經有過退訂,該名單不為空。
  • 試發送的統計數字合理:佇列中的數量接近使用者總數減去退訂數及排除數;與上一期的 NOTES.md 相比沒有異常的跳躍。
  • 廣播模式:broadcast_sync.py 未回報任何意外的過時聯絡人。
  • 每張託管圖片的網址都回傳 200 狀態碼。
  • 配額:如果已設定 provider.monthly_quota,則傳入 --sent-this-month N(這個月所有期數 NOTES.md 中記錄的已發送數量總和,加上如果已知的其他使用同方案的郵件數量)。如果腳本顯示發送將超出配額,請停止並詢問使用者;只有在使用者明確說「好」之後,才能傳遞 --yes-over-quota 參數。

逐次發送是可恢復的:如果中途停止,重新執行相同的指令,它會跳過已經發送過的地址。

步驟 8:驗證與同步

  • 逐次發送:python3 scripts/verify_delivery.py ISSUE_DIR --sample 40。廣播:透過供應商 API 或儀表板執行 GET /broadcasts/{id}。
  • 一天後拉取退訂資料(broadcast_unsubs.py)。如果使用者將退訂資訊儲存在自己的資料庫中,且你有寫入權限,請匯入;否則請在報告中說明。

步驟 9:社群貼文

根據最終版的電子郵件內容,並遵循 references/social.md 撰寫:

  • X 貼文串:以 social.hook_prefix 開頭的鉤子貼文,點名所有項目,無連結,使用最強而有力的截圖。然後每個項目一篇編號貼文,包含其連結和截圖。再加上一則創辦人的一行個人引言貼文。
  • LinkedIn:一篇貼文,第一行是鉤子,每個項目一個簡短段落,純文字,附上圖片庫。
  • 社群(Discord 或 Slack):開場一行,每個項目一行並附上純文字連結,貼文串上線後再補上貼文串連結。

最多 4 到 5 個項目,無政策通知,宣稱需與實際網站相符。對產生的 social.md 執行相同的禁用詞彙和破折號檢查(lint_email.py 會讀取它)。然後,針對 social.post_via 中有設定工具的每個頻道,自行發布貼文並記錄貼文網址。對於沒有設定工具的頻道,將最終的文字和圖片交給使用者。創辦人的引言貼文來自個人帳號,因此除非該帳號已配置工具,否則請交給使用者處理。

步驟 10:影片(選擇性,僅在要求時執行)

如果使用者要求,請遵循 references/video.md:製作一個 15 到 25 秒的動畫,使用該期截圖,沒有標題投影片,每個項目有一個大標題,截圖為主,結尾加上產品網址。對於超過一定規模的團隊,Remotion 需要付費的公司授權;這是一個需要向使用者確認花費的問題。

步驟 11:歸檔與回報

在該期資料夾中保留以下檔案:subject.txt、email.html、email.txt、截圖、social.md、test_results.jsonl,以及一個內容包含項目列表、發送日期、使用路徑、受眾規模、成功和失敗數量、廣播 ID、貼文網址,以及一天後的退訂人數的 NOTES.md。如果產品有一個公開的網頁版變更日誌頁面(product.changelog_page)且其原始碼就在此儲存庫中,也請將該期內容新增進去。當使用者修正語氣或格式時,將學到的教訓加入設定檔中的 voice.notes,以便下一期能從中開始。然後,發送如開頭所述的一份摘要。

強制停止

停止該動作,完成所有其他安全的任務,然後回報是什麼被停止了以及原因。切勿繞過強制停止。

  • 你無法修正的 lint 錯誤。
  • 你無法修正的損壞連結或圖片(部署或修正後仍無法回傳 200 狀態碼)。
  • 測試回讀失敗且你無法找出原因。
  • 退訂過濾失敗:無法拉取或建立退訂名單、受眾查詢發生錯誤,或腳本因為 unsubs.txt 的問題而拒絕執行。切勿在沒有退訂名單的情況下發送郵件。
  • 發送過程中,供應商錯誤次數超過閾值(blast.py 在達到 provider.max_failures 或 provider.max_failure_rate 時會以狀態碼 2 退出)。回報錯誤;一旦問題解決,blast 是可恢復的。
  • 發送將超出配額、方案升級或其他任何需要花費的情況:詢問使用者(金錢規則)。
  • 發布工具出現登入、雙因子驗證或重新授權提示、CAPTCHA、平台警告或速率限制通知、付款或帳單表單。
  • 任何可能違反退訂規定或反垃圾郵件法規的行為(缺少退訂提示行、重新訂閱已退訂的人)。
  • 你無法驗證的宣稱。將其刪除,不要猜測。

審查模式

當 autonomy.mode: review 時,三個閘門也需要使用者的同意:

  1. 草稿閘門。 在對話中顯示主旨、電子郵件內容和項目列表。在使用者核准內容之前,不會發送任何東西。
  2. 測試閘門。 僅發送給 test_recipients。使用者在真實的收件匣中閱讀後,表示可以繼續或提出修正。
  3. 發送閘門。 顯示試發送的統計數字(佇列中、已排除、已退訂)。只有在使用者在對話中對該次特定發送表示「好」時,才會發送給所有人。對前面步驟的同意,不代表同意這一步。

社群貼文在發布前會先顯示,項目列表則在撰寫前提出。在對應的閘門通過之前,切勿傳遞發送參數。

回答「有多少訂閱者?」

訂閱者 = 使用者總數 - 退訂人數。從使用者的退訂資料表或 unsubs.txt 計算退訂人數(在廣播模式下,先執行 broadcast_unsubs.py)。也提供最新一期的退訂率。

檔案

  • config.example.yaml:包含每個公司特有的值,以及 autonomy、provider.monthly_quota 和 social.post_via。
  • templates/email.html、templates/email.txt:初始版面配置。
  • scripts/:lint_email.py、send_test.py(包含 --readback)、broadcast_sync.py、broadcast_create.py、broadcast_unsubs.py、blast.py 和 verify_delivery.py。
  • references/:voice-and-format.md、screenshots.md、sending.md、social.md 和 video.md。

相關技能