<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>文件 on Tarragon</title><link>https://tarrragon.github.io/blog/tags/%E6%96%87%E4%BB%B6/</link><description>Recent content in 文件 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Sat, 08 Aug 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E6%96%87%E4%BB%B6/index.xml" rel="self" type="application/rss+xml"/><item><title>多份文件必然漂移：同步期待要嘛有機制承接、要嘛明示降級</title><link>https://tarrragon.github.io/blog/report/doc-sync-needs-mechanism-or-demotion/</link><pubDate>Sat, 08 Aug 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/report/doc-sync-needs-mechanism-or-demotion/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>這則檢討處理開發流程的文件鏈設計：一個功能從需求到實作，資訊會流經多份文件——proposal、spec、use case、設計文件、追溯表、測試、註解、工作日誌。Brooks 在《人月神話》（The Mythical Man-Month）處理過這個問題，結論是同時維護多份文件不可能持續：文件之間的進度必然產生落差，而有落差的文件最終完全沒有人更新；他給的方向是把文件盡可能併入程式自身（self-documenting programs）、減少獨立文件的數量。Brooks 的直接對象是程式的文件（散文描述與流程圖、對照原始程式）；把同一條機制推廣到需求到實作的整條文件鏈，是本卡的延伸。&lt;/p>
&lt;p>本卡把這個論點收斂成可操作的判準，論述基礎有三塊。&lt;strong>站內的既有實測&lt;/strong>：一條規則的抽象卡片修過三次、執行端讀的操作文件停在第一版（原則層與操作層的單向漂移）；一行宣稱約束的註解在測試已存在時是沒有保護力的副本；測試假後端檔頭的「已模擬行為」彙整清單，沒有任何機制守著它與實際處理邏輯同步、終將過期（&lt;a href="https://tarrragon.github.io/blog/testing/05-test-design-judgment/test-comment-and-naming-discipline/" data-link-title="測試註解與命名紀律" data-link-desc="測試註解寫什麼、名稱與 reason 怎麼收斂、分析詞彙與開發過程該不該進程式碼 — 判斷測試文字去留的紀律">測試註解與命名紀律&lt;/a>）。&lt;strong>一次文件鏈盤點&lt;/strong>：對一套 TDD 流程 skill 的文件模型逐份檢查，找到四個錯配（詳見「一次文件鏈盤點的四個錯配」段）。&lt;strong>限制&lt;/strong>：盤點對象是一套 skill 的文件模型設計、不是在實際專案量測漂移發生率；「必然漂移」的必然性繼承自 Brooks 的論證與站內個案，樣本都是「有紀律的團隊仍然漂移」、對紀律極端嚴格的組織是否例外沒有資料。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>文件會不會漂移，由「同步期待」與「守護機制」是否匹配決定，不由撰寫紀律決定。&lt;/strong> 同步是一種對執行者當下任務沒有收益的工作——改程式的人當下的目標是讓程式對，回頭改另一份文件對這個目標零貢獻，收益全落在日後的讀者身上。收益結構決定了它不會自發發生；靠紀律撐的同步，撐到第一個 deadline 為止。&lt;/p>
&lt;p>機制的判準是兩件事：&lt;strong>觸發綁在不可跳過的動作點、且過期當下會被發現。&lt;/strong> 這條判準把兩個邊緣情境安放好——PR checklist 綁在合併 gate 上是弱機制：觸發對了、驗證仍靠人，效力取決於那格能不能被敷衍勾掉；每週被讀者消費的 roadmap 自帶弱機制：過期下週就被發現，同步對寫的人有當下收益、不落在「零收益」的前提裡——「靠習慣維持多年」的反例多半屬於這類，它們不是紀律戰勝了收益結構，是消費頻率把機制藏在裡面。&lt;/p>
&lt;p>修法是把每份文件明確分到三級之一、讓期待與機制對齊——「更勤勞地同步」不在選項裡：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>級別&lt;/th>
 &lt;th>同步期待&lt;/th>
 &lt;th>必要條件&lt;/th>
 &lt;th>例&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>活文件&lt;/td>
 &lt;td>永遠反映現狀&lt;/td>
 &lt;td>有機制守著——會紅的測試、編譯器、CI 比對腳本、lint&lt;/td>
 &lt;td>測試、型別、有覆蓋檢核腳本的規格&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>scaffold（鷹架，一次性支撐物）&lt;/td>
 &lt;td>只在被消費的那一刻正確，消費後即過期&lt;/td>
 &lt;td>標記一次性身分與消費時點，過期後不得被當權威引用&lt;/td>
 &lt;td>設計骨架、需求種子包、交接摘要&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>append-only 記錄&lt;/td>
 &lt;td>記錄寫下當時的事實，永不回改&lt;/td>
 &lt;td>標明時點，讀者知道它是史料不是現狀&lt;/td>
 &lt;td>決策記錄、工作日誌、事後檢討&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>漂移只發生在錯配格&lt;/strong>（同步期待與守護機制兩軸交出來的那一格）：被期待最新、卻沒有任何機制守著的文件。三級都不落的文件就是 Brooks 說的那種——起初有人勤勞地同步、落差出現後放棄、最後留著一份看起來像權威的錯誤資訊。分級的動作本身就是修法：一份沒有機制的「活文件」，出路只有兩條——給它機制（寫比對腳本掛進 CI；或更徹底、改為&lt;strong>從權威載體生成&lt;/strong>：副本變成 build 產物、同步義務直接消失，doctest 與 OpenAPI 文件生成正是 Brooks「併入程式」的直系後代），或誠實降級（標成 scaffold 或記錄）。&lt;/p>
