# Postmortem Prose

> Write tech longform in Traditional Chinese (Taiwan) with a postmortem voice: a personal, battle-tested style guide for de-AI-flavored engineering writing. 這是一份「個人」風格指南：撰寫／潤飾繁體中文（台灣）技術長文，聲音＝資深 SRE 寫「重寫戰記／事故復盤」。 觸發時機：要寫或校一篇技術部落格／長文（尤其「某產品的原生重寫、架構取捨、FFI／系統設計」這類 case study）、 把一段技術文字「去 AI 味」、或決定文章的語氣／節奏／結構／譬喻／標點。 由 TokenBar「Rust 引擎、Swift 外殼」重寫長文（HackMD zh/en，2026-06 反覆潤了七輪、被讀者實際回饋「AI 味」後修出來）萃取而成。 注意 genre 邊界：本 skill 是「技術長文」，與社群貼文／GitHub PR·issue 的克制語氣不同（見 §12）。

- Skill: `nanako0129/postmortem-prose` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add nanako0129/postmortem-prose`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nanako0129/postmortem-prose/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Nanako0129 (https://skillmd.com/u/nanako0129)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nanako0129/postmortem-prose

---


# postmortem-prose：用寫事故復盤的方式，寫技術長文

> 這是一份**個人**風格指南，別當通用最佳解拿去套。它記錄一個 SRE 怎麼寫自己的技術長文：規則是我的偏好（例如中文零破折號）、教訓是真的踩過的。拿去用時，把 persona 與偏好換成你自己的。

一句話目標：**讓文章讀起來像一個資深 SRE 在寫事故復盤／技術筆記：直白、有意見、敢下判斷、一句講一件事、用具體踩雷的語言，把「資訊密度過高的正確資訊堆疊」那種 AI 味洗掉。**

---

## §0 核心診斷：讀者說的「AI 味很重」，病灶在句子層級

這是全篇的總綱，其餘規則都是它的展開。

> 真實回饋長這樣：內容很有料、被稱讚有判斷力；但句型、用詞、敘述方式讀起來像 AI：生硬、資訊密度太高、難消化。而且讀者**講不出哪裡**像，只有「感覺」。

所以去 AI 味動的是**句子**，內容通常留著就好。目標聲音：

| 要 | 不要 |
|---|---|
| 直白、一句講一件事 | 一句塞三個觀念、資訊密度爆表 |
| 敢下判斷、有意見（「這不叫工程，比較像任性」） | 什麼都 hedge、四平八穩 |
| 具體踩雷語言（「為什麼按鈕是黑的，花了我一個下午」） | 抽象、教科書式定義堆疊 |
| 主動降低每句密度：長句拆短、留呼吸 | 每段都是高潮、讀者喘不過氣 |

---

## §1 硬規則（零容忍，每次潤稿後 grep 驗證）

### 1.1 破折號：分 genre 的矩陣

**技術長文（本 skill）：中文一律不用破折號。** 用冒號、逗號、分號、括號或拆句代替。這條也適用「我自己給使用者的中文回覆」，不只文章。**英文的 em dash 是標準標點、可保留**（英文拿掉反而生硬）。

跨 genre 對照（避免搞混，我搞混過很多次）：

| Genre | 中文破折號 | 英文 em dash |
|---|---|---|
| **技術長文（本 skill）** | 不用，改標點／拆句 | 可用（標準英文） |
| 社群貼文／release 宣傳 | 不用 | 不用 |
| GitHub PR·issue 內文 | 不用 | 可用但克制，且用真 unicode `—` 不用 `--` |
| landing 網頁文案 | 可用 | 可用 |

> 若某 genre 真的要用中文破折號，一律用「——」（U+2014×2 全形雙格），不可用單個「—」、連字號、或為避開而硬改成逗號。一般 hyphen（`sub-agent`、`per-session`）不受此限。

### 1.2 中國用語＝零容忍，一律台灣用語

每次潤稿後對整份 `grep` 掃一遍：

| 中國用語 | 台灣用語 | | 中國用語 | 台灣用語 |
|---|---|---|---|---|
| 代碼 | 程式碼 | | 默認 | 預設 |
| 進程 | 行程 | | 信息 | 資訊 |
| 函數 | 函式 | | 質量 | 品質 |
| 數組 | 陣列 | | 軟件 | 軟體 |
| 字符串 | 字串 | | 用戶 | 使用者 |
| 內存 | 記憶體 | | 報錯／報紅 | 出錯／變紅 |
| 性能 | 效能 | | 視頻 | 影片 |
| 緩存 | 快取 | | 屏幕 | 螢幕 |
| 調用 | 呼叫 | | 支持 | 支援 |

### 1.3 全形標點

zh 一律用全形：`，。：；、！？「」『』（）`，不用半形 `, . : ( )`。英文字／程式碼識別字之間照常用半形。

### 1.4 其餘硬規則

- **不用 emoji、不用行銷腔與浮誇詞**（「超」「感動」「🚀 revolutionary」都不要）。熱情 ≠ hype。
- **先讓讀者認識產品，再講技術**（這條是致命傷等級）。開頭先用具體畫面講清楚「它是什麼、長什麼樣、能幫使用者什麼」（配 hero／popover 截圖、列可見的 UI 表面），再進 FFI／架構。否則整篇變成「為一個我不認識的東西在炫技」。
- **事實一律對原始碼／來源查核，零虛構**。數字、函式數、版本、程式碼片段都要對得上 repo。（教訓：外部 AI 校稿把 macOS 26 改成 15＝引入錯誤、還幻覺兩個不存在的錯字。外部 AI 建議只是輸入，逐條驗過才能用。）
- **正文不留內部草擬痕跡**：拿掉「撰寫中草稿」標記、`[圖片]` 預留、`<!-- 內部註解 -->`、章節 [TODO]。也不要破第四面牆（「順便澄清 outline 草稿寫錯的事」這種只有作者知道的指涉，讀者出戲）。
- **staged／模擬的截圖一定在圖說標「示意」**，不可讓讀者誤以為是真實版本／真實 release notes。

---

## §2 句子層級的去 AI 味（§0 的具體手法）

### 2.1 避開 AI 對比句型

`不是⋯而是⋯` / `X，不是 Y` 這類對比句，神經敏感的讀者一眼判定「AI 寫的」，即使單句本身沒問題也有「味道」。打散、換句話說：

```
✗ 我的安全網是紀律，不是 backstop。
✓ 這裡沒有兜底的 backstop。真正撐住邊界的，是紀律。
```

少量真有修辭力的可留，但別整篇都是。

### 2.2 中文避免英式 staccato（過短句＋句號）

`一鍵。` `夠簡單了。` `macOS 14 以上。` 這種極短句配句號，在中文讀起來很突兀（英文反而是力道）。用逗號把短句串成流動的長句。

- **判準**：一句話中間沒有逗號、直接接句號、≤ 約 18 字＝要排除。
- **修法**：預設用冒號／逗號併入鄰句（題目句用冒號帶出說明最自然），或改成獨立一行不加句號，或用驚嘆號。
- **例外**：deliberate 的格言式收尾可保留（「先探測，再解析。」）。英文不受此限。

### 2.3 不要 meta-announce 結構／濃縮

`一句話：` `好問題，我們來把它拆開看。` `重頭戲來了` 這種宣告式開場是冗詞。連問兩句讀者就知道你在設問，直接給答案；想濃縮就直接濃縮，別先宣告「我要濃縮成一句話」。

### 2.4 關鍵技術名詞要解釋

對不熟 Rust／Swift 的讀者，一句塞三個看不懂的名詞會勸退。

- **行內極短註解**：`` staticlib（靜態函式庫：編譯期連進主程式） ``。
- **撐起整節論點的大概念**（FFI、ABI）用 admonition／blockquote「**名詞小抄**」（粗體開頭、不用 emoji）。
- density 寧可多一點，每則短到專家能一眼略過即可。

---

## §3 語氣、語調、口吻

- **活潑來自對技術發自內心的熱情**：「這個太酷了，我好想讓你也知道」這份情感貫穿全文、感染讀者，是讓人讀得心情澎湃的關鍵。具體：真誠的「第一次看到時我⋯」「我加了一個快取 vs 我想過這個快取」。但仍不用 emoji、不用 hype。
- **敢下判斷、有意見**：SRE 的品味在於「知道這個工具不能怎麼壞」。用強觀點開場（「能跑、有測試、踩過真實資料的程式碼，只為了遷就一道語言邊界就丟掉重來，那不叫工程，比較像任性」）。
- **誠實＝這類文章的最強武器**：
  - 主動承認搆不到的天花板（Liquid Glass、`catch_unwind`）。
  - 大方把功勞給對的人（引擎給上游 tokscale、記憶體優化給貢獻者、程式碼給 AI）。
  - **權威靠證據不靠身分**：如果作者不是該技術棧老手，就更要用**實測數字、測試、觀察**建立信任，別用「隱含的專家口吻」撐。每個 claim 掛環境（release build、機型、資料量、樣本次數）。
  - **AI 協助要揭露，且框成底氣、別寫成道歉**：「我不是 Rust／Swift 專家，程式碼大量是 AI 寫的，我的工作是另一半：定義需求、架構原則、失敗邊界、什麼叫『對』，然後不斷 review、退回、修正它的輸出。」這把文章從「FFI 深潛」重定位成「AI 時代的 SRE case study」，更獨特也更難被打。（放開頭、可用 `:::info` 色塊。）
- **克制自我稱讚**：`我最想分享／我最得意／我最喜歡的手工` 這類「最」用多了邊際遞減。留一兩個最重的，其餘拿掉。**保留**本質謙虛的（「我幾乎要為『沒有自己寫它』感到驕傲」＝把功勞給 tokscale）。

---

## §4 節奏

- **設問 → 解答**是引擎：先丟一個讀者心裡的問題，再由文章解答，製造「哦，原來是這樣，我看懂了」的著陸點。即使讀者沒全懂，這些斷點會讓他有信心、有興趣讀下去。（「值得嗎？我覺得值得。」這種設問→解答是刻意的聲音，別當 AI 味刪掉。）
- **喘息空間**：短段落、signpost（「我們解決了 X，但這帶出 Y⋯」）。技術長文尤其需要。
- **一個議題接一個議題**，中間穿插反思與延伸問題，思緒是流動的，別寫成清單。

---

## §5 譬喻

- **精簡、功能性的譬喻可以**：「保留引擎，換掉身體」「把韌性焊進每一道接縫」有辨識度，是聲音。
- **過度文藝的比喻會被工程師讀成 AI／矯情**：例「一道誠實的傷疤」用一兩次有力，用四五次會從「坦誠」滑向反向炫耀（把限制重新包裝成品味）→ 洗掉，但保留它在講的事實。
- **同一個譬喻別重複太多次**（discipline×7、weld×4、battle-tested×3 就太密）。
- **保留**翻譯書式的風趣設問（不讀翻譯書的讀者 get 不到也沒關係，那是聲音）。**不要**學使用者另一個 persona 的「人類噪音」：動漫梗／東方梗埋梗、顏文字 kaomoji，那是別的 voice，不進技術長文。

---

## §6 結構與起承轉合

**Genre 定位**：這是「工程重寫戰記／case study」，**別當 tutorial 寫**。它不保證讀者能照著做，它讓讀者認識「你怎麼做這件事、你的工程取捨」。接受這個定位，長度與密度就有正當性。

### 起承轉合

- **起**：產品是什麼＋為什麼要做（§0）。一句話論點壓成標題（「Rust 的引擎，Swift 的外殼」）＝開場就回答一個工程決策。
- **承**：埋一個硬限制當種子（§1「靜態 library 沒有自己的背景迴圈」），明說「到 §3 你會看到它逼出我最在意的設計」。
- **轉**：在後面的章節解開那個限制（§3 用惰性 tick 回答 §1 的種子）。每一節＝拆解論點裡的一個動詞。
- **合**：§9 回到開頭的一句話論點，逐條收束（留住引擎／最小 FFI／焊進韌性）。

### 版面順序

1. 頂部 metadata bar（日期 · 閱讀時間 · 標籤）。閱讀時間**要誠實**（30 分的長文別標 15 分）。
2. **先講結論／TL;DR**：一句話論點 + before/after 數據表（呼應數據導向）。
3. （AI 協助很深時）緊接一段**定位句**（§3，可 `:::info`）。
4. `[TOC]` + 一句 **reading guide**（「想看 FFI 讀 §2–3、想看正確性讀 §4–5」）降低長文門檻。
5. 各節之間用 `---` 分隔。
6. **接近結尾放一段「誠實的邊界／還沒解」**：本機 log 不是計費真相、沒量常駐 CPU／冷啟動／電池⋯。這比第五個「傷疤」更能建立可信度。每個問題都配一個漂亮解法，反而降低可信度。
7. 結尾「延伸閱讀」footer。
- **每個 claim 收斂到情境**：「在這個資料量／更新頻率下成立的選擇」，不要寫得像「JSON FFI 是最佳解」的 definitive guide。
- **圖片 caption 寫「這張圖告訴你什麼」而非只描述**。

---

## §7 排版鐵則（HackMD／部落格皆安全）

- **段落一段一行、不硬斷**（HackMD `breaks: true` 把單一換行當 `<br>`，硬斷會跑版）。
- **圖一律用 Mermaid**，不要手繪 ASCII art（CJK 全形字與等寬 ASCII 對不齊，必跑版）。平台不吃 Mermaid 再 export SVG/PNG。
- **強調框用 HackMD admonition**：`:::info`（藍，context/名詞小抄）、`:::success`（綠，核心論點）、`:::warning`（黃，硬限制／鐵則）、`:::danger`、`:::spoiler`。色塊前後**必須留空行**；別在一段裡疊太多色塊。
- **複雜的部分轉 md-style 圖表**（流程→ Mermaid、多欄比較→表格），列點是最後手段。
- **標題獨佔一行、前面留空行**（`## §N` 黏在前一句同一行不會被 parse 成標題；ATX 標題前缺空行很脆弱）。
- mermaid label 用純文字（`at least 10s`），別用 `&ge;` 之類 HTML entity（HackMD 可能渲染成字面）。

