原則層與操作層是兩份會漂移的副本,而漂移只往一個方向
論述基礎與限制
本卡從一次多輪審查的第三輪抽出。當時查的是「規則寫下來之後同批稿件仍然犯」,掃到一條規則的套用率是零:九則微案例沒有任何一則做了那條規則要求的動作。
直覺的解釋是自審失效——規則在那裡、寫的人沒照做。實際去查才發現另一件事:那條規則寫在原則卡上,而執行時實際被讀的是另一份操作文件,那一份停在規則被抽出時的第一版,後來卡片修過三次的內容一次都沒有同步過去。套用率零不是因為沒照做,是因為照的是舊版。
回頭比對同一批的其他規則,漂移的分布有規律:與操作文件同時寫下的那幾條都同步了;卡片在後續輪次被修正的那幾條,操作文件全部停在原版。
限制:本卡談的是同一條原則被寫在兩個地方的情形(抽象層與操作層各一份)。單一來源的規則不適用;兩份內容本來就該不同的情形(規格與實作、需求與測試)也不適用——那裡的差異是設計,不是漂移。
核心原則
一條原則同時存在於抽象層與操作層時,兩份是會各自演化的副本,而修正流向單向:抽象層被反覆修改、操作層停在第一次抽出時的版本。 判斷某條規則有沒有漂移,不看抽象層寫了什麼,看執行者實際會讀的那一份寫了什麼。
單向性來自修改成本不對稱。抽象層是討論的焦點,反駁、補條件、改措辭都直接落在它身上,改一段文字就完成。操作層是程序性的,同一條改動要先判斷「它影響哪幾個步驟、插在哪一步之後」,而那個判斷比改文字貴得多。時間壓力下的自然順序因此是先改抽象層、操作層稍後——而「稍後」沒有觸發器。
漂移看不見的原因是兩份各自讀起來都完整。操作層沒有殘缺、沒有內部矛盾、也沒有指向抽象層說「以那邊為準」;它就是一份自洽的舊版本。要看見差異只能把兩份並排逐句比對,而既有的檢查沒有一項在做這件事——審查抽象層的人讀抽象層,審查稿件的人讀操作層。
反模式:把漂移誤診成自審失效
套用率異常低時,兩種成因的表徵一模一樣:規則存在、稿件沒照做。而它們的修法相反。
自審失效的修法是加強檢查——把規則寫進 reviewer 的維度、加一輪掃描、寫進完稿清單。漂移的修法是同步兩份副本。誤診成前者的代價是修法完全無效:加再多輪審查,reviewer 拿的還是那份舊操作文件,掃出來的仍然是「符合舊規則」。而審查通過會反過來確認「規則已經落實」,讓漂移更難被發現。
分辨方式只有一個動作:套用率低到不像疏忽時,先打開執行者實際讀的那一份,確認它寫的與抽象層是不是同一件事。這個動作要排在歸因之前,而不是歸因之後。
修法:改抽象層時同批改操作層,並把「執行者讀哪一份」寫下來
改動的單位是這條原則的所有副本,不是被指出問題的那一份。 審查報告點名的通常是抽象層(因為討論在那裡發生),修完它只完成一半。收尾動作是問「這條原則還寫在哪裡」,逐一同步。
每條原則要記錄它的執行入口。抽象層在文末註明「操作面在哪一份文件的哪一節」,讓下一次修改時目的地是現成的而不必回想。這一步的成本在寫下的當下最低,因為那時剛做完抽出的動作、還記得放在哪。
版本號的粒度要對得上。操作層有版本號時,抽象層的每一次實質修改都該對應一次版本更新;抽象層改了而操作層版本沒動,本身就是漂移的訊號。反過來也成立——操作層的變更紀錄若寫不出「這次同步的是哪一條原則的哪一次修正」,代表同步是憑印象做的。
排定一次反向核對。抽象層的原則累積到一定數量之後,從操作層那一端逐條回查:這一句對應的原則現在長什麼樣。方向要從操作層出發,因為漂移的形態是操作層缺內容,而從抽象層出發只會確認「每一條都有對應段落」。
新內容引用既有文件的某條判準時,把那一段整段讀完並判定以誰為準。 這一條處理的是本卡最高頻的接觸點:寫新內容時回頭在既有文件補一條指向新內容的連結。那個動作只讀既有文件的路由段,不讀它的正文——於是連結對上了、判準沒有被並排過一次,而兩份此刻可能已經在講不同的事。判定的結果只有兩種:以新的為準就同批改舊的,以舊的為準就改新的;兩份都留是漂移的起點,不是折衷。
跟其他原則的關係
- #147 規範化跟自審是兩種認知任務:本卡是它最常見的誤診來源。#147 的形態是規則正確而自審沒抓到,本卡的形態是執行者讀到的規則是舊的;兩者的表徵相同(套用率低)而修法相反(加強檢查 vs 同步副本)。歸因錯了,修法的方向也就錯了。
- #243 要求執行者做判定的規則,要一併規定判定留下什麼痕跡:本卡在它的上游。#243 管規則本身留不留得下痕跡,本卡管規則有沒有傳到執行者手上——規則設計得再好,執行者讀的是舊版就不生效。
- #221 檢查規則的作用域要顯式列舉:兩者都讓「已檢查」失去意義,斷點不同。#221 是規則沒有涵蓋那些檔案,本卡是規則的兩個副本內容不同。共同的處置方向是把涵蓋範圍與版本從隱性變成顯性。
- #44 Single Source of Truth:值的住址只能有一處:本卡是它在「無法只有一處」時的處置。原則與操作化必須各有一份,因為兩者的讀者與用法不同;SSoT 在這裡無法直接套用,能做的是把同步變成有觸發器的動作而不是靠記憶。
- #247 多次局部正確的修法會合成缺陷:同屬「沒有人並排讀」的家族,對象不同——本卡的兩份是同一條原則的兩個副本,那一張的兩處是同一份內容的兩次修改。
- #239 宣告的組合不等於執行的組合:同型的宣告與實際落差,層次不同。#239 是同一個執行者宣告啟用兩件事而只做了一件,本卡是規則在傳遞過程中掉了版本。
- #262 內容超出容器時擴充結構、不壓縮內容:本卡在容器決策裡的位置由它指定——同一概念的多個版本要在選容器出口之前收斂,否則展開會寫出兩套更詳細的版本、連結會把讀者送到用不同語彙描述同一件事的地方。它的第二輪試點裡這一類是最大宗(一章的階段表整張與同模組另一章不相容),而每篇單獨讀都不顯示問題——本卡的漂移在教學內容裡的形態是兩篇平行章節,不只是原則卡與操作文件那一組。
- #263 同一個對象被兩篇各自分解一次時,不相容會長得像互補:機制相反的 sibling,兩者的表徵接近而修法互斥。本卡的兩份有共同起源、差異單向累積、修法是同步;那張卡的兩套是平行發明、從未相同過,同步會把兩份各自完整的分解合成一個兩邊都不像的第三套。誤診的方向可預測——跨篇撞到兩套不一致時,先假設漂移比先假設平行發明省力,因為漂移有現成的修法。
- #256 多份文件必然漂移:同步期待要嘛有機制承接、要嘛明示降級:本卡的上游選項。本卡處理既有雙副本的機制補法(反向核對、版本號對齊、改動單位取所有副本),#256 補上更早的問題——這第二份副本該不該以「被期待最新」的身分存在;能引用就不複製、能降級成一次性 scaffold 就不掛同步期待,雙副本機制是拆不掉時的退位處置。
判讀徵兆
- 一條規則的套用率是零或接近零,而執行者是有能力做到的人。
- 抽象層的文件被修改過多次,而對應的操作文件版本紀錄停在很早的日期。
- 審查報告反覆點名同一條規則沒被遵守,修法每次都是「加強檢查」。
- 抽象層寫得出「這條原則的操作面在哪」,操作層寫不出「這一段對應哪一條原則」——單向的可追溯性代表同步只往一個方向做過。
- 把兩份並排讀是從來沒有人做過的動作,而且沒有任何檢查要求它。
- 新內容宣告「這件事的分工見某份既有文件」,而寫的人不知道那份文件對應段落現在寫了什麼——回指是路由層的動作,判準層沒有被並排。
- 兩份的成對關係跨了文件類型(概念卡與操作章、規格與教學),因此不會被當成「同一份東西的兩個副本」而納入任何同步習慣。