&lt;p>三級裡最容易被誤讀的是 append-only 記錄：它看起來沒有機制，其實是唯一不需要機制的一級——「永不回改」撐得住，因為回改一份日誌對任何人的當下任務同樣零收益，沒有力量推著它變動；時點標記讓讀者自帶折舊，讀兩年前的決策記錄不會期待它反映今天。它的陷阱在被當成現狀讀：工作日誌裡「目前架構是 X」寫下時為真、三次重構後字面依舊——這不是漂移，是讀者用錯了級別，修法是在入口標明「本目錄是時序史料」。&lt;/p>
&lt;p>分級處理的是單份文件；跨文件的第二條原則跟著出來：&lt;strong>每類資訊指定唯一的權威載體，其他位置引用、不複製。&lt;/strong> 複製出去的每一份都是一個新的同步義務，而沒有機制守著的義務不會被履行。行為的權威載體是測試——它是唯一改壞當下會發聲的那份，這正是 Brooks「把文件併入程式」在有測試文化下的現代形式；介面的權威載體是程式碼簽名；「為什麼」拆兩半——repo 內的決策脈絡在需求文件、repo 外的事實（法規、外部契約）在註解。&lt;/p>
&lt;p>測試的權威帶兩個限定。它是&lt;strong>現狀的權威、不是正確性的權威&lt;/strong>——意圖的權威在需求文件，測試可能鎖住錯誤的實作，兩個權威分歧時是需求裁決、不是文件同步問題，修測試還是修需求由人決定。且權威限於測試覆蓋的範圍——未覆蓋的行為，權威回到意圖文件，而那條界線要可見（覆蓋映射的 gap 標記就是界線）。&lt;/p>
&lt;hr>
&lt;h2 id="一次文件鏈盤點的四個錯配">一次文件鏈盤點的四個錯配&lt;/h2>
&lt;p>對一套 TDD 流程（proposal → spec → use case → 種子包 → 設計文件 → 測試 → 追溯表）逐份套用分級，錯配長這樣：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>同一份行為敘述存在四處&lt;/strong>：UC 場景步驟被完整複製進 ticket 的種子包（開工時塞進任務單的需求場景副本）、再進設計文件的場景區段、最後進測試。UC 修訂後、中間兩份沒有機制跟上。判定：種子包與設計文件的場景區段是 scaffold、只在階段交接那一刻正確，但沒有被標記，讀起來像活文件。&lt;/li>
&lt;li>&lt;strong>追溯表的狀態欄是宣稱&lt;/strong>：UC 場景與測試的映射表用人工把 &lt;code>gap&lt;/code> 改成 &lt;code>covered&lt;/code>，而既有的收尾掃描只查 &lt;code>gap&lt;/code>、不驗 &lt;code>covered&lt;/code> 的真實性——假 covered 與真 covered 在表上不可區分。判定：被當活文件、機制只有半套；出路是比對腳本連 covered 一起驗，或把狀態欄降級為盤點當天的快照記錄。&lt;/li>
&lt;li>&lt;strong>設計文件沒有生命週期&lt;/strong>：規格設計階段產出的功能規格放在 ticket 目錄，實作完成後它長得像權威規格，實際上從實作階段的每個決策起就開始漂移。判定：它是 scaffold，消費者是測試設計階段；消費完成後要標記 archived，權威轉移到測試與程式碼。&lt;/li>
&lt;li>&lt;strong>回補機制是單向的&lt;/strong>：測試階段發現 UC 沒寫的邊界、回補進 UC——但已經複製出去的舊副本不在回補範圍，回補反而擴大了 UC 與副本的落差。判定：回補只該修權威載體；這正是「引用不複製」的理由——副本不存在，回補就不需要第二站。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;p>&lt;strong>割裂&lt;/strong>：讀者要跨多份文件才能拼出一個行為的全貌，而各份的版本不一致時，他不知道信哪份。&lt;strong>重複&lt;/strong>：同一資訊多處出現、每處都被期待維護，漂移之後「哪份是對的」變成考古題。&lt;strong>錯誤註解比沒有註解更糟&lt;/strong>：漂移過的文件仍然帶著權威的外觀，讀者依它行動——這與宣稱約束的註解讓 reviewer 以為有人在守是同一個機制，宣稱本身消滅了查證動機。&lt;/p>
&lt;p>論述基礎第一項的那次漂移，走完整條路長這樣。抽出操作文件是為了讓執行有現成步驟可照——當初的理由成立；卡片開始修訂之後，兩份各自讀起來都完整，審卡片的人讀卡片、審稿件的人讀操作文件，沒有任何檢查把兩份並排，修正一次都沒傳到執行端。浮出水面時規則的套用率是零，第一診斷是「自審失效」、修法方向指向加強檢查——而 reviewer 拿的仍是舊文件，審查通過反而回頭確認「規則已落實」，讓漂移更難被發現。誤診的分辨動作與同步修法見 &lt;a href="../principle-operationalization-drifts/">#245&lt;/a>。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../protective-comment-signals-missing-enforcement/">#253 寫註解的動機是怕被改壞時，要處理的是那個約束&lt;/a>&lt;/strong>：同構的上一層。#253 處理單行註解——不參與執行、改壞不發聲、防護需求要交給會發聲的機制；本卡把同一個判準抬到文件層：不被機制守著的文件、同步需求同樣送錯了窗口。「行為的權威載體是測試」直接沿用 #253 的落點選擇。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../principle-operationalization-drifts/">#245 原則層與操作層是兩份會漂移的副本，而漂移只往一個方向&lt;/a>&lt;/strong>：本卡三級分類的實測實例。抽象卡片與操作文件是兩份都被期待最新的活文件、之間沒有機制——正是錯配格；#245 的修法（反向核對、版本號對齊）是給既有雙副本補機制，本卡補上游選項：一開始就不要有第二份被期待最新的副本。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../annotation-with-no-local-payoff-needs-a-trigger/">#249 對當下段落沒有收益的標註不會自發發生&lt;/a>&lt;/strong>：本卡「不由紀律決定」的機制來源。同步另一份文件對改程式的人當下零收益，收益結構決定它不會自發發生——分級是把「期待它發生」改成「不期待它發生、或讓機制代勞」。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../lint-scope-must-be-explicit-fact/">#221 檢查規則的作用域要顯式列舉&lt;/a>&lt;/strong>：追溯表錯配的形態來源。狀態欄寫 &lt;code>covered&lt;/code> 與實際有測試是兩件事，宣稱與現狀在表上不可區分——把宣稱當成現狀讀，正是零 error 與未涵蓋同訊號的文件版。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../current-content-needs-a-carrier-that-reaches-readers/">#268 要維持當期的內容，只能放在更新到得了讀者的載體上&lt;/a>&lt;/strong>：本卡的適用邊界。三級分類預設載體可以被補機制（自家的文件、掛得上 CI 的東西），而載體改完之後到不到得了讀者是更前面的一問：印出來的書、發布後不再送達的文件、別人維護而你只能引用的內容，讀者手上那一份不因為出了新版而改變，「給機制」這條出路在那裡不存在。「誠實降級」在那裡也只解決一半——降級之後那個主題無人承接，讀者要的答案落地沒有著落，所以 #268 在降級之外多要求一步：把具體值路由到到得了讀者的載體。順序是先答那兩問，答案落在「可更新」那一格時才回來分級。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>徵兆&lt;/th>
 &lt;th>該做的行動&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>流程新增一份文件產出、說明裡有「保持同步」「記得更新」字樣&lt;/td>
 &lt;td>問守護機制是什麼；指不出來就分級——給機制或降級&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>同一段敘述（場景、規格、清單）出現在兩份以上文件&lt;/td>
 &lt;td>指定權威載體、其他處改引用；scaffold 副本標記消費時點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>映射表、狀態欄、覆蓋表由人工維護&lt;/td>
 &lt;td>寫比對腳本掛進 CI 或收尾階段；做不到就標成快照、註明盤點日期&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>一份階段性產出在流程結束後仍留在原地、沒有標記&lt;/td>
 &lt;td>補生命週期：誰消費它、消費完成後標 archived、權威轉移到哪&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>發現文件與現狀不符、第一反應是「補一條同步規則」&lt;/td>
 &lt;td>先分級——錯配格的解是機制或降級，加規則是在期待紀律做機制的工作&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="適用範圍與邊界">適用範圍與邊界&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>適用&lt;/strong>：開發流程內部的文件鏈（需求、規格、設計、測試、追溯、註解）；審查一套流程或 skill 的文件模型。&lt;/li>
