模組二|敘事規格化(Day 5–9)
《矽墟》是我正在寫的一部科幻小說,拆成 200 回短篇連載,整部作品用管軟體專案的方式在管:敘事結構寫成規格檔,成品用腳本驗收。訂過的規則多半有效——句數守住了、追讀引擎跑起來了、完稿淘汰線壓出了每句 12 字的密度。
本篇講一個失敗的。我覺得它比那些成功的更有用,因為證據就在同一個檔案裡:兩張狀態表,一張完整活到第 20 章,一張在第 20 回就停更了。
同一個人寫的、同一份文件裡、同一段時間。差別只在設計。
一回 20 句,處理一個立即問題。這個尺度很好寫。
問題是跨回的東西:
寫到第 150 回的時候,前面 149 回不在你腦子裡。你需要一個外部的狀態存放處。
這件事本身沒有爭議,大家都知道要記。難的是它怎麼樣才不會死。
Day 5 講過它,長這樣:
| 章 | 本章結束時隊伍狀態 | 本章新增/更新的問題 | 下一章不得忘記 |
|---|---|---|---|
| 01 | 調律者+焰刃;守前/報後成立 | 誰在追著回訊? | 焰刃不是武器,是主動留下守人的人。 |
| … | |||
| 20 | 零式為缺席者答到,隊伍守住她 | 舊院未破、海霧與回收域未關 | 這是第一部結束,不是世界答案。 |
20 列,一列不缺,從第 01 章到第 20 章全部有內容。
同一個檔案,往下滾幾行,另一張表:
| 篇/回 | 已寫入的關係狀態 | 留給下一回的問題 |
|---|---|---|
| 01.01–01.05 | 調律者先替未知的過路人扶正警示牌,再為車底義體用掉最後半格電;他選擇接近,但不答陌生的呼喚。 | 主核為何知道他的名字? |
| 01.06–01.10 | 焰刃醒後主動護人;兩人以「左砍、右報」建立第一個位置默契,並一起回山。 | 誰在夜市暗處學走他們的節拍? |
| 02.01–02.05 | 焰刃替調律者守住第一個據點;調律者學會不替綠語說「放手」。 | 綠語醒後,會如何面對自己救不回來的東西? |
| 02.06–02.10 | 綠語先問能不能碰,焰刃主動留下疤;三人把「記得」和「救回」分開。 | 殘塔為何比三人的心跳慢一拍? |
四列。到 02.10 為止。
而 novel/短篇/ 裡實際有:
200 檔 61,405 字元 每回 20–21 句,全數完稿
這張表落後 180 回。
它下面還有一行字,寫著「實作位置:01.01_夜市失聲.md 至 02.10_說好了.md」,那是它最後一次被更新時的狀態,然後就凍在那裡了。
我在寫這個系列之前,完全不知道它停在這裡。
我一開始的解釋是「回太多了,記不完」。但這個解釋不成立:那張表是 5 回一列,200 回只需要 40 列。章表有 20 列,40 列並沒有多到做不完。
真正的差別在別的地方。