---

## §8 雙語（zh + en）紀律

- **平價（parity）**：兩版說同一件事、同樣的數字與 claim，別讓版本漂掉（雙語文章最常見的 bug）。
- **標點按語言各自處理**：中文不用破折號、英文 em dash 可留；中文全形、英文半形。
- 中文的 inline 名詞註解密度可比英文高一點（對中文讀者是對的選擇）。
- 改動要成對：改一版就對照改另一版，並確認數字沒有單邊漂移。

---

## §9 潤稿 SOP（使用者拍板「這 SOP 很好」）

```
Gemini（agy CLI，出 SRE 口吻、去 AI 味的草稿）
  → Claude 守門（修回作者的聲音／母題、清掉中國用語、補回被漏掉／改掉的事實數字）
  → grep 驗證 0 中國用語 + 0 中文破折號
  → 使用者過目
  → 才走 HackMD 推送流程
```

> 關鍵：**Gemini 分不出「作者刻意的聲音」與「AI 味」**（會把設問→解答、傷疤母題當 AI 味刪掉），所以 voice 守門必須 Claude 來。校準目標 voice 的依據＝爬鐵人賽＋知名技術 blogger 抓的共同點。

**agy（Gemini CLI）工法**：大檔**不要 inline 進 prompt**（68KB 會卡死十幾分鐘）；改 `--add-dir <dir>` 讓它自己讀檔（小 argv 繞過卡點）。`Gemini 3.5 Flash (High)` 可用且快；多輪用 `-c`（continue，保有全文 context）；每次跑前後 `md5 -q` 比對證明它沒改到檔（純建議模式）。macOS 無 `timeout`（用 `gtimeout` 或 Bash 工具自身 timeout）。

