explainroo
explainroo is a free, open source tool that lets your AI agent make explainer videos with a voice. It runs on your own computer and needs no API key.
零維運、全免費的個人科技雷達,每日將 GitHub 熱門專案與科技新聞精選推送到 Discord。Zero-ops, free daily tech radar: GitHub trending + curated AI/dev news to Discord.
Translation pending
MediaGitHub @sylvia-HOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗排程型、純自用、全免費、零維運的每日技術晨報。每天清晨(排程台北 04:07,實際送達約 06:00~07:00), 自動掃描近一週最受關注、新崛起的 GitHub repo,並從 24 個技術新聞來源精選當日最值得開發者關注的消息, 翻成繁體中文推播到 Discord;同時發佈公開的 GitHub Pages 儀表板 與 Atom feed,供隨時查閱與訂閱閱讀器追蹤。
整條 pipeline 只用 GitHub Actions + Discord Webhook + Gemini 免費層 + GitHub API,沒有伺服器、 沒有資料庫、沒有付費方案;LLM 每日只呼叫一次,去重與排序全程零 LLM。全程以 GitHub Spec Kit(Spec-Driven Development)開發,八個 Feature 依序完成,每個非顯而易見的決策都留有 spec/clarify 紀錄(見文末開發歷程)。
| 項目 | 數字 |
|---|---|
| 新聞來源 | 32 個設定項、24 個啟用(AI 11/DevOps 6/前後端 5/跨領域 2) |
| 每日新聞 | 至多 15 則,AI 為主、非 AI 預設 ≤5(動態放寬);未滿時以未歸類的資安/一般軟體工程新聞補位 |
| LLM 呼叫 | 新聞策展每日 1 次(gemini-3.8-flash 帶 thinking,備援 gemini-3.5-flash-lite);repo 簡介一生 1 次並快取、榜單日多 1 次一句話 TL;DR(皆 gemini-3.5-flash-lite) |
| 榜單 | 每領域追蹤 top 15,推播綜合 top 10,每 7 天只推變化 |
| 榜單資料 | GitHub Trending weekly 6 個頁面 + Search API 2 條查詢,不自存星星歷史 |
| 排程 | 雙離峰 cron(台北 04:07 主班、04:37 補班)+ 時間戳 guard;手動 dry_run 乾跑、replay_date 降級日補發,皆不寫狀態 |
| 常駐服務/資料庫 | 0 |
| 月費 | $0 |
| 單元測試 | 810 個、71 個測試套件 |
三條輸出流:
晨報是一則橘色 embed,標題帶台北日期,內容逐則編號(以下取自實際推播):
📡 Tech Radar 晨報 · 2026-09-02
1. 程式語言 Mojo 正式宣佈開源
專為人工智慧與高效能運算設計的程式語言 Mojo 正式宣佈開源。這項轉變對開發者而言意義重大,
意味著社群可以更深入參與該語言的底層架構、貢獻程式碼……
2. Google Gemini 推出全新代理式影片理解功能
Google 替 Gemini 模型推出具備代理式(agentic)能力的影片理解功能……
3. Cloudflare 透過 Zstandard 與 Pingora 探索快取儲存空間最佳化
Cloudflare 分享了他們如何在快取系統中導入 Zstandard 壓縮技術與 Pingora 架構……
榜單日先來一張封面卡(藍色),再每個新進/竄升 repo 一張卡(AI 綠色、前後端黃色)。封面文字取自 實際推播,卡片內容為示意:
📊 榜單變化 · 2026-08-31
本次榜單變化
本次技術雷達榜單由 tt-a1i/archify 奪得 #1,共有 9 個新進項目(AI 佔 7 個、前後端佔 2 個)
以及 1 個下降項目。
🔻 下降
makeplane/plane #8 → #10
🆕 schollz/croc ← 標題可點,連到 repo
croc 是一款基於 Go 語言的高效能檔案傳輸工具,解決了跨設備傳輸檔案時……(≤250 字)
本週增星 ⭐ +1.1k 語言 `Go` 領域 前後端
🔺 owner/repo
……
本週增星 ⭐ +8.6k 語言 `Python` 名次 #9 → #3
星數、連結、名次、日期全部由程式填入,LLM 只寫敘事文字。任何來源失敗、發佈失敗都會另發紅色 告警到獨立的告警頻道,不會污染晨報與榜單頻道。
一支跑完即退的 NestJS CLI job(NestFactory.createApplicationContext(),保留 DI、不啟 HTTP
server),由 radar.yml 內兩個 job 依序執行:
GitHub Actions 雙離峰 cron(UTC 20:07 / 20:37 = 台北 04:07 / 04:37)
│
├─ radar job
│ ├─ 從獨立 state 分支載入 state/board.json(唯一權威狀態)
│ │
│ ├─ 榜單段(BoardSegmentService)—— 每 7 天
│ │ ├─ lastBoardPushAt 距今 < 162h → 整段跳過,不耗任何 GitHub 配額
│ │ ├─ GitHub Trending weekly 6 頁 + Search API 2 條查詢,各自容錯隔離
│ │ ├─ 零 LLM 兩領域歸類(AI/前後端;topics 優先、未命中即排除)
│ │ ├─ weeklyStarsEstimate 統一尺 → 每領域 top 15 → 綜合 top 10(每領域保底 2 席)
│ │ ├─ 與上次快照 diff → 新進/竄升/下降(掉榜靜默)
│ │ ├─ 新進/竄升生成 250 字簡介(快取命中不打 LLM)+ 一句話 TL;DR
│ │ ├─ 推播榜單頻道
│ │ └─ 推播成功才寫回狀態(原子寫入)
│ │
│ ├─ 晨報段(NewsSegmentService)—— 每日
│ │ ├─ lastNewsPushAt 距今 < 18h → 整段跳過
│ │ ├─ 24 個來源抓取(RSS/Atom、HN Algolia、Reddit weekly、GitHub Releases),各自容錯
│ │ ├─ 零 LLM 去重:URL 正規化合併 → 標題 Jaccard ≥0.6 補漏
│ │ ├─ 跨領域來源關鍵字歸類(無命中但 ≥300 分者以「未歸類」保留)
│ │ ├─ 剔除 45 天內已推播的 URL;剔除與近 14 天已推標題 Jaccard ≥0.6 者
│ │ ├─ Stage A 漏斗:分數門檻 → 30 天新鮮度 → 加權 → 三層決勝排序 → 未歸類名額 20 → 收斂至 80 則
│ │ ├─ Stage B 策展:唯一一次 Gemini 呼叫(Flash 帶 thinking,503 退 Lite)
│ │ │ → officialPicks / communityPicks / backfillPicks
│ │ ├─ 硬驗證:幻覺剔除 → 單一來源 ≤2 → 非 AI 動態上限 → 總數 ≤15 → 補位補到 15 → 字數收斂
│ │ ├─ 推播新聞頻道(每則訊息 ≤10 張 embed 且 ≤6,000 字元)
│ │ └─ 推播成功才寫回狀態(原子寫入)
│ │
│ ├─ 手動 workflow_dispatch 勾 dry_run → 只跑晨報段乾跑:跳過 guard、結果推告警頻道、不寫狀態
│ │
│ └─ 狀態有實際變更 → radar-bot commit 到 state 分支(no-diff 早退;乾跑跳過)
│
└─ publish job(needs: radar;乾跑時跳過)
├─ 查 repo 可見性:private → 靜默跳過;查詢失敗 → 告警後跳過
├─ 純函式渲染 index.html + feed.xml(零 LLM,模組層即不引入 LLM)
└─ 上傳並部署到 GitHub Pages
兩段各自吞掉已知失敗模式(guard 跳過、空內容、推播失敗皆 best-effort 告警、不擲錯);頂層 try/catch 只是未預期例外的安全網,任一段炸掉不會中止另一段,已落檔的狀態也不回滾。
來源是唯一設定檔 src/config/news-sources.ts。增刪修來源只改這個檔案,不動任何抓取/漏斗
程式碼;載入時以 zod 驗證欄位與 id 唯一性,任何違規直接擲錯。每個來源只有六個必要欄位:
id、type、url、domain、tier、enabled,加一個選用的 freshnessWindowDays(只能把預設 30 天
的新鮮度視窗縮短,目前僅 kubernetes-blog 設 10 天);沒有逐來源的權重或門檻,所有數字都由 tier 決定。
| Tier | 定位 | 分數門檻 | 權重 | 說明 |
|---|---|---|---|---|
| 1 | 常開高訊號聚合 | 100 | ×1.0 | 有社群分數者(HN)低於門檻即淘汰 |
| 2 | 官方一手來源 | 無 | ×1.0 | 沒有社群分數,一律以基準分 100 入池,天然視為強訊號 |
| 3 | 選配實驗 | 150 | ×0.5 | 更高門檻、一半權重,可隨時停用 |
Tier 1:常開高訊號
| 來源 id | 類型 | 領域 | 說明 |
|---|---|---|---|
hn | HN Algolia API | 跨領域 | Hacker News 近 4 天 story(2026-09-12 由 7 天改),唯一帶社群分數的來源 |
lobsters-ai | RSS | AI | Lobste.rs ai tag |
lobsters-devops | RSS | DevOps | Lobste.rs devops tag |
lobsters-programming | RSS | 跨領域 | Lobste.rs programming tag |
reddit-localllama | Reddit weekly RSS | AI | r/LocalLLaMA 週熱門 |
simonwillison | RSS | AI | Simon Willison 純文章 feed(atom/entries/,每週約 2 則;2026-09-12 由 atom/everything/ 改來,原 feed 的 blogmark 連結指向自站而非原文,URL 去重接不上會與原文兩推) |
Tier 2:官方一手來源
| 來源 id | 類型 | 領域 | 狀態 | 說明 |
|---|---|---|---|---|
openai-blog | RSS | AI | 啟用 | OpenAI 官方 news |
deepmind-blog | RSS | AI | 啟用 | DeepMind 官方 basic feed |
github-next | RSS | AI | 啟用 | GitHub Next 官方實驗性功能部落格 |
github-changelog-copilot | RSS | AI | 啟用 | GitHub 官方 Changelog 的 Copilot 標籤,每週約 6 篇,直接命中新工具/能力更新(2026-09-12 新增) |
github-blog-ai-ml | RSS | AI | 啟用 | GitHub Blog「AI & ML」分類,30 天內約 10 篇工程實作文(Copilot runtime、多模型協作、AI coding 降本),與 changelog 互補(2026-09-21 新增) |
huggingface-blog | RSS | AI | 啟用 | Hugging Face 官方 blog,30 天內約 15 篇 fine-tuning/TRL/agent 實作文;08-04 移除,09-14 以停用項列回,09-21 重新啟用(AI 入選平均 5.0 則、一手技術深度供給仍薄) |
raschka-ahead-of-ai | RSS | AI | 啟用 | Sebastian Raschka「Ahead of AI」,約 2 篇/月,架構解析與實作教學(2026-09-14 新增) |
interconnects | RSS | AI | 停用 | Nathan Lambert「Interconnects」,約 3 篇/週,開放模型與 RL 分析(2026-09-14 新增;09-21 停用:09-15~09-21 每日 3~4 席進候選池、7 天 0 入選) |
ollama-blog | RSS | AI | 啟用 | Ollama 官方 blog,約 2 篇/月,本地模型相關發布(2026-09-14 新增) |
anthropic-news | RSS | AI | 停用 | 無公認官方 RSS 端點,不以第三方中轉站替代(2026-09-14 覆測仍 404) |
gh-nodejs | GitHub Releases | 前後端 | 啟用 | Node.js 官方發佈 |
gh-cpython | GitHub Releases | 前後端 | 啟用 | CPython 官方發佈 |
gh-typescript | GitHub Releases | 前後端 | 啟用 | TypeScript 官方發佈 |
vue-blog | RSS | 前後端 | 停用 | feed 最新一篇為 741 天前(2026-09-12 實測),比照 web-dev 停用觀察 |
web-dev |
Tier 3:選配實驗
| 來源 id | 類型 | 領域 | 狀態 | 說明 |
|---|---|---|---|---|
gh-vue | GitHub Releases | 前後端 | 啟用 | Vue core 發佈 |
gh-react | GitHub Releases | 前後端 | 啟用 | React 發佈 |
thenewstack | RSS | DevOps | 啟用 | The New Stack |
cloudflare-blog | RSS | DevOps | 啟用 | Cloudflare 官方 blog;2026-09-12 由 Tier 2 降級——117 則推播中佔 24 則(20%),且含認證、流量報告等公關文。Tier 3 無分數候選加權 50、排在所有 Tier 1/2 之後,候選池滿時進不了 LLM,近似停用 |
reddit-devops | Reddit weekly RSS | DevOps | 停用 | GitHub Actions runner IP 遭 Reddit 持續 403/429 |
reddit-node | Reddit weekly RSS | 前後端 | 停用 | 同上 |
reddit-python | Reddit weekly RSS | 前後端 | 停用 | 同上 |
reddit-reactjs | Reddit weekly RSS | 前後端 | 停用 | 同上 |
enabled: false 加日期註解處理,設定檔本身就是決策紀錄
(為何停、何時覆測、覆測結果)。vue-blog 停用後前後端啟用來源全為 GitHub Releases,文章類供給由
hn/lobsters-programming 的關鍵字歸類與「未歸類」通道承擔;vercel atom 為候補,尚未動手。llama.cpp
releases)、會被 release-filter 濾光(codex/gemini-cli/claude-code 全為 pre-release 或 patch),就是
二手/公關內容(Latent Space、blog.google、Grafana、HashiCorp)。其後只在有具體缺口時補:09-12
GitHub Changelog(Copilot)與 Kubernetes blog,09-14 三個 AI 技術深度來源(其中 interconnects 一週 0
入選後停用),09-21 github-blog-ai-ml 與重啟 huggingface-blog。Anthropic 五個候選端點皆 404,維持不收。id 的紅色告警,不會無聲略過;但計數取過濾前
的筆數,所以 GitHub Releases 整批被版本噪音過濾掉不會誤報。一則新聞從「被抓到」到「出現在推播裡」依序經過九關;前八關除了第六關之外全部是純函式、零 LLM。
src/news/fetchers/)依 type 分派四種 fetcher,同型來源只需加設定:
| 類型 | 做法 | 分數 |
|---|---|---|
hn-algolia | 附 created_at_i > 4 天前 與 hitsPerPage=100,客戶端再核對一次 4 天口徑(2026-09-12 由 7 天改:pipeline 每日執行,7 天視窗使同一批未入選候選被 LLM 重複評估最多 7 次,且 HN 曾佔候選池 24/50 席;HN 熱度多在 48 小時內定型);丟棄標題尾綴「(YYYY)」(後可接 [pdf]/[video] 標籤)且該年份 12/31 距今超過 30 天者(OLD_YEAR_GRACE_DAYS,與新鮮度視窗同一把尺,避免 1 月誤殺上年度年度報告;HN 重貼舊文慣例,HN 豁免新鮮度視窗故靠此把關);Ask HN 無外連時以 HN item 頁為去重鍵 | points |
rss | rss-parser,缺標題或連結即丟棄 | 無 |
reddit-weekly | 同 RSS,Reddit RSS 不帶 upvote | 無 |
github-releases | 同 RSS,再經版本噪音過濾 | 無 |
版本噪音過濾(src/news/release-filter.ts):丟棄 pre-release(-alpha/-beta/-rc/-canary
等,以及 CPython 的 PEP 440 寫法如 3.15.0b4)與純 patch release;標題或內文含 security、
CVE-、advisory 者即使是 patch 也保留;版本號無法解析者保守保留。
抓取禮貌:自訂 User-Agent、429/5xx/網路錯誤指數退避+jitter(最多 3 次、上限 8 秒)、尊重
Retry-After;其他 4xx 立即放棄。每個來源獨立 try/catch,失敗只影響自己。
社群平台連結過濾(src/news/social-hosts.ts,2026-09-12 新增):抓取完成、進入 URL 去重之前,
目標 URL 的 host 為 twitter.com/x.com/bsky.app/threads.net、常見 Mastodon 實例或符合
mastodon.*/mstdn.* pattern 者直接丟棄(log [漏斗 A] 社群平台連結過濾後)。貼文沒有摘要、
LLM 只能憑標題判斷,且多為個人動態而非技術內容(09-12 候選池 3 則)。清單是獨立資料檔,增刪
host 只改該檔、不動過濾邏輯;短網址(t.co 等)不解址故不列。代價:僅在 X/Mastodon 發布的
一手公告(模型上線、API 變更、事故說明),若 HN 投稿指向該貼文是唯一入口,會在漏斗最前端整則
消失——已知且接受,觀察兩週。過濾套用於全部來源的候選、不限 HN;日後若在 news-sources.ts
新增以這些 host 為目標連結的來源會被無聲全滅(症狀:來源解析 N 則、社群過濾後大量減少),屆時
於 social-hosts.ts 加 allowlist 或把過濾限定於 hn。
src/news/url-normalize.ts、dedup.ts)同一件事常被多個來源報導,去重主力是零 LLM 的 target-URL 正規化:
www.、去 #fragment、去尾斜線(根路徑除外)。utm_*、mc_* 前綴,以及 ref、fbclid、gclid、igshid、ncid、spm、
cmpid 等;剩餘 query 依 key、value 排序,讓參數順序不同的連結合併。t.co/bit.ly 重複交給第六關的 LLM 補。同 URL 只留分數最高者為代表(無分數視為 −∞、同分取 sourceId 字典序),sources[] 聯集累積。
src/news/title-similarity.ts)進入這一關前先套一次新鮮度視窗(2026-09-12 起):URL 合併後代表項無分數(RSS/Releases)且
publishedAt 缺失或超過 30 天即丟,HN 有分數者豁免。原本這個視窗只在第六關末端套用,標題比對時
封存舊文仍在場(openai-blog 的 feed 含整站 1192 篇),會把其他來源的新文章吞掉、代表項落在舊文後
再被視窗整則丟掉;提前後進入這一關的候選由約 1690 則降到約 300 則,第六關的同一檢查保留為結構性
保險。放在第二關之後是因為 URL 精確合併不可能誤吞,且低分 HN 投稿與同 URL 官方舊文合併後的交叉
驗證豁免要保留。每個來源另印「解析 N 則 → 過濾後 M 則」的觀測 log(含 0 筆者)。
不同連結但其實是同一件事(官方 blog 與 HN 討論串),以標題 Jaccard 相似度補漏:小寫、以非英數
切詞、去約 50 個英文停用詞,|交集| / |聯集| ≥ 0.6 且發表日期相差 ≤ 14 天才合併(2026-09-12
新增:Jaccard 把版本號當普通 token,「ChatGPT Images 2.0」與「2.5」曾被判為同一則;同一件事的多篇報導
不會相差數月,候選缺日期者維持可合併)。日期比的是群組的最早/最晚範圍而非當前代表項,避免無日期的
高分 HN 項抹掉群組日期,或三則相似標題鏈式漂移出 28 天。這一關全程不呼叫 LLM。
src/news/news-classify.ts)非跨領域來源沿用設定的 domain;hn、lobsters-programming 兩個跨領域來源以詞界正規表達式
比對標題+摘要,優先序 AI > DevOps > 前後端(關鍵字 25/17/24 個)。
關鍵字只負責正向命中,不再有否決權(2026-09-25)。無命中時依序:已與非跨領域來源同 URL 合併者沿用 該來源的領域;有真實社群分數且 ≥300 者以「未歸類」身分保留、交第 7 關的 LLM 判定領域與重要性(每日 名額 20,第 6 關把關);其餘才丟。起因是 2026-09-15 Jev 發布:HN 1979 分的官方公告在四天視窗內每天被抓到、 每天被丟,晨報全程無感;重播 09-16~09-25 的 HN top 100,關鍵字每天丟 72~85%,≥300 分被丟的有 38~53 則, 含 MiMo v2.6、OpenJev、Grok 4.7 等新模型發布。新公司、新模型的名字本來就不在關鍵字表裡,而「我不知道、 但應該關注」正是晨報要捕捉的東西。
src/news/seen-news.ts)比對 seenNews 已推清單(保留 45 天,讀寫兩端都修剪),比對鍵同樣是正規化後的 URL,所以換了追蹤
參數再出現仍算已推。這一關刻意排在收斂之前,避免已推項目佔用收斂名額。
保留天數原為 7 天,2026-09-02 改為 45 天:保留期必須大於等於一則新聞最久還能當候選的時間,而無分數
來源的新鮮度視窗是 30 天,官方 feed 又常把同一篇掛上數週。原本每隔 8 天同一則就會再推一次,實測
310 則推播中有 46 則是重複;單元測試現在斷言保留期 ≥ 新鮮度視窗,兩個常數不會再各自漂移。代價是
seenNews 由約 50 筆膨脹到兩三百筆(數十 KB),但每日 diff 量不變;feed 的「同 id 取新棄舊」也因此
從必要機制退居防呆。
跨日標題去重(2026-10-06):URL 比對接不上「同一事件換連結再出現」——1.3.1 上線九天內荷蘭 NixOS、
Gemini 4 Argon、Sonnet 5.5 各重推兩次。現在推播寫回 seenNews 時連同候選原始標題落檔(非 LLM 改寫的
繁中標題),漏斗對近 14 天帶標題的已推紀錄做 Jaccard ≥ 0.6 比對,命中即排除並在 log 列出配對。14 天與當日
池內標題合併的視窗同一把尺;門檻保守,只接「同一篇換連結」或措辭高度重疊者——上述三組實例的 Jaccard 其實
只有 0.23 到 0.43,屬「同主題、不同報導」,是否重推是語意判斷,不在零 LLM 層誤殺;候補方案是把近期已推標題
投影進策展 prompt 交 LLM 判斷。
src/news/funnel.ts)| 步驟 | 規則 |
|---|---|
| 分數門檻 | 只對有分數者生效:Tier 1 ≥100、Tier 3 ≥150;Tier 2 無門檻;被 ≥2 來源交叉驗證者豁免(避免官方文章被低分 HN 投稿合併後連帶出局) |
| 新鮮度 | 無分數者需在 30 天內發表(publishedAt 為原文真實日期),避免封存舊文被討論區重新提及混入;HN 因 publishedAt 是投稿時間而豁免。來源可在 news-sources.ts 以 freshnessWindowDays 縮短(只能 ≤ 30,目前僅 kubernetes-blog 設 10 天),URL 合併的候選取各來源視窗最大值 |
| 加權 | base × tierWeight + 交叉驗證加權 100(sources ≥ 2)+ 榜單相關性加權 50(提到目前榜上 repo),無分數者 base = 100 |
| 排序 | 加權分數 ↓ → 跨來源輪流分配序 ↑ → normalizedUrl ↑;publishedAt 刻意不當跨來源決勝鍵,只在同來源組內決定先後 |
| 未歸類名額 | 第 4 關保留的「未歸類」候選須有分數且 ≥300,依分數只取前 20 則(2026-09-25 起;09-26 由 10 調高,避免較低分的 AI 新事物被高分的資安/趣聞擠出池) |
| 收斂 | 取前 80 則送 LLM(2026-09-25 由 60 → 70、09-26 → 80,容納未歸類名額) |
跨來源輪流分配是實測踩坑後加的:所有無分數的一手來源都是 100 分同分,單純用 URL 字母序決勝時
blog.cloudflare.com 曾佔掉 25 席中的 9 席,把好幾個官方來源整批擠出候選池。現在同分候選按來源
分組、逐輪各發 1 則、最多 3 輪,超過 3 輪的直接剔除;只要收斂名額扣掉有分數候選後 ≥ 當日活躍
來源數,每個來源至少有 1 則能進候選池。同一來源內「留哪 3 則」依發表日期由新到舊(2026-09-02 起,
先前沿用 URL 字母序,路徑帶月份縮寫的來源會讓 /Aug/ 長期壓過 /Sep/);跨來源之間仍是公平輪流,
不會重新引入「誰發得勤誰贏」的偏誤。
src/curation/)候選為 0 則時連 LLM 都不叫。有候選時只送公開欄位:ref(0 起算索引)、標題、領域、tier、分數、
來源數、是否在榜、發表天齡、摘要節錄(≤500 字)。不送 URL。呼叫帶 thinkingLevel: high
(2026-09-27 起;此前完全沒有思考 token,同一批候選 Lite 只選 6 則、開 thinking 後 12 則)。天齡是 2026-09-02 補上的:此前 LLM
分不出三週前與今天的文章,prompt 以「重要性相當時優先較新者,但天齡不改變是否重大」的軟性偏好使用它。
Prompt 要求三件事:殘餘語意去重、依「對開發者的重要性而非熱度」挑至多 15 則、每則改寫為繁中
標題(≤70 字)+內容(≤500 字,回答「發生了什麼、為何對開發者重要」)。回應固定為三個陣列
officialPicks / communityPicks / backfillPicks,每則回 ref、title、content,「未歸類」候選另須
回填 domain;backfillPicks 只收未歸類候選中的資安事件與一般軟體工程新聞(見第 8 關補位)。
未歸類候選與同題標記(2026-09-25):第 4 關保留的候選在投影裡領域欄顯示「未歸類」,prompt 給的是
正向先驗——「這正是本晨報最想捕捉的新事物,不要因為名字陌生或你不認識它就視為不重要,你的訓練資料也可能
沒有它」,只要標題暗示新模型/工具/框架/概念的發布、開源實作或重大技術討論就收錄並回填 domain;明顯與
軟體開發無關者熱度再高也不選。另有零 LLM 的同題群集(src/news/topic-cluster.ts):同一個罕見詞當日
跨 ≥2 來源出現在 ≥3 則標題裡,就在候選前加「🔥同題「X」×N(M 來源)」,prompt 明示這是「正在崛起」的正面
訊號、同題候選優先收錄最一手的一則。Jev 發布後 09-22~09-25 候選池每天有 2~5 則相關候選,LLM 一則都沒選,
因為單看一則陌生標題無從判斷輕重。
「算重大」分三類(2026-09-12 限縮):(1)【官方發布】新模型/工具/版本、breaking change、安全通報、
標準變動、重大 deprecation;(2)【技術深度內容】深入評測、實作經驗、架構或效能分析、技術爭論——
技術深度是必要條件、社群熱度只是加分訊號(無分數的一手部落格深文也算;熱門而非技術的不算);
(3)【影響開發者的外部事件】監管政策/法規變動、主要服務或 API 的當機/事故——即使無技術細節也算
重大。陣列歸屬:officialPicks=(1)+(3)、communityPicks=(2) 技術深度內容;同時命中 (2) 或排除清單
時以 (3) 為準(否則 HN 高分帶入的當機事故會落入 communityPicks 被截掉)。明列排除:募資/估值、
人事異動;訴訟/指控的進行中進展不收、已生效判決若改變開發者可用的工具/授權/API 依 (3) 收錄;
與軟體開發無關的趣聞(遊戲引擎/圖形效能技術與硬體技術評測不在此列);廠商認證/合規公告、廠商統計
或威脅報告、行銷公關文。回應只能有三個鍵,額外鍵(如 LLM 自創的 externalPicks)不擲錯、以
warn 揭露;改寫只依候選標題與摘要、不得補充來源未提供的事實(2026-09-12 起 prompt 明文要求)。
Prompt 內幾個實測後的關鍵設計,見工程亮點。
src/curation/curation-validate.ts)固定順序,只在 LLM 已選的集合內剔除或重排,永不遞補新候選:
officialPicks 固定接在 communityPicks 之前合併。ref 必須是 [0, 候選數) 內的整數,越界即丟;重複 ref 只留第一次。
url、domain、sourceCount、weightedScore 全由程式從 candidates[ref] 附回,LLM 沒有
任何機會產生連結。max(5, 15 − AI 則數):AI 不設下限也不設上限,逐一評選、合格皆收;AI 供給
不足 10 則時把未用滿的名額讓給非 AI(AI 4 則 → 非 AI 可到 11 則),只在 AI 確實不足時放寬。
超額時 DevOps 優先保留,同領域內維持重要性序。(2026-09-25 由 max(3, 10 − AI) 調整。)
「未歸類」候選以 LLM 回填的 domain 參與配額;未回填者預設 ai 並 warn。officialPicks(官方發布+影響開發者的外部事件)若已達 15 則,communityPicks
(技術深度內容)會在此被完全截掉,這正是結構性優先的體現。
補位(2026-09-26):三桶精選處理完後若未滿 15 則,才依序補入 backfillPicks——只收「未歸類」候選中的
資安事件與一般軟體工程新聞,領域記為 general、排在最後、不計入非 AI 配額。未歸類候選中的 AI 新事物走前兩
陣列,永遠先於補位;這是則數偏低時的補位,不是擴大範圍。已歸類候選若被 LLM 誤放進補位陣列,不剔除、
改回流主桶套配額(2026-09-27;首日 Node.js LTS 發布曾因此整則消失),並 warn 揭露。…,不重打 LLM。seenNews 追加正規化 URL(2026-09-12 起連同代表項 sourceId、合併後全部
sources 與 domain,供月度統計;舊條目不回填)、lastNewsPushAt 更新、publish.news 與 feed
(上限 50 筆)同步更新,Discord 與 Pages 保證是同一份資料。chunkEmbedsByBudget 同時受「≤10 張」與「合計 ≤6,000」約束,超出就
拆成下一則訊息,不靜默丟內容。降級路徑(LLM 失敗)一律排除「未歸類」候選——沒有 LLM 判斷時它們會以高分
佔滿降級晨報。gemini-3.8-flash,帶 thinking)呼叫失敗(429/503 重試耗盡、型號 404、空回應)時,先以 Lite
(gemini-3.5-flash-lite,同樣帶 thinking)用同一 prompt 單次重試(2026-09-12 起,仍屬同一次策展;空回應也換型號,
因為不同型號對同一 prompt 的截斷/安全過濾行為可能不同);Lite 也失敗、或 JSON 解析失敗時,改以 Stage A 的加權分數順序取候選,套用相同的配額與總數規則,以
content: null、degraded: true 推播(只有原文標題與連結),並發 Discord 紅色降級告警(此前降級
無告警)。不會推出未經驗證的 LLM 原文,也不會整天沒有晨報。「本週增星」一律借用 GitHub 官方數字,不自建每日星星快照、不做 day-over-day 比對:
| 來源 | 內容 | 容錯 |
|---|---|---|
| GitHub Trending weekly(主力) | 全站 + typescript、javascript、python、rust、shell 共 6 頁,since=weekly,以 cheerio 解析官方「stars this week」 | 逐頁隔離,一頁失敗只丟該頁;6 頁合計 0 筆才視為失敗並告警 |
| GitHub Search API(補位) | 每領域一條查詢:(llm OR rag OR agent OR gpt) created:>7天前 stars:>30、(nextjs OR react OR svelte OR nodejs OR golang) created:>7天前 stars:>20,各取 30 筆 | 逐查詢隔離;0 筆是正常結果,不告警 |
GET /repos/{full_name} | 為 Trending 候選補 repoId、topics、總星數、建立日 | 併發 ≤6,單筆失敗只丟該候選;401/403 立即告警,否則失敗率 > 50% 才告警 |
Search 的 OR 群組直接從歸類關鍵字表衍生(曾因兩處各寫一份而讓 vue 漂移),且查詢屬於哪個領域
不帶進歸類,一律由 topics/description 重新判定。
統一尺 weeklyStarsEstimate(src/board/weekly-stars.ts):Trending 候選直接用官方週增量;
Search 候選以 min(round(總星數 ÷ 天齡 × 7), 總星數) 估算。上限是關鍵:created:>7天 的 repo
所有星星都來自本週,總星數就是真實上界,沒有它,一個今天建立、300 星的 repo 會被線性外推到
2,100 星而壓過真正的 Trending 冠軍。天齡無法解析回 null 而非 0,因為 0 代表「今天建立」會被
最大幅放大。
GitHub API 用量:每次執行 2 次 search + 每個 Trending 候選 1 次 core + 每個新進/竄升 repo 1 次
README;呼叫在送出前計數(失敗也算),剩餘額度低於門檻(core 50/search 3)時預先退避,403 帶
Retry-After 視為次級速率限制而非憑證問題。
src/classify/)language 刻意不當輸入。ai 命中 blockchain。代價是 openai、
agents、reactjs 這類黏合詞要逐一補進 extra 清單。docker 命中,那是
部署方式不是領域),週增星 259/136/25 對比 AI 的 13,195/7,129。此決定只影響榜單,新聞側
的 DevOps 配額與來源完全不受影響;舊狀態檔中的 devops 項目以逐筆寬鬆載入丟棄並警告,不讓
整個狀態檔失效。週增星 ↓ → 總星數 ↓ → 新進者優先 → repoId ↑。同一個比較器用於保底席、競爭席與
最終名次,第四層保證嚴格全序,結果不依賴 sort 穩定性。repoId,改名或轉移 owner 不會被當成新 repo。src/diff/board-diff.ts)| 類型 | 定義 | 附簡介 |
|---|---|---|
| 🆕 新進 | 在本次 top 10、不在上次 | 是 |
| 🔺 竄升 | 名次前進 ≥1 | 是 |
| 🔻 下降 | 名次後退 ≥1 | 否,只列一行 #前 → #後 |
| 不變 | 名次相同 | 不出現 |
| 掉榜 | 不在本次 top 10 | 靜默;日後重回視為新進,簡介讀快取 |
「掉榜靜默」是結構性的:diff 只迭代本次推播榜,程式上不存在「掉榜」這種變化型別。已知代價: 門檻為 1 名時,任一新進會把下方所有 repo 都推成「下降」,但下降卡不耗簡介與 LLM,且視窗只有 10 席,成本有界。
榜單以 lastBoardPushAt 計時,不綁 cron。門檻 162h = 168h − 6h:時間戳記錄的是推播完成
時刻,永遠晚於 cron 觸發;若用整數 168h,七天後同一班 cron 算出來永遠差一點點而跳過,改由下一班
推,起點就往後滑。Actions cron 只會晚不會早,誤差單向累積,節奏會從 7 天漂成 7.x 天。6 小時
寬限同時吸收 cron 延遲與雙班抖動。判定回傳的是原因(no-timestamp/clock-anomaly/due/
not-due)而非布林值,時鐘異常時照跑但額外告警。未到期的執行在呼叫任何 GitHub API 之前就返回。
src/intro/、src/curation/board-summary*)repoId 為鍵快取在狀態檔,掉榜不清除,重回即命中。策展 prompt 踩過幾個具體的坑,修法多半是把約束從 prompt 文字移到程式結構或絕對判準:
officialPicks / communityPicks 兩個獨立陣列,LLM 只需
把每則正確分類(遠比「記得執行順序」簡單),「官方優先」交給合併邏輯固定排序,截斷時永遠先
吃社群那一組。2026-09-12 起兩陣列的定義為 officialPicks=(1) 官方發布+(3) 影響開發者的外部
事件、communityPicks=(2) 技術深度內容(見第 4 點),不再是單純的「官方 vs 社群」。officialPicks(同時命中 (2) 時以 (3) 為準,免得 HN 高分帶入的
當機事故落入 communityPicks 被截掉)——它們即使沒有技術細節,也直接改變開發者可用的服務或
必須遵守的規則。2026-09-25 的 Jev 事件把一個藏了兩個月的盲區翻出來:跨領域來源(HN)的關鍵字歸類原本兼任「離題過濾」, 無命中即丟。對已知領域這很合理,對「新崛起的東西」卻剛好相反——新公司、新模型的名字不可能在關鍵字表裡, 而那正是晨報最想第一時間看到的。重播四天的 HN top 100,被這道閘門丟掉的 ≥300 分候選每天 38~53 則,含 1979 分的 Jev 官方公告、MiMo v2.6、OpenJev、Grok 4.7。修法有三層:
通道而非救援:關鍵字無命中但分數 ≥300 的候選以「未歸類」身分入池(每日 20 席,09-26 由 10 調高),由 LLM 判定領域與
重要性並回填 domain;prompt 給的是正向先驗(「名字陌生 ≠ 不重要,你的訓練資料也可能沒有它」)。
擴充關鍵字只是治標——OpenJev、Astra、Dario 這類專有名詞永遠救不到。
同題群集:零 LLM 地統計「同一罕見詞跨多來源多則出現」,標給 LLM 當「正在崛起」的訊號。Jev 相關候選 曾連續四天進池、LLM 一則未選,因為單看一則陌生標題無從判斷輕重。
可觀測:歸類丟棄過去只有一個「-96」的計數,現在未歸類的保留數、入池數、名額外剔除數都有 log。
補位而非擴大範圍(2026-09-26):未歸類候選裡的資安事件與一般軟體工程新聞(F-Droid 2.0、Go 官方 SIMD、
Snapdragon 支援 Linux)對開發者有價值卻不屬三桶,過去一律落選。現在三桶精選未滿 15 則時才由第三陣列
backfillPicks 補位、永遠排最後、不計入非 AI 配額。上線首日 LLM 把 Node.js LTS 發布誤放進補位陣列而被整則
剔除,隔日改為「已歸類候選回流主桶套配額」——放錯陣列是分類錯誤,不該變成入選錯誤。
配套:候選池 60 → 70 → 80、晨報上限 10 → 15(非 AI 預設 5),上限是天花板不是目標;降級路徑排除未歸類候選。
LLM 只能用索引指涉候選、只回敘事文字;星數、連結、名次、日期永遠由程式填入,兩個 prompt 都明令 不得產生這些數字。就算 LLM 抽風,數字與連結永遠是真的。空回應(多為截斷或安全過濾)刻意 不重試,重送同一 prompt 通常仍空,只會白燒免費層配額,改走降級路徑。
state/board.json 是唯一權威狀態,只經 StateStore 讀寫;save() 先驗證、以 key 排序序列化
(git diff 乾淨)、寫 .tmp 再 rename;load() 遇壞檔擲錯不覆寫。save() 成功才把新狀態 assign 進共用物件,失敗只需還原簡介快照即可完整回滾,未落檔
的榜單推播不可能透過晨報段稍後的 save() 外洩。feed[].url 刻意不加 URL 驗證(z.url())、對 feed 不加 .max(50):嚴格驗證會在推播
成功之後讓 save() 擲錯、遺失時間戳,補班 cron 就會重推同一份晨報。上限只在唯一寫入點強制。state 分支:develop/main 不出現 bot commit,高頻變動檔不
製造合併衝突,且 commit 仍算 repo 活動、避免 Actions 60 天無活動自動停用。isFinite 守衛,因為 Number('') === 0 會在頁面改版時無聲記成
0 星;同類坑在速率限制標頭(Number(null) === 0)與天齡計算(回 null 不回 0)也各擋一次。.radar-alert-sent 標記檔:workflow 的備援告警只看標記
是否存在,涵蓋啟動前失敗、告警本身送不出、狀態 push 失敗,且不重複發。publish job 在 radar 之後執行,對狀態檔唯讀、零 LLM(模組層即不引入 LLM module):
index.html:無 JS 的靜態頁,順序為今日精選新聞 → 本週榜單(分 AI/前後端,含快取簡介)→ 上次
變化摘要;所有插值經 HTML escape。feed.xml:Atom 1.0,最新在前,最多 50 筆。新聞 GUID 為 news:{正規化 URL};榜單事件 GUID 為
repo:{repoId}:{new|climbed}:{日期},帶日期是因為同一 repo 可合法在數週後再次新進,純 repoId
會被閱讀器當作已讀吞掉。feed 只有新進與竄升,刻意不存星數,50 筆帶星數的時間序列就等於
自存星星歷史。feed.xml 先寫、index.html 最後寫,部署 gate 是 hashFiles('public/index.html'),
讓它兼任提交點,不可能部署出訂閱者全部 404 的半套站台。模組(src/) | 職責 |
|---|---|
config | env(zod)驗證,缺機密 fail-fast;news-sources.ts 來源清單與 schema |
sources / github | GitHub Trending 解析、Search/Repo/README API、速率限制與退避 |
classify | 榜單兩領域關鍵字歸類(零 LLM) |
board | 候選合併、weeklyStarsEstimate 統一尺、每領域 top 15 |
diff | 綜合 top 10、決勝比較器、七日節奏判定、與上次快照 diff、狀態 commit 純函式 |
news | 四種 fetcher、URL 正規化、標題相似度、已推清單、Stage A 漏斗、版本噪音過濾 |
curation | Stage B 單次 LLM 策展:prompt、解析、硬驗證、配額、字數收斂、降級;榜單 TL;DR |
intro | README 素材整理、簡介 prompt、250 字收斂、快取與降級 |
llm | Gemini 唯一封裝(429/503 退避、空回應不重試、錯誤帶狀態碼) |
pipeline | 榜單段/晨報段編排、guard、embed 組版與分批 |
discord | 三頻道 webhook、429 退避、失敗告警、告警標記檔 |
publish | 可見性偵測、頁面/feed 純函式渲染、發佈編排 |
state | 狀態 schema(寬鬆載入策略)與 StateStore 原子讀寫 |
| 用途 | 技術 |
|---|---|
| 執行環境 | Node.js 24、TypeScript(strict) |
| 應用框架 | NestJS 11(createApplicationContext,一次性 CLI job) |
| LLM | @google/genai(Gemini 免費層:晨報策展 gemini-3.8-flash(thinking=high)/備援 gemini-3.5-flash-lite、簡介與榜單 TL;DR gemini-3.5-flash-lite,見下方型號說明) |
| HTML/RSS 解析 | cheerio、rss-parser |
| Atom 產生 | feed |
| 驗證 | zod(env、來源清單、狀態檔、GitHub API 回應) |
| 排程與部署 | GitHub Actions(workflow_dispatch + 雙 cron)、GitHub Pages |
| 推播 | Discord Channel Webhook,三頻道分流 |
| 測試 | Jest、ts-jest |
Gemini 型號依資料流分兩個(src/llm/llm.types.ts),共用同一把 GEMINI_API_KEY 與同一套退避/錯誤分類:
| 用途 | 型號 | 說明 |
|---|---|---|
| 榜單簡介、榜單日 TL;DR | gemini-3.5-flash-lite(GEMINI_MODEL_BOARD,預設) | 免費層約 15 RPM/1,000 RPD;穩定態七天只有 0~數次呼叫 |
| 每日晨報策展(主) | gemini-3.8-flash(GEMINI_MODEL_NEWS)+ thinkingLevel: high | 免費層 5 RPM/20 RPD(2026-09-12 於 AI Studio 確認);每日 1 次、含退避最多 4 次 HTTP 嘗試(10s/20s/40s+jitter),對 20 RPD 有 5 倍餘裕;本機手動執行吃同一份 RPD |
| 每日晨報策展(備援) | gemini-3.5-flash-lite(GEMINI_MODEL_NEWS_FALLBACK)+ thinkingLevel: high | 主型號擲 LlmError(429/503 耗盡、型號 404、空回應、10 分鐘期限用盡)時以同一 prompt 單次重試,仍屬同一次策展;兩者皆敗才降級為原文標題版並發紅色告警(見第 9 關) |
thinking 只增加 token、不增加請求數,對 RPM/RPD 零成本;若型號以 400 拒絕 thinking 參數,LlmService
會以同一 prompt 不帶 thinking 重送一次,不會因設定問題一路降級。簡介與 TL;DR 不帶 thinking。免費層型號 ID
曾無預警提前下架(gemini-2.5-flash 與 2.5-flash-lite 在官方公告日前即回 404),所以 LlmService 對非可重試
錯誤一律印出實際狀態碼與訊息,避免 404 被誤判成速率限制。
型號沿革(細節見 開發指南 §2.4):
gemini-3.7-flash,當天撞免費層上限而改回 Lite(該型號從未進庫;撞限可能來自本機反覆手動執行,但「Flash 與 Lite 配額不同級、換型號前先查 AI Studio」的教訓成立)。gemini-3.8-flash、失敗退 Lite,其餘留 Lite。上線後 13 天裡 Flash 幾乎每天首次呼叫即 503(high demand),三天四次重試全數耗盡退 Lite;Lite 日只選 5~7 則,Flash 成功日 9~10 則。3.5-flash-lite、備援 3.1-flash-lite),想避開 Flash 的 503 與配額餘裕問題;但 Lite 四個策展日則數 5/7/7/6,且漏選明顯的官方發布,兩天後依預設的退場條件改回。3.1-flash-lite 退場(從未在正式排程成功過)。同日乾跑實測:Flash 四次 503 退 Lite,Lite+thinking 選出 12 則(同日無 thinking 為 6 則)。觀察中:若 Flash 持續每日退 Lite,下一步是把 Lite+thinking 設為主型號(只改常數)。| 變數 | 用途 |
|---|---|
DISCORD_NEWS_WEBHOOK_URL | 每日晨報 |
DISCORD_BOARD_WEBHOOK_URL | 榜單變化 |
DISCORD_ALERT_WEBHOOK_URL | 告警(來源失敗、發佈失敗、備援告警) |
GH_API_TOKEN | GitHub API 唯讀;不可用 GITHUB_ 前綴,Actions 會擋 |
GEMINI_API_KEY | Gemini API |
缺任一機密即 fail-fast、exit ≠ 0、不推播;驗證錯誤訊息只含欄位名,不含值。
npm ci
npm run build
DISCORD_NEWS_WEBHOOK_URL="https://discord.com/api/webhooks/…" \
DISCORD_BOARD_WEBHOOK_URL="https://discord.com/api/webhooks/…" \
DISCORD_ALERT_WEBHOOK_URL="https://discord.com/api/webhooks/…" \
GH_API_TOKEN="…" \
GEMINI_API_KEY="…" \
node dist/main.cli.js
$env:DISCORD_NEWS_WEBHOOK_URL="https://discord.com/api/webhooks/…"
$env:DISCORD_BOARD_WEBHOOK_URL="https://discord.com/api/webhooks/…"
$env:DISCORD_ALERT_WEBHOOK_URL="https://discord.com/api/webhooks/…"
$env:GH_API_TOKEN="…"; $env:GEMINI_API_KEY="…"
node dist/main.cli.js
目前有 install script 的 4 個相依套件已在 package.json 的 allowScripts 記為 false,安裝時不會執行(需 npm ≥ 11.18,Node 24 線 ≥ 24.20)。新增依賴後若 npm ci/npm install
列出「not yet covered by allowScripts」,依開發指南 §8.y 以 npm install-scripts deny|approve <pkg> 處理。
另有三個模式:NEWS_INGEST_OBSERVE=1 只跑 Stage A 漏斗並印出候選表(不呼叫 LLM、不推播),
PUBLISH_MODE=1 只跑發佈段(見 quickstart),
NEWS_DRY_RUN=1 晨報乾跑(2026-09-27):跳過 18h guard、照常抓取與策展(消耗 1 次策展配額),結果推到
告警頻道(標「乾跑」),不推晨報頻道、不寫狀態、不跑榜單段。Actions 上以 workflow_dispatch 勾選
dry_run 觸發,state commit 與 Pages 發佈一併跳過;用來在調整 prompt/型號後立即驗證,不必等隔日排程、
也不必動 state 分支。NEWS_REPLAY_DATE=YYYY-MM-DD(須搭配 NEWS_DRY_RUN=1;Actions 上填 replay_date 即隱含乾跑)
為降級日補發(2026-10-17):把該台北日已推的原始標題逐則翻成繁中(不重新篩選),先送一則黃色說明、再送翻譯版到告警頻道,不寫狀態。
npm test
810 個單元測試、71 個測試套件,與原始碼同目錄。憲章要求的關鍵邏輯皆有覆蓋:Trending 解析(HTML 快照)、兩領域歸類、榜單 diff 與決勝、URL/標題去重、簡介快取命中、新聞配額與字數上限、來源 schema 與 tier 加權、未歸類通道與同題群集、補位與回流、晨報 18h guard、榜單 162h 節奏、狀態原子寫入。 Gemini 一律 mock,並另測降級路徑與 thinking 退回路徑。
.github/workflows/radar.yml:workflow_dispatch + cron 7 20 * * *、37 20 * * *(UTC),
concurrency 排隊不取消。radar job 從 state 分支載入狀態、執行、僅在有 diff 時由 radar-bot
commit 回 state 分支(push 失敗重試 3 次);publish job needs: radar,以 job 層級最小權限
部署 Pages。設定方式:Settings → Secrets and variables → Actions 填五項機密;Settings → Pages 把
Source 設為 GitHub Actions;到 Actions 頁 Run workflow 手動驗證。手動執行時勾 dry_run 即為晨報乾跑:
跳過 18h guard、真的抓取與策展、結果推到告警頻道,不寫狀態、不跑榜單段、不發佈 Pages。
.github/workflows/test.yml:push(排除 state 分支)與 pull_request 時以 Node 24 跑兩個並行 job,權限只有
contents: read、checkout 不保留憑證、各限 10 分鐘:test(npm ci --ignore-scripts → npm run build → npm test)
與 audit(npm audit --omit=dev --audit-level=high,只看執行期依賴)。audit 在既有依賴出新公告時也會紅燈,
不一定是該次 push 造成;有修正版就開 fix/ 分支升級,沒有修正版或確認誤報時記進 docs/plans/ 並接受紅燈到上游修正。
與每日排程分開,測試或稽核失敗都不擋晨報。三處 npm ci 都帶 --ignore-scripts,不讓相依套件的 install script 在帶有
token 的 job 裡執行;本機則由 package.json 的 allowScripts 把目前有 install script 的套件記為不執行。現況見開發指南 §8.y、理由見 ADR 0008。
| Feature | 目錄 | 內容 |
|---|---|---|
| F1 | specs/001-foundation | 專案骨架、狀態存取、推播通道、排程 |
| F2 | specs/002-board-sources | 榜單來源抓取與兩領域歸類 |
| F3 | specs/003-board-state-diff | 榜單快照與變化偵測(七日節奏) |
| F4 | specs/004-news-ingest | 新聞來源設定檔與零 LLM 過濾漏斗 |
| F5 | specs/005-repo-intro | LLM 封裝與 repo 簡介生成 |
| F6 | specs/006-news-curation | 每日單次 LLM 策展與降級備援 |
| F7 | specs/007-pipeline-push | Pipeline 端到端編排與 Discord 組版 |
| F8 | specs/008-pages-publish | GitHub Pages 儀表板 + Atom feed |
每個 Feature 從 develop 各自 branch,走完整 Spec Kit 流程(specify → clarify → plan → checklist → tasks → analyze → implement)後以 --no-ff 合併回 develop。
| RSS |
| 前後端 |
| 停用 |
| feed 自 2026-05-29 起停更,形同啞源 |
gh-kubernetes | GitHub Releases | DevOps | 啟用 | Kubernetes 官方發佈 |
kubernetes-blog | RSS | DevOps | 啟用 | Kubernetes 官方 blog,每週約 4 篇版本功能文章;releases 經過濾後每月僅約 1 則,補上一手功能說明(2026-09-12 新增);新鮮度視窗縮為 10 天(2026-09-21:版本系列文在 feed 上掛數週,每天滴一兩篇三週前的舊文) |
cncf-blog | RSS | DevOps | 啟用 | CNCF 官方 blog |