章表是我排劇情的時候寫的。我要決定第 8 章誰加入、留什麼問題給第 9 章:寫這張表就是在做規劃工作本身。
回表是我寫完一回之後要回頭補的。那一回已經完成了,故事已經前進了,回去填表不會讓任何東西變好。
前者在工作路徑上,後者在工作路徑之外。
這就是全部的原因。任何需要「做完事之後額外回去補」的紀錄,都會死。不是因為人懶,是因為那個動作沒有任何當下回報:你填不填,下一回都照樣寫得出來。
章表我會讀。執行表(NOVEL-STATE-SYSTEM.md,Day 2 講過的那份動筆前必讀的執行表)的固定流程第一步就寫著:
- 從台帳讀「本章結束狀態」與「下一章不得忘記」。
每次動筆前都會讀它,所以它壞了我馬上知道。
回表沒有出現在任何流程裡。它是「寫給以後的自己看的」,而以後的自己從來沒有被要求去看它。
沒有人讀的文件,不會有人發現它過期了。 它可以錯 180 回而毫無症狀——我今天是為了寫這篇文章去查,才發現的。
章表的粒度是「章」:一個章結束時,隊伍狀態確實有一個明確的變化,值得記一列。
回表的粒度是「5 回」,但 5 回這個切法是我硬分的,它不對應任何自然的狀態變化邊界。有時候一個關係變化橫跨 8 回,有時候 2 回就跳兩次。5 回一列,記的內容永遠是勉強湊出來的。
粒度如果不對應真實的變化邊界,填表就會變成一件感覺不對的事,而感覺不對的事最容易被跳過。
我還沒改,但方向想清楚了,寫在這裡當作紀錄。
方向一:把它從手寫改成生成。
「留給下一回的問題」其實就是每一回的最後一句。而最後一句在檔案裡,可以直接抓出來:
# 每回最後一句 = 那一回留的鉤子
for f in novel/短篇/*.md; do
echo "$(basename $f .md) $(grep -v '^#' "$f" | grep -v '^>' | grep . | tail -1)"
done
跑一次就有 200 列,而且永遠不會過期,因為它是從內容算出來的,不是另外維護的。
能推導的東西不要手動維護:這條在寫程式上是常識,我在文件上卻犯了。
方向二:手寫的部分只留推導不出來的。
「已寫入的關係狀態」這欄推導不出來,它需要判斷。那就只留這一欄,而且粒度改成「每次關係真的變化時記一列」,不是每 5 回記一列。
表格的列數應該由事件決定,不是由固定間隔決定。
方向三:讓它進入流程,否則不要做。
如果一張表不會出現在「動筆前要讀什麼」的清單裡,那它遲早會死。與其留一張過期的表誤導未來的自己,不如不做。
過期的狀態表比沒有狀態表更危險,因為你會相信它。

代價一:我現在有一張錯的表在 repo 裡。
它看起來很正常——格式整齊、內容正確、只是停在 02.10。如果我沒有去數 novel/短篇/ 有幾個檔案,我會以為它是對的。
這種「正確但過期」的文件,殺傷力比明顯錯誤的文件大得多。
代價二:生成方案會失去人的判斷。
自動抓最後一句,抓到的是「文字上的最後一句」,不是「我當初想留的那個問題」。有些回的鉤子藏在倒數第三句,最後一句只是收尾。
自動化會讓表永不過期,但也會讓它變笨。 這是個真實的取捨,不是免費升級。
代價三:我到現在還沒修。
寫完這篇的今天,那張表還是四列。修它要重讀 180 回的內容,那是好幾天的工作。
我把它列進待辦,但我不確定會不會做——而這個不確定本身,就是「工作路徑之外的事會死」最好的例證。連寫了一整篇文章講它,都不保證我會去做。
一、狀態紀錄要長在工作路徑上,不能掛在旁邊。
判斷句:做這件事的時候,我是不是本來就得產出這個東西?
會活的東西的例子:PR 模板裡的必填欄位、CI 產出的報告、commit message、規劃階段的設計文件。
會死的東西的例子:寫完程式再補的架構圖、上線後才寫的 runbook、「記得更新」的 changelog。
不是紀律問題,是位置問題。 換一批更自律的人來,結果一樣。
二、沒有讀者的文件會靜默過期,而且無法察覺。
每一份文件都應該能回答:誰、在什麼時候、會被要求讀它?
答不出來的,就是準備要過期的。而它過期時不會有任何症狀,這是最危險的部分。
我的回表錯了 180 回,repo 完全正常、文章照樣產出、沒有任何東西壞掉。它只是安靜地在那裡等著誤導未來的我。
三、能推導的不要手動維護,這條在文件上跟在程式上一樣。
我們都知道不該把 derived state 存起來手動同步。但換到文件、表格、清單上,就會忘記這條。
先問:這一欄能不能從既有內容算出來? 能的話寫個五行腳本,比維護紀律可靠一百倍。
推導不出來的那些欄位,才是真正需要人的地方,而那時候你要維護的東西已經少很多了。
模組二到此結束。五天講的是同一件事:把主觀品質變成可判定的規格,定義單位(Day 5)、寫成位置(Day 6)、串成引擎(Day 7)、用刪除測試驗收(Day 8),以及知道哪些規格其實不會被執行(Day 9)。
明天進模組三,題目換到 AI 生圖產線。第一篇先講整體架構:為什麼我用三個不同的模型做三件事,而不是找一個最強的打天下。