---

## §10 對外部 AI 校稿的紀律

外部 AI（Gemini、ChatGPT reviewer⋯）的評價只是**輸入**，逐條對原始檔／程式碼查核後才能採用：

- **會幻覺硬錯誤**：把 macOS 26「訂正」成 15（反而引入錯誤）、宣稱有兩個不存在的錯字。
- **會讀到舊版**：它戳「我最X 太多」時，那些其實我上一輪已軟化；它戳「mtime 假設沒講」時我已補了。**先確認線上現況再回應**。
- **會講過頭 / 高估**：說「誠實傷疤四五次」實際是三次。
- **但真戳中的要認**：TokenBar 這篇被戳得最準的一項＝「沒有 `catch_unwind` 又沒設 `panic = "abort"`，panic 跨 C ABI＝UB」，這是真洞，補一行 `panic = "abort"` 就解決。

分類：哪些**已修**、哪些**真開放值得做**、哪些**我不同意/它講錯**、哪些**要使用者給資訊**。

---

## §11 HackMD 發佈機制（ops）

- API token 放本機檔案、不進版控（讀取只 inline、不印不存）。API base `https://api.hackmd.io/v1`；`GET /me` 驗證、`GET /notes` 列表、`PATCH /notes/{id}` body `{"content": 全文含 frontmatter}`。
- **雷一**：請求 body 上限約 100KB，`json.dumps` 預設 `ensure_ascii=True` 會把中文轉 `\uXXXX` 灌爆成 102KB → 413。**必須 `ensure_ascii=False` 再 `.encode('utf-8')`**。
- **雷二**：curl 要用 `--data @body.json` + 純 `Content-Type: application/json`；用 `--data-binary` + `charset=utf-8` 會回 500。
- PATCH 回 202、無 body；推完用 `GET /notes/{id}` 抓回比 **md5** 驗證（比 `/download` 可靠、無 CDN 快取）。
- **邊改 live 邊潤＝推前務必重抓 live 當基準＋drift 防護**（GET 比對 base，不符就 abort 不蓋，保住使用者線上手改）。
- 圖片：本機圖用 `hackmd.io/_uploads/...`，潤稿只動文字、URL 一字不動；改動前後驗證 `_uploads` URL 集合不變。