&lt;li>&lt;strong>邊界&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>對外發布的文件&lt;/strong>（使用者手冊、公開 API 文件）：讀者拿不到 repo 內的權威載體，副本無法避免；此時同步要當成發布流程的一個步驟來設計（發布時從權威載體生成），不適用「不複製」。&lt;/li>
&lt;li>&lt;strong>法規或稽核要求的副本&lt;/strong>：保存義務來自 repo 外，副本的存在本身是需求；標明版本與時點即可。&lt;/li>
&lt;li>&lt;strong>定期重編的文件&lt;/strong>（季度更新的 onboarding 指南）：不是第四級，是組合——append-only 快照的序列、加上行事曆觸發的重編排程；排程就是它的機制，逾期未重編即降為史料。&lt;/li>
&lt;li>&lt;strong>沒有測試文化的專案&lt;/strong>：「行為的權威載體是測試」預設測試存在且自動跑；前提不成立時，文件可能就是唯一載體，先讓機制存在再談降級。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>這則檢討處理開發流程的文件鏈設計：一個功能從需求到實作，資訊會流經多份文件——proposal、spec、use case、設計文件、追溯表、測試、註解、工作日誌。Brooks 在《人月神話》（The Mythical Man-Month）處理過這個問題，結論是同時維護多份文件不可能持續：文件之間的進度必然產生落差，而有落差的文件最終完全沒有人更新；他給的方向是把文件盡可能併入程式自身（self-documenting programs）、減少獨立文件的數量。Brooks 的直接對象是程式的文件（散文描述與流程圖、對照原始程式）；把同一條機制推廣到需求到實作的整條文件鏈，是本卡的延伸。</p>
<p>本卡把這個論點收斂成可操作的判準，論述基礎有三塊。<strong>站內的既有實測</strong>：一條規則的抽象卡片修過三次、執行端讀的操作文件停在第一版（原則層與操作層的單向漂移）；一行宣稱約束的註解在測試已存在時是沒有保護力的副本；測試假後端檔頭的「已模擬行為」彙整清單，沒有任何機制守著它與實際處理邏輯同步、終將過期（<a href="/blog/testing/05-test-design-judgment/test-comment-and-naming-discipline/" data-link-title="測試註解與命名紀律" data-link-desc="測試註解寫什麼、名稱與 reason 怎麼收斂、分析詞彙與開發過程該不該進程式碼 — 判斷測試文字去留的紀律">測試註解與命名紀律</a>）。<strong>一次文件鏈盤點</strong>：對一套 TDD 流程 skill 的文件模型逐份檢查，找到四個錯配（詳見「一次文件鏈盤點的四個錯配」段）。<strong>限制</strong>：盤點對象是一套 skill 的文件模型設計、不是在實際專案量測漂移發生率；「必然漂移」的必然性繼承自 Brooks 的論證與站內個案，樣本都是「有紀律的團隊仍然漂移」、對紀律極端嚴格的組織是否例外沒有資料。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p><strong>文件會不會漂移，由「同步期待」與「守護機制」是否匹配決定，不由撰寫紀律決定。</strong> 同步是一種對執行者當下任務沒有收益的工作——改程式的人當下的目標是讓程式對，回頭改另一份文件對這個目標零貢獻，收益全落在日後的讀者身上。收益結構決定了它不會自發發生；靠紀律撐的同步，撐到第一個 deadline 為止。</p>
<p>機制的判準是兩件事：<strong>觸發綁在不可跳過的動作點、且過期當下會被發現。</strong> 這條判準把兩個邊緣情境安放好——PR checklist 綁在合併 gate 上是弱機制：觸發對了、驗證仍靠人，效力取決於那格能不能被敷衍勾掉；每週被讀者消費的 roadmap 自帶弱機制：過期下週就被發現，同步對寫的人有當下收益、不落在「零收益」的前提裡——「靠習慣維持多年」的反例多半屬於這類，它們不是紀律戰勝了收益結構，是消費頻率把機制藏在裡面。</p>
<p>修法是把每份文件明確分到三級之一、讓期待與機制對齊——「更勤勞地同步」不在選項裡：</p>
<table>
  <thead>
      <tr>
          <th>級別</th>
          <th>同步期待</th>
          <th>必要條件</th>
          <th>例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>活文件</td>
          <td>永遠反映現狀</td>
          <td>有機制守著——會紅的測試、編譯器、CI 比對腳本、lint</td>
          <td>測試、型別、有覆蓋檢核腳本的規格</td>
      </tr>
      <tr>
          <td>scaffold（鷹架，一次性支撐物）</td>
          <td>只在被消費的那一刻正確，消費後即過期</td>
          <td>標記一次性身分與消費時點，過期後不得被當權威引用</td>
          <td>設計骨架、需求種子包、交接摘要</td>
      </tr>
      <tr>
          <td>append-only 記錄</td>
          <td>記錄寫下當時的事實，永不回改</td>
          <td>標明時點，讀者知道它是史料不是現狀</td>
          <td>決策記錄、工作日誌、事後檢討</td>
      </tr>
  </tbody>