---

## §12 Genre 邊界（別把本 skill 套錯地方）

本 skill 是**技術長文**。同一個人在別的場合語氣不同：

- **社群貼文／release 宣傳**：更克制、無 emoji、數據導向、CTA 極短、不用任何破折號。
- **GitHub PR／issue**：預設**英文**、套 [[md-style]]（表格/blockquote/code 優先於列點）、回 AI reviewer 不寫社交肯定（「Good catch」等）、開頭 @對方。
- **landing 網頁文案**：可用 em dash。


---

## 附錄：發佈前快速 checklist

- [ ] `grep` 0 中國用語、0 中文破折號、標點全形
- [ ] 無 emoji、無 hype 詞、無 `不是…（而）是` 對比句（含省略「而」與倒裝「是X，不是Y」的變體）、戲劇化譬喻不重複
- [ ] 開頭先講「產品是什麼」＋ TL;DR 數據表＋（AI 協助則放定位句）
- [ ] 每個數字掛實測環境；claim 收斂到情境、非 definitive guide
- [ ] 有「誠實的邊界／還沒解」段；功勞歸對人；AI 揭露框成底氣
- [ ] 設問→解答的節奏、短段落喘息；自我稱讚「最」留一兩個
- [ ] 標題獨佔一行＋前後空行；admonition 前後空行；圖用 Mermaid
- [ ] 雙語 parity：數字/claim 不漂移；標點各語言各自處理
- [ ] 內部草擬痕跡清乾淨；staged 截圖標「示意」
- [ ] 事實逐條對 repo/原始碼查核（含外部 AI 校稿建議）
- [ ] 推 HackMD：`ensure_ascii=False`、drift 防護、md5 readback、`_uploads` 不變