</table>
<p><strong>漂移只發生在錯配格</strong>（同步期待與守護機制兩軸交出來的那一格）：被期待最新、卻沒有任何機制守著的文件。三級都不落的文件就是 Brooks 說的那種——起初有人勤勞地同步、落差出現後放棄、最後留著一份看起來像權威的錯誤資訊。分級的動作本身就是修法：一份沒有機制的「活文件」，出路只有兩條——給它機制（寫比對腳本掛進 CI；或更徹底、改為<strong>從權威載體生成</strong>：副本變成 build 產物、同步義務直接消失，doctest 與 OpenAPI 文件生成正是 Brooks「併入程式」的直系後代），或誠實降級（標成 scaffold 或記錄）。</p>
<p>三級裡最容易被誤讀的是 append-only 記錄：它看起來沒有機制，其實是唯一不需要機制的一級——「永不回改」撐得住，因為回改一份日誌對任何人的當下任務同樣零收益，沒有力量推著它變動；時點標記讓讀者自帶折舊，讀兩年前的決策記錄不會期待它反映今天。它的陷阱在被當成現狀讀：工作日誌裡「目前架構是 X」寫下時為真、三次重構後字面依舊——這不是漂移，是讀者用錯了級別，修法是在入口標明「本目錄是時序史料」。</p>
<p>分級處理的是單份文件；跨文件的第二條原則跟著出來：<strong>每類資訊指定唯一的權威載體，其他位置引用、不複製。</strong> 複製出去的每一份都是一個新的同步義務，而沒有機制守著的義務不會被履行。行為的權威載體是測試——它是唯一改壞當下會發聲的那份，這正是 Brooks「把文件併入程式」在有測試文化下的現代形式；介面的權威載體是程式碼簽名；「為什麼」拆兩半——repo 內的決策脈絡在需求文件、repo 外的事實（法規、外部契約）在註解。</p>
<p>測試的權威帶兩個限定。它是<strong>現狀的權威、不是正確性的權威</strong>——意圖的權威在需求文件，測試可能鎖住錯誤的實作，兩個權威分歧時是需求裁決、不是文件同步問題，修測試還是修需求由人決定。且權威限於測試覆蓋的範圍——未覆蓋的行為，權威回到意圖文件，而那條界線要可見（覆蓋映射的 gap 標記就是界線）。</p>
<hr>
<h2 id="一次文件鏈盤點的四個錯配">一次文件鏈盤點的四個錯配</h2>
<p>對一套 TDD 流程（proposal → spec → use case → 種子包 → 設計文件 → 測試 → 追溯表）逐份套用分級，錯配長這樣：</p>
<ol>
<li><strong>同一份行為敘述存在四處</strong>：UC 場景步驟被完整複製進 ticket 的種子包（開工時塞進任務單的需求場景副本）、再進設計文件的場景區段、最後進測試。UC 修訂後、中間兩份沒有機制跟上。判定：種子包與設計文件的場景區段是 scaffold、只在階段交接那一刻正確，但沒有被標記，讀起來像活文件。</li>
<li><strong>追溯表的狀態欄是宣稱</strong>：UC 場景與測試的映射表用人工把 <code>gap</code> 改成 <code>covered</code>，而既有的收尾掃描只查 <code>gap</code>、不驗 <code>covered</code> 的真實性——假 covered 與真 covered 在表上不可區分。判定：被當活文件、機制只有半套；出路是比對腳本連 covered 一起驗，或把狀態欄降級為盤點當天的快照記錄。</li>
<li><strong>設計文件沒有生命週期</strong>：規格設計階段產出的功能規格放在 ticket 目錄，實作完成後它長得像權威規格，實際上從實作階段的每個決策起就開始漂移。判定：它是 scaffold，消費者是測試設計階段；消費完成後要標記 archived，權威轉移到測試與程式碼。</li>
<li><strong>回補機制是單向的</strong>：測試階段發現 UC 沒寫的邊界、回補進 UC——但已經複製出去的舊副本不在回補範圍，回補反而擴大了 UC 與副本的落差。判定：回補只該修權威載體；這正是「引用不複製」的理由——副本不存在，回補就不需要第二站。</li>
</ol>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<p><strong>割裂</strong>：讀者要跨多份文件才能拼出一個行為的全貌，而各份的版本不一致時，他不知道信哪份。<strong>重複</strong>：同一資訊多處出現、每處都被期待維護，漂移之後「哪份是對的」變成考古題。<strong>錯誤註解比沒有註解更糟</strong>：漂移過的文件仍然帶著權威的外觀，讀者依它行動——這與宣稱約束的註解讓 reviewer 以為有人在守是同一個機制，宣稱本身消滅了查證動機。</p>
<p>論述基礎第一項的那次漂移，走完整條路長這樣。抽出操作文件是為了讓執行有現成步驟可照——當初的理由成立；卡片開始修訂之後，兩份各自讀起來都完整，審卡片的人讀卡片、審稿件的人讀操作文件，沒有任何檢查把兩份並排，修正一次都沒傳到執行端。浮出水面時規則的套用率是零，第一診斷是「自審失效」、修法方向指向加強檢查——而 reviewer 拿的仍是舊文件，審查通過反而回頭確認「規則已落實」，讓漂移更難被發現。誤診的分辨動作與同步修法見 <a href="../principle-operationalization-drifts/">#245</a>。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../protective-comment-signals-missing-enforcement/">#253 寫註解的動機是怕被改壞時，要處理的是那個約束</a></strong>：同構的上一層。#253 處理單行註解——不參與執行、改壞不發聲、防護需求要交給會發聲的機制；本卡把同一個判準抬到文件層：不被機制守著的文件、同步需求同樣送錯了窗口。「行為的權威載體是測試」直接沿用 #253 的落點選擇。</li>
<li><strong><a href="../principle-operationalization-drifts/">#245 原則層與操作層是兩份會漂移的副本，而漂移只往一個方向</a></strong>：本卡三級分類的實測實例。抽象卡片與操作文件是兩份都被期待最新的活文件、之間沒有機制——正是錯配格；#245 的修法（反向核對、版本號對齊）是給既有雙副本補機制，本卡補上游選項：一開始就不要有第二份被期待最新的副本。</li>
<li><strong><a href="../annotation-with-no-local-payoff-needs-a-trigger/">#249 對當下段落沒有收益的標註不會自發發生</a></strong>：本卡「不由紀律決定」的機制來源。同步另一份文件對改程式的人當下零收益，收益結構決定它不會自發發生——分級是把「期待它發生」改成「不期待它發生、或讓機制代勞」。</li>
<li><strong><a href="../lint-scope-must-be-explicit-fact/">#221 檢查規則的作用域要顯式列舉</a></strong>：追溯表錯配的形態來源。狀態欄寫 <code>covered</code> 與實際有測試是兩件事，宣稱與現狀在表上不可區分——把宣稱當成現狀讀，正是零 error 與未涵蓋同訊號的文件版。</li>
<li><strong><a href="../current-content-needs-a-carrier-that-reaches-readers/">#268 要維持當期的內容，只能放在更新到得了讀者的載體上</a></strong>：本卡的適用邊界。三級分類預設載體可以被補機制（自家的文件、掛得上 CI 的東西），而載體改完之後到不到得了讀者是更前面的一問：印出來的書、發布後不再送達的文件、別人維護而你只能引用的內容，讀者手上那一份不因為出了新版而改變，「給機制」這條出路在那裡不存在。「誠實降級」在那裡也只解決一半——降級之後那個主題無人承接，讀者要的答案落地沒有著落，所以 #268 在降級之外多要求一步：把具體值路由到到得了讀者的載體。順序是先答那兩問，答案落在「可更新」那一格時才回來分級。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>流程新增一份文件產出、說明裡有「保持同步」「記得更新」字樣</td>
          <td>問守護機制是什麼；指不出來就分級——給機制或降級</td>
      </tr>
      <tr>
          <td>同一段敘述（場景、規格、清單）出現在兩份以上文件</td>
          <td>指定權威載體、其他處改引用；scaffold 副本標記消費時點</td>
      </tr>
      <tr>
          <td>映射表、狀態欄、覆蓋表由人工維護</td>
          <td>寫比對腳本掛進 CI 或收尾階段；做不到就標成快照、註明盤點日期</td>
      </tr>
      <tr>
          <td>一份階段性產出在流程結束後仍留在原地、沒有標記</td>
          <td>補生命週期：誰消費它、消費完成後標 archived、權威轉移到哪</td>
      </tr>
      <tr>
          <td>發現文件與現狀不符、第一反應是「補一條同步規則」</td>
          <td>先分級——錯配格的解是機制或降級，加規則是在期待紀律做機制的工作</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：開發流程內部的文件鏈（需求、規格、設計、測試、追溯、註解）；審查一套流程或 skill 的文件模型。</li>
<li><strong>邊界</strong>：
<ul>
<li><strong>對外發布的文件</strong>（使用者手冊、公開 API 文件）：讀者拿不到 repo 內的權威載體，副本無法避免；此時同步要當成發布流程的一個步驟來設計（發布時從權威載體生成），不適用「不複製」。</li>
<li><strong>法規或稽核要求的副本</strong>：保存義務來自 repo 外，副本的存在本身是需求；標明版本與時點即可。</li>
<li><strong>定期重編的文件</strong>（季度更新的 onboarding 指南）：不是第四級，是組合——append-only 快照的序列、加上行事曆觸發的重編排程；排程就是它的機制，逾期未重編即降為史料。</li>
<li><strong>沒有測試文化的專案</strong>：「行為的權威載體是測試」預設測試存在且自動跑；前提不成立時，文件可能就是唯一載體，先讓機制存在再談降級。</li>
</ul>
</li>
</ul>
]]></content:encoded></item></channel></rss>