<?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/%E5%AF%AB%E4%BD%9C/</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>Mon, 29 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E5%AF%AB%E4%BD%9C/index.xml" rel="self" type="application/rss+xml"/><item><title>正向改寫要保留對照論據、不能空降結論</title><link>https://tarrragon.github.io/blog/report/positive-rewrite-preserves-contrast/</link><pubDate>Wed, 29 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/positive-rewrite-preserves-contrast/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>「X、不是 Y」這個句型在做兩件事：給結論 X、排除讀者直覺會想到的 Y。&lt;/strong> 兩者是同一個推理單元、一起出現才完整。為了滿足「正向陳述優先」而把 Y 直接刪掉、剩下的 X 就失去 contrast、變成沒依據的空降斷言。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>改寫方式&lt;/th>
 &lt;th>結論是否站得住&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>保留「X、不是 Y」&lt;/td>
 &lt;td>站得住、Y 提供 contrast、讀者知道 X 排除了什麼可能性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>補理由：「X、因為 …」&lt;/td>
 &lt;td>站得住、用 reasoning 取代 contrast&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>改對照表：A 欄列 X / B 欄列 Y&lt;/td>
 &lt;td>站得住、把對照升級成結構化呈現&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>直接刪 Y、只剩 X&lt;/td>
 &lt;td>不站得住、X 變成空降斷言、讀者無法判斷依據&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>補一個更弱的 hint（「Y 只是表象」）&lt;/td>
 &lt;td>不站得住、hint 沒解釋為什麼是表象、等同沒寫&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>寫作規範要求「正向陳述優先」、AI 或作者批量改寫舊文時、為了滿足 grep &lt;code>不是 / 不要 / 避免&lt;/code> 等掃描規則、會把句子裡的否定詞機械式刪掉。但很多否定詞承擔的是 &lt;strong>contrast 角色&lt;/strong>、不是冗餘 — 抽掉之後句子在語法上正向了、但語意上失去了推理依據。&lt;/p>
&lt;p>具體例子（本 blog &lt;code>compositional-writing&lt;/code> skill 的修正過程）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">原文：拆分依據是**認知負擔與情境匹配度**、不是行數。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">改 1：拆分依據是**認知負擔與情境匹配度**（行數只是表象）。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">改 2：拆分依據是**認知負擔與情境匹配度**。&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>原文：給結論（認知負擔）+ 排除讀者直覺（行數）。Y = 行數是讀者最容易想到的替代答案、明確排除掉這條路才有意義。&lt;/li>
&lt;li>改 1：把「不是 Y」軟化成「Y 只是表象」、但&lt;strong>沒解釋為什麼是表象&lt;/strong>。讀者讀完不知道「行數為什麼不算依據」、結論依然空降、只是包裝成正向句。&lt;/li>
&lt;li>改 2：直接刪、結論完全失去 contrast。&lt;/li>
&lt;/ul>
&lt;p>兩個改法都比原文差。&lt;/p>
&lt;hr>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>正向改寫時、先判斷被刪掉的 Y 是哪一類：&lt;/p>
&lt;h3 id="y-是讀者直覺會想到的替代方案--保留-contrast">Y 是讀者直覺會想到的替代方案 → 保留 contrast&lt;/h3>
&lt;p>讀者第一直覺會想到 Y、只給 X 不夠。處理方式有三：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>保留「X、不是 Y」原句&lt;/strong>（規則六精神：反例段落要有正向錨點、但反例本身仍存在）— 這不違反「正向陳述優先」、因為「正向陳述優先」要的是「主句承載結論、反例只做對照」、不是「全段沒有否定詞」。「X、不是 Y」這個句型主句仍是 X（正向陳述）、Y 是子句裡的 contrast、結構上符合規範&lt;/li>
&lt;li>&lt;strong>補解釋&lt;/strong>：「X、因為 [推理]」 — 用 reasoning 接管 contrast 的角色&lt;/li>
&lt;li>&lt;strong>升級成對照表&lt;/strong>：兩欄並列 X 跟 Y、讓 contrast 變結構化呈現、不靠句法&lt;/li>
&lt;/ol>
&lt;h3 id="y-是冗餘否定讀者不會想到-y--直接刪">Y 是冗餘否定（讀者不會想到 Y） → 直接刪&lt;/h3>
&lt;p>例：「使用 LRU cache、不是普通 dict」— 若上下文沒有人會把 dict 當預設、Y 是冗餘、刪掉沒損失。&lt;/p>
&lt;p>判別問題：「&lt;strong>讀者讀到 X 之前、心裡最可能想到的答案是 Y 嗎？&lt;/strong> 是 → 保留 contrast。否 → 安全刪。」&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="結論變空降斷言讀者無法驗證">結論變空降斷言、讀者無法驗證&lt;/h3>
&lt;p>「行數只是表象」這種句子、讀者讀完只能選兩條路：&lt;/p>
&lt;ul>
&lt;li>全盤接受（迷信權威）&lt;/li>
&lt;li>自己腦補理由（每個讀者腦補不同、原則無法統一傳遞）&lt;/li>
&lt;/ul>
&lt;p>兩條都讓「教學」失效 — 教學的目的是讓讀者拿到 reasoning、能套用到新情境、不是讓讀者背規則。&lt;/p>
&lt;h3 id="規則崩潰壓力下會回退到刪掉的-y">規則崩潰：壓力下會回退到刪掉的 Y&lt;/h3>
&lt;p>機會成本語氣的核心 reasoning 是「絕對主義教讀者規則（壓力下會忘）、機會成本教讀者思考方式」。空降斷言是更糟的「規則」— 連「為什麼是規則」都沒給、讀者壓力下完全無錨點、會回退到自己的直覺（也就是被刪掉的 Y）。&lt;/p>
&lt;h3 id="批量改寫無法被-review">批量改寫無法被 review&lt;/h3>
&lt;p>改寫成「（Y 只是表象）」「（Y 是次級訊號）」這類軟化措辭時、表面看起來完成正向化、實際上把問題藏起來 — 規範掃描器（grep &lt;code>不是&lt;/code>）不再 catch、人類 reviewer 也容易放過、議題在文章裡持續腐爛。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關&lt;/a>&lt;/strong>：本卡是 #67 在「寫作規範執行」層的具體案例。批量正向化時、最便利的做法（grep + 機械刪否定詞）跟意圖對齊（保留推理鍊）反向 — 越容易執行、越容易產出空降斷言。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精修&lt;/a>&lt;/strong>：本卡是 #82 在「寫作規則」層的同形 pattern。grep &lt;code>不是 / 不要&lt;/code> 是字面層攔截、看不到那個「不是」承擔的是 contrast 還是冗餘 — 需要 behavioral pass（讀者能否驗證結論）。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../writing-multi-pass-review/">#83 寫作的 multi-pass review&lt;/a>&lt;/strong>：本卡補強 #83 的 frame 設計 — 「正向陳述」這輪掃完之後、要再加一輪「結論可驗證性」掃描、確認被改的句子仍然有推理依據。&lt;/li>
&lt;li>&lt;strong>&lt;code>compositional-writing&lt;/code> 規則六（反例段落用正向陳述）&lt;/strong>：規則六說「反例段落要有正向概念當錨點」、本卡補規則六沒覆蓋的反向 case — &lt;strong>正向句也可能因為刪掉對照而失去依據&lt;/strong>。兩條互補：規則六防止「只有反例沒有錨點」、本卡防止「只有錨點沒有對照」。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>當你寫下或審閱以下句型時、停下來檢查：&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>「X、不是 Y」這個句型在做兩件事：給結論 X、排除讀者直覺會想到的 Y。</strong> 兩者是同一個推理單元、一起出現才完整。為了滿足「正向陳述優先」而把 Y 直接刪掉、剩下的 X 就失去 contrast、變成沒依據的空降斷言。</p>
<table>
  <thead>
      <tr>
          <th>改寫方式</th>
          <th>結論是否站得住</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>保留「X、不是 Y」</td>
          <td>站得住、Y 提供 contrast、讀者知道 X 排除了什麼可能性</td>
      </tr>
      <tr>
          <td>補理由：「X、因為 …」</td>
          <td>站得住、用 reasoning 取代 contrast</td>
      </tr>
      <tr>
          <td>改對照表：A 欄列 X / B 欄列 Y</td>
          <td>站得住、把對照升級成結構化呈現</td>
      </tr>
      <tr>
          <td>直接刪 Y、只剩 X</td>
          <td>不站得住、X 變成空降斷言、讀者無法判斷依據</td>
      </tr>
      <tr>
          <td>補一個更弱的 hint（「Y 只是表象」）</td>
          <td>不站得住、hint 沒解釋為什麼是表象、等同沒寫</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="情境">情境</h2>
<p>寫作規範要求「正向陳述優先」、AI 或作者批量改寫舊文時、為了滿足 grep <code>不是 / 不要 / 避免</code> 等掃描規則、會把句子裡的否定詞機械式刪掉。但很多否定詞承擔的是 <strong>contrast 角色</strong>、不是冗餘 — 抽掉之後句子在語法上正向了、但語意上失去了推理依據。</p>
<p>具體例子（本 blog <code>compositional-writing</code> skill 的修正過程）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">原文：拆分依據是**認知負擔與情境匹配度**、不是行數。
</span></span><span class="line"><span class="ln">2</span><span class="cl">改 1：拆分依據是**認知負擔與情境匹配度**（行數只是表象）。
</span></span><span class="line"><span class="ln">3</span><span class="cl">改 2：拆分依據是**認知負擔與情境匹配度**。</span></span></code></pre></div><ul>
<li>原文：給結論（認知負擔）+ 排除讀者直覺（行數）。Y = 行數是讀者最容易想到的替代答案、明確排除掉這條路才有意義。</li>
<li>改 1：把「不是 Y」軟化成「Y 只是表象」、但<strong>沒解釋為什麼是表象</strong>。讀者讀完不知道「行數為什麼不算依據」、結論依然空降、只是包裝成正向句。</li>
<li>改 2：直接刪、結論完全失去 contrast。</li>
</ul>
<p>兩個改法都比原文差。</p>
<hr>
<h2 id="理想做法">理想做法</h2>
<p>正向改寫時、先判斷被刪掉的 Y 是哪一類：</p>
<h3 id="y-是讀者直覺會想到的替代方案--保留-contrast">Y 是讀者直覺會想到的替代方案 → 保留 contrast</h3>
<p>讀者第一直覺會想到 Y、只給 X 不夠。處理方式有三：</p>
<ol>
<li><strong>保留「X、不是 Y」原句</strong>（規則六精神：反例段落要有正向錨點、但反例本身仍存在）— 這不違反「正向陳述優先」、因為「正向陳述優先」要的是「主句承載結論、反例只做對照」、不是「全段沒有否定詞」。「X、不是 Y」這個句型主句仍是 X（正向陳述）、Y 是子句裡的 contrast、結構上符合規範</li>
<li><strong>補解釋</strong>：「X、因為 [推理]」 — 用 reasoning 接管 contrast 的角色</li>
<li><strong>升級成對照表</strong>：兩欄並列 X 跟 Y、讓 contrast 變結構化呈現、不靠句法</li>
</ol>
<h3 id="y-是冗餘否定讀者不會想到-y--直接刪">Y 是冗餘否定（讀者不會想到 Y） → 直接刪</h3>
<p>例：「使用 LRU cache、不是普通 dict」— 若上下文沒有人會把 dict 當預設、Y 是冗餘、刪掉沒損失。</p>
<p>判別問題：「<strong>讀者讀到 X 之前、心裡最可能想到的答案是 Y 嗎？</strong> 是 → 保留 contrast。否 → 安全刪。」</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="結論變空降斷言讀者無法驗證">結論變空降斷言、讀者無法驗證</h3>
<p>「行數只是表象」這種句子、讀者讀完只能選兩條路：</p>
<ul>
<li>全盤接受（迷信權威）</li>
<li>自己腦補理由（每個讀者腦補不同、原則無法統一傳遞）</li>
</ul>
<p>兩條都讓「教學」失效 — 教學的目的是讓讀者拿到 reasoning、能套用到新情境、不是讓讀者背規則。</p>
<h3 id="規則崩潰壓力下會回退到刪掉的-y">規則崩潰：壓力下會回退到刪掉的 Y</h3>
<p>機會成本語氣的核心 reasoning 是「絕對主義教讀者規則（壓力下會忘）、機會成本教讀者思考方式」。空降斷言是更糟的「規則」— 連「為什麼是規則」都沒給、讀者壓力下完全無錨點、會回退到自己的直覺（也就是被刪掉的 Y）。</p>
<h3 id="批量改寫無法被-review">批量改寫無法被 review</h3>
<p>改寫成「（Y 只是表象）」「（Y 是次級訊號）」這類軟化措辭時、表面看起來完成正向化、實際上把問題藏起來 — 規範掃描器（grep <code>不是</code>）不再 catch、人類 reviewer 也容易放過、議題在文章裡持續腐爛。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></strong>：本卡是 #67 在「寫作規範執行」層的具體案例。批量正向化時、最便利的做法（grep + 機械刪否定詞）跟意圖對齊（保留推理鍊）反向 — 越容易執行、越容易產出空降斷言。</li>
<li><strong><a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精修</a></strong>：本卡是 #82 在「寫作規則」層的同形 pattern。grep <code>不是 / 不要</code> 是字面層攔截、看不到那個「不是」承擔的是 contrast 還是冗餘 — 需要 behavioral pass（讀者能否驗證結論）。</li>
<li><strong><a href="../writing-multi-pass-review/">#83 寫作的 multi-pass review</a></strong>：本卡補強 #83 的 frame 設計 — 「正向陳述」這輪掃完之後、要再加一輪「結論可驗證性」掃描、確認被改的句子仍然有推理依據。</li>
<li><strong><code>compositional-writing</code> 規則六（反例段落用正向陳述）</strong>：規則六說「反例段落要有正向概念當錨點」、本卡補規則六沒覆蓋的反向 case — <strong>正向句也可能因為刪掉對照而失去依據</strong>。兩條互補：規則六防止「只有反例沒有錨點」、本卡防止「只有錨點沒有對照」。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>當你寫下或審閱以下句型時、停下來檢查：</p>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「X、Y 只是表象 / 次級訊號 / 不重要」</td>
          <td>「Y 只是 …」沒展開原因 = 把斷言用副詞包裝、仍是空降</td>
      </tr>
      <tr>
          <td>「X」單句結論、上下文沒有對照表 / reasoning / 例子</td>
          <td>結論失去支撐、讀者無法判斷為何成立</td>
      </tr>
      <tr>
          <td>改寫前句子是「X、不是 Y」、改寫後 Y 消失</td>
          <td>檢查 Y 是否承擔 contrast、是 → 補回或升級結構化呈現</td>
      </tr>
      <tr>
          <td>Reviewer 讀完問「為什麼？」</td>
          <td>讀者沒拿到 reasoning、結論是空降</td>
      </tr>
      <tr>
          <td>自己解釋給別人聽時、會自然說「不是 Y、是 X」</td>
          <td>口語會自動補上的 contrast、文字版被機械刪掉了</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：寫作規範執行（規則化掃描 → 批量改寫）、AI 輔助寫作的 review、知識卡片 / 教學文章的論證段落</li>
<li><strong>不適用</strong>：純 reference 型內容（API 文件、規格表）— 這類內容讀者只查不推理、contrast 不重要</li>
<li><strong>邊界</strong>：「保留 contrast」≠「保留所有否定詞」— 冗餘否定（讀者不會想到的 Y）仍該刪、判別標準是「讀者直覺會不會想到 Y」</li>
</ul>
]]></content:encoded></item><item><title>Multi-pass review 的 scope 要蓋『同類風險區』、不是『改動區』</title><link>https://tarrragon.github.io/blog/report/multi-pass-scope-must-cover-risk-zone/</link><pubDate>Wed, 29 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/multi-pass-scope-must-cover-risk-zone/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>Multi-pass review 的 scope 由『同類風險區』決定、不是『我改過的檔』。&lt;/strong> 跑某條原則的 pass（例如「結論可驗證性」）、scope 就是「所有可能違反該原則的檔」、不是「我這次改了的檔」。後者是執行便利選擇、不是 review scope 的合法依據 — 同一原則違反通常分布在整個 corpus、改動區只佔小比例。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Scope 定義方式&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>整個 corpus 既有的同類違規（佔多數）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「同類風險的內容範圍」&lt;/td>
 &lt;td>該原則在整個 corpus 的所有違規&lt;/td>
 &lt;td>無 — 這就是該原則 review 的合法 scope&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>判別問題：「&lt;strong>這次 pass 用的 frame、適用範圍是哪些檔？我的 scope 涵蓋了那個範圍嗎？&lt;/strong>」答案是「沒有、我只掃了改動區」就需要擴大 scope。&lt;/p>
&lt;hr>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>寫了一條新原則卡片（例：#94 結論可驗證性）後、要套回既有寫作做 multi-pass review。預設行為是「掃我這次改過的檔」、原因：&lt;/p>
&lt;ul>
&lt;li>改動區是當下 working memory 裡的內容、便利&lt;/li>
&lt;li>改動區 diff 短、容易跑完&lt;/li>
&lt;li>改動區是「我剛動過的、所以可能有違規」的直覺對象&lt;/li>
&lt;/ul>
&lt;p>這三個理由都是&lt;strong>執行便利&lt;/strong>、不是「review scope 的合法依據」。新原則套回既有 corpus 時、違規通常已經存在於沒被改動的部分（因為原則之前不存在、整個 corpus 都沒按該原則寫過）。只掃改動區會 systematic miss 大部分違規。&lt;/p>
&lt;p>具體 case：本 blog &lt;code>compositional-writing&lt;/code> skill 的負向表述清理：&lt;/p>
&lt;ol>
&lt;li>寫 #94 結論可驗證性原則（contrast 該保留還是該刪的判別）&lt;/li>
&lt;li>Multi-pass 跑 6 輪、scope 設為「我改過的 SKILL.md / writing-articles.md / #94 卡片本身」&lt;/li>
&lt;li>第二天使用者讀 references/writing-prompts.md、發現「Prompt 的『原子單位』不是『一句話』、而是『一個可被驗收的任務』」就是 #94 該抓的 case&lt;/li>
&lt;li>該違規分布廣度：scan 整個 references/ 目錄、相同句型違規共 4 處（writing-prompts / writing-logs / designing-fields / managing-article-collections）、僅 0 處在我改動區內&lt;/li>
&lt;/ol>
&lt;p>我的 multi-pass 設計把 4 處違規 100% 漏掉、使用者用肉眼讀就抓到。&lt;/p>
&lt;hr>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="第一步定義原則的適用範圍">第一步：定義原則的「適用範圍」&lt;/h3>
&lt;p>寫一條新原則時、明確標註該原則適用於哪些檔 / section。例：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>原則&lt;/th>
 &lt;th>適用範圍&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>#94 結論可驗證性&lt;/td>
 &lt;td>所有教學 / 知識卡 / 規範文件的論證段落&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>規則五 最重要的話優先說&lt;/td>
 &lt;td>所有有「核心命題」「重點」段落的文件&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Severity 判準對齊分流目的&lt;/td>
 &lt;td>所有定義 severity 的 logging / monitoring 文件&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="第二步pass-scope--適用範圍--待-review-corpus">第二步：Pass scope = 適用範圍 ∩ 待 review corpus&lt;/h3>
&lt;p>跑該原則的 pass 時、scope 是「該原則的適用範圍」交集「目前要 review 的 corpus」、跟「我改過哪些檔」完全無關。&lt;/p>
&lt;p>對 compositional-writing skill 而言：跑 #94 pass 的合法 scope 是 &lt;code>.claude/skills/compositional-writing/**/*.md&lt;/code> 全部、不是「我這次 commit 動到的 5 個檔」。&lt;/p>
&lt;h3 id="第三步用-grep-把同類風險區找出來">第三步：用 grep 把同類風險區找出來&lt;/h3>
&lt;p>同類風險常有結構性 signature（句型、詞彙、模式）、可用 grep 把適用範圍縮到具體行。例：&lt;/p>
&lt;ul>
&lt;li>#94：grep &lt;code>不是.*而是\|不是.*是\|只是表象\|只是次級訊號&lt;/code> → 候選行&lt;/li>
&lt;li>規則五：grep &lt;code>^[^*].*。.*它&lt;/code> → 「X。它不是…」後置定義候選&lt;/li>
&lt;li>Severity 判準：grep &lt;code>severity.*\(嚴重度\|頻率\)&lt;/code> → 替代判準誤用候選&lt;/li>
&lt;/ul>
&lt;p>把 grep 命中行當 review 起點、再人工判斷是否真違規。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="multi-pass-退化成-self-edit-pass">Multi-pass 退化成 self-edit pass&lt;/h3>
&lt;p>只掃改動區 = 把 multi-pass review 退化成「我剛寫的東西自己再看一次」、這是 &lt;a href="../writing-multi-pass-review/">#83&lt;/a> 「同 frame 重看」的另一種變形 — 表面在跑 N 輪、實際 scope 是同一塊小區。違規率沒下降、只是把改動區內的違規多檢查了 N 次。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>Multi-pass review 的 scope 由『同類風險區』決定、不是『我改過的檔』。</strong> 跑某條原則的 pass（例如「結論可驗證性」）、scope 就是「所有可能違反該原則的檔」、不是「我這次改了的檔」。後者是執行便利選擇、不是 review scope 的合法依據 — 同一原則違反通常分布在整個 corpus、改動區只佔小比例。</p>
<table>
  <thead>
      <tr>
          <th>Scope 定義方式</th>
          <th>抓得到的違規</th>
          <th>漏掉的違規</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「我改過的檔」（便利）</td>
          <td>改動區的新引入違規 + 我順手注意到的舊違規</td>
          <td>整個 corpus 既有的同類違規（佔多數）</td>
      </tr>
      <tr>
          <td>「同類風險的內容範圍」</td>
          <td>該原則在整個 corpus 的所有違規</td>
          <td>無 — 這就是該原則 review 的合法 scope</td>
      </tr>
  </tbody>
</table>
<p>判別問題：「<strong>這次 pass 用的 frame、適用範圍是哪些檔？我的 scope 涵蓋了那個範圍嗎？</strong>」答案是「沒有、我只掃了改動區」就需要擴大 scope。</p>
<hr>
<h2 id="情境">情境</h2>
<p>寫了一條新原則卡片（例：#94 結論可驗證性）後、要套回既有寫作做 multi-pass review。預設行為是「掃我這次改過的檔」、原因：</p>
<ul>
<li>改動區是當下 working memory 裡的內容、便利</li>
<li>改動區 diff 短、容易跑完</li>
<li>改動區是「我剛動過的、所以可能有違規」的直覺對象</li>
</ul>
<p>這三個理由都是<strong>執行便利</strong>、不是「review scope 的合法依據」。新原則套回既有 corpus 時、違規通常已經存在於沒被改動的部分（因為原則之前不存在、整個 corpus 都沒按該原則寫過）。只掃改動區會 systematic miss 大部分違規。</p>
<p>具體 case：本 blog <code>compositional-writing</code> skill 的負向表述清理：</p>
<ol>
<li>寫 #94 結論可驗證性原則（contrast 該保留還是該刪的判別）</li>
<li>Multi-pass 跑 6 輪、scope 設為「我改過的 SKILL.md / writing-articles.md / #94 卡片本身」</li>
<li>第二天使用者讀 references/writing-prompts.md、發現「Prompt 的『原子單位』不是『一句話』、而是『一個可被驗收的任務』」就是 #94 該抓的 case</li>
<li>該違規分布廣度：scan 整個 references/ 目錄、相同句型違規共 4 處（writing-prompts / writing-logs / designing-fields / managing-article-collections）、僅 0 處在我改動區內</li>
</ol>
<p>我的 multi-pass 設計把 4 處違規 100% 漏掉、使用者用肉眼讀就抓到。</p>
<hr>
<h2 id="理想做法">理想做法</h2>
<h3 id="第一步定義原則的適用範圍">第一步：定義原則的「適用範圍」</h3>
<p>寫一條新原則時、明確標註該原則適用於哪些檔 / section。例：</p>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>適用範圍</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>#94 結論可驗證性</td>
          <td>所有教學 / 知識卡 / 規範文件的論證段落</td>
      </tr>
      <tr>
          <td>規則五 最重要的話優先說</td>
          <td>所有有「核心命題」「重點」段落的文件</td>
      </tr>
      <tr>
          <td>Severity 判準對齊分流目的</td>
          <td>所有定義 severity 的 logging / monitoring 文件</td>
      </tr>
  </tbody>
</table>
<h3 id="第二步pass-scope--適用範圍--待-review-corpus">第二步：Pass scope = 適用範圍 ∩ 待 review corpus</h3>
<p>跑該原則的 pass 時、scope 是「該原則的適用範圍」交集「目前要 review 的 corpus」、跟「我改過哪些檔」完全無關。</p>
<p>對 compositional-writing skill 而言：跑 #94 pass 的合法 scope 是 <code>.claude/skills/compositional-writing/**/*.md</code> 全部、不是「我這次 commit 動到的 5 個檔」。</p>
<h3 id="第三步用-grep-把同類風險區找出來">第三步：用 grep 把同類風險區找出來</h3>
<p>同類風險常有結構性 signature（句型、詞彙、模式）、可用 grep 把適用範圍縮到具體行。例：</p>
<ul>
<li>#94：grep <code>不是.*而是\|不是.*是\|只是表象\|只是次級訊號</code> → 候選行</li>
<li>規則五：grep <code>^[^*].*。.*它</code> → 「X。它不是…」後置定義候選</li>
<li>Severity 判準：grep <code>severity.*\(嚴重度\|頻率\)</code> → 替代判準誤用候選</li>
</ul>
<p>把 grep 命中行當 review 起點、再人工判斷是否真違規。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="multi-pass-退化成-self-edit-pass">Multi-pass 退化成 self-edit pass</h3>
<p>只掃改動區 = 把 multi-pass review 退化成「我剛寫的東西自己再看一次」、這是 <a href="../writing-multi-pass-review/">#83</a> 「同 frame 重看」的另一種變形 — 表面在跑 N 輪、實際 scope 是同一塊小區。違規率沒下降、只是把改動區內的違規多檢查了 N 次。</p>
<h3 id="既有-corpus-的違規永久累積">既有 corpus 的違規永久累積</h3>
<p>每次跑 pass 都只掃改動區、整個 corpus 的既有違規會永久不被處理 — 因為新加的原則只回頭掃改動區、舊內容沒被改的就永遠不過 review。corpus 越大、這個問題越嚴重 — 違規被結構性掩蓋、不是因為沒人看、是因為 scope 預設把它們排除。</p>
<h3 id="違規由使用者眼睛-catch而不是流程-catch">違規由使用者眼睛 catch、而不是流程 catch</h3>
<p>最終結果是違規被使用者讀到才發現、而不是 review 流程主動 catch。這違反 <a href="../literal-interception-vs-behavioral-refinement/">#82</a> 跟 <a href="../external-trigger-for-high-roi-work/">#72</a> — 把高 ROI 的 review 工作結構性跳過、靠外部 trigger（使用者抱怨）才執行。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></strong>：本卡是 #67 在「review scope 設定」層的具體案例。最便利的 scope（改動區）跟意圖對齊（同類風險區）反向 — 越便利、越漏掉違規。</li>
<li><strong><a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精煉</a></strong>：本卡跟 #82 互補。#82 是「驗證粒度」要對齊、本卡是「驗證範圍」要對齊 — 兩個都是把 review 結構錯位、結果都是 false confidence。</li>
<li><strong><a href="../writing-multi-pass-review/">#83 寫作的 multi-pass review</a></strong>：本卡補強 #83 沒覆蓋的 scope 軸。#83 講「每輪換 frame」（horizontal）、本卡講「每輪 scope 由原則適用範圍決定」（範圍）— frame × scope 兩軸都對齊、multi-pass 才有意義。</li>
<li><strong><a href="../external-trigger-for-high-roi-work/">#72 高 ROI 無外部觸發的工作會被結構性跳過</a></strong>：「擴大 scope 跑 corpus-wide review」是高 ROI 但無強制 trigger 的工作、本卡指出該動作預設會被「改動區便利 scope」結構性取代。</li>
<li><strong><a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據</a></strong>：本卡跟 #94 是同次事故串接 — #94 抓到「改寫違規」、本卡抓到「review scope 漏掉的違規」、兩條一起才是完整的「正向改寫流程」。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>當你準備 / 正在跑 multi-pass review 時、停下來檢查：</p>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pass 的 scope 是「我改過的檔」</td>
          <td>便利 scope、跟原則適用範圍對不上</td>
      </tr>
      <tr>
          <td>沒明確標註「這條原則適用於哪些檔」</td>
          <td>沒適用範圍 = scope 沒依據、預設就會回退到改動區</td>
      </tr>
      <tr>
          <td>跑完 pass 沒用 grep 把同類風險區掃過一遍</td>
          <td>缺結構性掃描、漏掉的違規無法被流程 catch</td>
      </tr>
      <tr>
          <td>Review 報告寫「修了 X 處違規」、沒寫「掃過 Y 個檔」</td>
          <td>報告只記輸出、沒記 scope、無法事後驗證 review 範圍是否合法</td>
      </tr>
      <tr>
          <td>使用者後續抓到違規、且該違規不在你的改動區</td>
          <td>scope 失誤的 retro signal、表示這條原則的 pass 該 corpus-wide</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：multi-pass review、新原則套回既有 corpus、批量品質檢查</li>
<li><strong>不適用</strong>：純 syntax / lint check（這類由工具固定 scope 跑全 corpus、無便利退化問題）</li>
<li><strong>邊界</strong>：「同類風險區」≠「全 repo 全掃」— scope 由原則適用範圍界定、不無限擴大；範圍邊界比較適合寫在原則定義時（一次想清楚、之後直接套用）、勝過 review 時臨時決定（每次都要重判一次、累積成本高）</li>
</ul>
]]></content:encoded></item><item><title>適用範圍要展開成 file enumeration、口語描述不夠</title><link>https://tarrragon.github.io/blog/report/applicability-scope-must-be-enumerated/</link><pubDate>Wed, 29 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/applicability-scope-must-be-enumerated/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>適用範圍要展開成具體 file enumeration、不能只給口語類型描述。&lt;/strong> 「所有教學文件」「所有規範文件」這類描述聽起來夠語意化、實際執行 review 時要當場推導「具體哪些檔屬於這個類型」— 推導步驟容易漏。Enumerate 成具體 file list（或可重現該 list 的 grep / find 指令）才是合法的適用範圍形式。&lt;/p>
&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;code>.claude/skills/compositional-writing/**/*.md&lt;/code>」&lt;/td>
 &lt;td>合法、明確檔列表、可重現&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「&lt;code>grep -l '## 核心原則' content/report/&lt;/code>」&lt;/td>
 &lt;td>合法、可重現的 grep 規則&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「同類教學文件、含 mirror / fork / 翻譯版」&lt;/td>
 &lt;td>不夠、mirror / fork / 翻譯版要明列具體 path&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>判別問題：「&lt;strong>這個適用範圍能 reproduce 出具體 file list 嗎？兩個人各自展開會得到同一個 list 嗎？&lt;/strong>」答案是「不能」就需要 enumerate。&lt;/p>
&lt;hr>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>寫了一條原則卡片（例：#95 multi-pass scope 由適用範圍決定）後、開始套用該原則跑 review。預設行為是讀「適用範圍」描述、心裡推導具體檔、開始掃。推導過程典型遇到的事故：&lt;/p>
&lt;ul>
&lt;li>描述用語意層詞彙（「教學文件」「規範文件」）、心裡只想到主檔、忘了 mirror / sibling / 翻譯版&lt;/li>
&lt;li>描述用 directory 層級（「&lt;code>.claude/skills/&lt;/code>」）、忘了 &lt;code>content/skills/&lt;/code> 是同 surface mirror&lt;/li>
&lt;li>描述用「所有 X」，X 邊界本來就模糊（「所有 Pattern 卡片」— 哪些算 Pattern？）&lt;/li>
&lt;/ul>
&lt;p>具體 case：本 blog 跑 #94 + #95 review 時、適用範圍寫「&lt;code>compositional-writing&lt;/code> skill 的所有 references」、心裡推導 = &lt;code>.claude/skills/compositional-writing/references/*.md&lt;/code>。漏掉的是：&lt;/p>
&lt;ul>
&lt;li>&lt;code>content/skills/compositional-writing/*.md&lt;/code>（同 surface mirror、AGENTS.md Skill 撰寫規範要求「主體相同」）&lt;/li>
&lt;li>同名檔在兩個物理路徑都存在、語意上是同一份內容&lt;/li>
&lt;/ul>
&lt;p>連續兩輪 review（#94 跟 #95）都漏同 5 個 mirror 檔、共 10 處違規透過 mirror 永久躲過 review。&lt;strong>Root cause 不是「我忘了」、是「適用範圍沒 enumerate、每次 review 都要重新心算一次具體 list」&lt;/strong>。&lt;/p>
&lt;hr>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="第一步原則定義時-enumerate-適用範圍">第一步：原則定義時 enumerate 適用範圍&lt;/h3>
&lt;p>寫原則卡片時、適用範圍欄位寫具體 file enumeration（path glob 或 grep / find 指令）、不寫類型描述。例：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="gu">## 適用範圍
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="gu">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="k">-&lt;/span> &lt;span class="sb">`.claude/skills/compositional-writing/SKILL.md`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="k">-&lt;/span> &lt;span class="sb">`.claude/skills/compositional-writing/references/*.md`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="k">-&lt;/span> &lt;span class="sb">`content/skills/compositional-writing/*.md`&lt;/span>（mirror、AGENTS.md §9 規範同步）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">- &lt;span class="sb">`content/report/*.md`&lt;/span>（教學卡）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>或用可重現的 grep / find 規則：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 適用範圍 = 含「## 核心原則」section 的所有教學卡&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">grep -rl &lt;span class="s2">&amp;#34;^## 核心原則&amp;#34;&lt;/span> content/report/ content/skills/&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>兩種形式擇一、避免「所有 X 類文件」的口語描述。&lt;/p>
&lt;h3 id="第二步review-開始前先跑-enumeration確認-list-完整">第二步：Review 開始前先跑 enumeration、確認 list 完整&lt;/h3>
&lt;p>跑 pass 之前、先 ls / grep 出具體檔列表、貼到 review 紀錄裡、確認沒漏。例：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">$ find .claude/skills/compositional-writing content/skills/compositional-writing -name &lt;span class="s2">&amp;#34;*.md&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">.claude/skills/compositional-writing/SKILL.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">.claude/skills/compositional-writing/references/writing-articles.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">... &lt;span class="o">(&lt;/span>&lt;span class="m">15&lt;/span> files total&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">content/skills/compositional-writing/skill.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">content/skills/compositional-writing/writing-articles.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">... &lt;span class="o">(&lt;/span>&lt;span class="m">12&lt;/span> files total&lt;span class="o">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>把這個 list 當這次 pass 的 ground truth、跟原則的「適用範圍 enumeration」比對、有 discrepancy（list 多 / 少）就停下來重看適用範圍定義。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>適用範圍要展開成具體 file enumeration、不能只給口語類型描述。</strong> 「所有教學文件」「所有規範文件」這類描述聽起來夠語意化、實際執行 review 時要當場推導「具體哪些檔屬於這個類型」— 推導步驟容易漏。Enumerate 成具體 file list（或可重現該 list 的 grep / find 指令）才是合法的適用範圍形式。</p>
<table>
  <thead>
      <tr>
          <th>適用範圍的形式</th>
          <th>合法性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「所有教學 / 知識卡 / 規範文件的論證段落」</td>
          <td>不夠、執行時要當場推導具體檔、推導步驟易漏</td>
      </tr>
      <tr>
          <td>「<code>.claude/skills/compositional-writing/**/*.md</code>」</td>
          <td>合法、明確檔列表、可重現</td>
      </tr>
      <tr>
          <td>「<code>grep -l '## 核心原則' content/report/</code>」</td>
          <td>合法、可重現的 grep 規則</td>
      </tr>
      <tr>
          <td>「同類教學文件、含 mirror / fork / 翻譯版」</td>
          <td>不夠、mirror / fork / 翻譯版要明列具體 path</td>
      </tr>
  </tbody>
</table>
<p>判別問題：「<strong>這個適用範圍能 reproduce 出具體 file list 嗎？兩個人各自展開會得到同一個 list 嗎？</strong>」答案是「不能」就需要 enumerate。</p>
<hr>
<h2 id="情境">情境</h2>
<p>寫了一條原則卡片（例：#95 multi-pass scope 由適用範圍決定）後、開始套用該原則跑 review。預設行為是讀「適用範圍」描述、心裡推導具體檔、開始掃。推導過程典型遇到的事故：</p>
<ul>
<li>描述用語意層詞彙（「教學文件」「規範文件」）、心裡只想到主檔、忘了 mirror / sibling / 翻譯版</li>
<li>描述用 directory 層級（「<code>.claude/skills/</code>」）、忘了 <code>content/skills/</code> 是同 surface mirror</li>
<li>描述用「所有 X」，X 邊界本來就模糊（「所有 Pattern 卡片」— 哪些算 Pattern？）</li>
</ul>
<p>具體 case：本 blog 跑 #94 + #95 review 時、適用範圍寫「<code>compositional-writing</code> skill 的所有 references」、心裡推導 = <code>.claude/skills/compositional-writing/references/*.md</code>。漏掉的是：</p>
<ul>
<li><code>content/skills/compositional-writing/*.md</code>（同 surface mirror、AGENTS.md Skill 撰寫規範要求「主體相同」）</li>
<li>同名檔在兩個物理路徑都存在、語意上是同一份內容</li>
</ul>
<p>連續兩輪 review（#94 跟 #95）都漏同 5 個 mirror 檔、共 10 處違規透過 mirror 永久躲過 review。<strong>Root cause 不是「我忘了」、是「適用範圍沒 enumerate、每次 review 都要重新心算一次具體 list」</strong>。</p>
<hr>
<h2 id="理想做法">理想做法</h2>
<h3 id="第一步原則定義時-enumerate-適用範圍">第一步：原則定義時 enumerate 適用範圍</h3>
<p>寫原則卡片時、適用範圍欄位寫具體 file enumeration（path glob 或 grep / find 指令）、不寫類型描述。例：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="ln">1</span><span class="cl"><span class="gu">## 適用範圍
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="gu"></span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="k">-</span> <span class="sb">`.claude/skills/compositional-writing/SKILL.md`</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="k">-</span> <span class="sb">`.claude/skills/compositional-writing/references/*.md`</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="k">-</span> <span class="sb">`content/skills/compositional-writing/*.md`</span>（mirror、AGENTS.md §9 規範同步）
</span></span><span class="line"><span class="ln">6</span><span class="cl">- <span class="sb">`content/report/*.md`</span>（教學卡）</span></span></code></pre></div><p>或用可重現的 grep / find 規則：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 適用範圍 = 含「## 核心原則」section 的所有教學卡</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">grep -rl <span class="s2">&#34;^## 核心原則&#34;</span> content/report/ content/skills/</span></span></code></pre></div><p>兩種形式擇一、避免「所有 X 類文件」的口語描述。</p>
<h3 id="第二步review-開始前先跑-enumeration確認-list-完整">第二步：Review 開始前先跑 enumeration、確認 list 完整</h3>
<p>跑 pass 之前、先 ls / grep 出具體檔列表、貼到 review 紀錄裡、確認沒漏。例：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">$ find .claude/skills/compositional-writing content/skills/compositional-writing -name <span class="s2">&#34;*.md&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">.claude/skills/compositional-writing/SKILL.md
</span></span><span class="line"><span class="ln">3</span><span class="cl">.claude/skills/compositional-writing/references/writing-articles.md
</span></span><span class="line"><span class="ln">4</span><span class="cl">... <span class="o">(</span><span class="m">15</span> files total<span class="o">)</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">content/skills/compositional-writing/skill.md
</span></span><span class="line"><span class="ln">6</span><span class="cl">content/skills/compositional-writing/writing-articles.md
</span></span><span class="line"><span class="ln">7</span><span class="cl">... <span class="o">(</span><span class="m">12</span> files total<span class="o">)</span></span></span></code></pre></div><p>把這個 list 當這次 pass 的 ground truth、跟原則的「適用範圍 enumeration」比對、有 discrepancy（list 多 / 少）就停下來重看適用範圍定義。</p>
<h3 id="第三步把-enumeration-規則做成工具化檢查">第三步：把 enumeration 規則做成工具化檢查</h3>
<p>當 enumeration 規則穩定後（例：「<code>.claude/skills/&lt;x&gt;/</code> 跟 <code>content/skills/&lt;x&gt;/</code> 永遠是 mirror 關係」）、把它寫成 lint / pre-commit hook：</p>
<ul>
<li>mirror 檢查：兩 path 同名檔有 diff → 警告</li>
<li>enumeration 漂移檢查：原則卡片裡的 path glob 跟實際 ls 結果有差 → 警告</li>
</ul>
<p>工具化後 enumeration 不再依賴人為紀律、是結構性保證。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="review-scope-每次都要重新心算漏判率隨輪次累積">Review scope 每次都要重新心算、漏判率隨輪次累積</h3>
<p>口語描述的適用範圍 = 每次 review 都要當場推導具體 list。推導步驟有錯漏率、每跑一輪 review 就累積一次。本 blog 跑 #94 / #95 連續兩輪都漏同 5 個 mirror = 推導錯漏率 100%、不是偶發。</p>
<h3 id="mirror--fork--副本永遠躲過-review">Mirror / fork / 副本永遠躲過 review</h3>
<p>語意上是同一份內容、物理上不同 path 的檔（mirror / fork / 翻譯版 / SDK 多語言 port），最容易在「所有 X」描述下被漏掉 — 因為心算推導對齊到「主檔」、副本被「以為已包含」漏跳過。連續多輪後副本內容會嚴重 drift、跟主檔失去同步。</p>
<h3 id="enumeration-缺失等於沒有原則的-ssot">Enumeration 缺失等於沒有原則的 SSoT</h3>
<p>適用範圍是原則的「作用域 SSoT」、沒寫清楚就等於每個讀者各自解釋一份 — #44 SSoT 違反在「原則作用域」維度的具體形態。讀者 A 跑 review 涵蓋 mirror、讀者 B 不涵蓋、原則套用結果就會 drift。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass scope 要蓋同類風險區</a></strong>：本卡是 #95 的下游具體化。#95 答「scope 從哪來 = 適用範圍 ∩ corpus」、本卡答「適用範圍長什麼樣 = enumerated file list」。兩條串起來才是完整 review 流程。</li>
<li><strong><a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精煉</a></strong>：本卡跟 #82 互補。Enumerate file list 是字面層（具體 path）、enumeration completeness 是行為層的合法性判準（兩個人展開能否得到同一個 list）— 兩層都要對齊、scope 才合法。</li>
<li><strong><a href="../single-source-of-truth/">#44 Single Source of Truth</a></strong>：本卡是 #44 在「原則作用域」維度的具體案例。適用範圍口語描述 = 每個讀者各自解釋一次、結果 drift。</li>
<li><strong><a href="../measurement-completeness/">#7 量測值缺一不可</a></strong>：本卡是 #7 在「review 範圍」的同形 pattern — enumerate 漏一個 = sanity 防線有缺口、整組 review 結果不可信。</li>
<li><strong><a href="../two-occurrence-threshold/">#42 2 次門檻是訊號</a></strong>：本卡的觸發來自「同方向漏判 2 次」訊號 — mirror 漏同步在 #94 / #95 review 連續發生、就是 #42 訊號要求抽象的 case。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>當你寫原則卡片或準備跑 review 時、停下來檢查：</p>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>適用範圍寫「所有 X 類文件」（口語類型描述）</td>
          <td>沒 enumerate、執行時要心算、易漏副本</td>
      </tr>
      <tr>
          <td>適用範圍只寫主目錄、沒列 mirror / fork / 翻譯版</td>
          <td>mirror 系列檔最容易漏、明列</td>
      </tr>
      <tr>
          <td>兩個人讀同一個適用範圍、心裡展開的 file list 不一樣</td>
          <td>適用範圍模糊、要改寫成 grep / find 規則</td>
      </tr>
      <tr>
          <td>Review 跑完、沒有「實際掃過哪些檔」的紀錄</td>
          <td>scope 沒驗證、漏判無 retro signal</td>
      </tr>
      <tr>
          <td>連續多輪 review 都漏同類檔（例 mirror）</td>
          <td>#42 訊號、enumerate 規則該升級成工具化檢查</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用範圍 enumeration</strong>：
<ul>
<li><code>content/report/*.md</code>（所有 report 卡片寫適用範圍時）</li>
<li><code>.claude/skills/*/SKILL.md</code>（所有 skill 入口的觸發路由）</li>
<li><code>.claude/rules/**/*.md</code>（所有規範文件的作用域）</li>
</ul>
</li>
<li><strong>不適用</strong>：純文字創作（散文 / 詩 / 故事）— 這類沒有「原則作用域」議題、enumerate 是 over-engineering</li>
<li><strong>邊界</strong>：「Enumerate」≠「全 repo 全列」— 適用範圍仍由原則決定、enumerate 只是把該範圍寫成可重現形式；範圍本身的合理性是另一件事（由原則的 trade-off 決定）</li>
</ul>
]]></content:encoded></item><item><title>Metadata surface 要納入寫作 review 範圍</title><link>https://tarrragon.github.io/blog/report/metadata-surface-in-writing-review/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/metadata-surface-in-writing-review/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>寫作 review 的 surface 包含正文與 metadata surface。&lt;/strong> Title、description、frontmatter、heading、link label、MOC 索引條都是讀者入口與 grep 入口；它們和正文共同建立讀者第一個概念錨點。正文通過 multi-pass review 只代表 body surface 收斂，metadata surface 仍要跑同一套意圖、語氣、grep-ability 與索引一致性檢查。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Surface&lt;/th>
 &lt;th>典型位置&lt;/th>
 &lt;th>Review 責任&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Body surface&lt;/td>
 &lt;td>段落、表格、範例、判讀徵兆&lt;/td>
 &lt;td>完整論證、段首核心、案例補足&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Metadata surface&lt;/td>
 &lt;td>&lt;code>title&lt;/code>、&lt;code>description&lt;/code>、&lt;code>tags&lt;/code>、&lt;code>weight&lt;/code>&lt;/td>
 &lt;td>讀者第一眼、搜尋摘要、排序與分類&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Navigation surface&lt;/td>
 &lt;td>&lt;code>_index.md&lt;/code> 索引條、MOC hook、link label&lt;/td>
 &lt;td>跨篇路由、下一步判斷、概念入口一致性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Identity surface&lt;/td>
 &lt;td>檔名、slug、canonical link&lt;/td>
 &lt;td>可回溯識別、跨工具定位、單次 grep 命中&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>判別問題：「&lt;strong>讀者看到這篇文章之前，會先看到哪些文字？這些文字有沒有跟正文跑同一輪 review？&lt;/strong>」&lt;/p>
&lt;hr>
&lt;h2 id="warp-分析摘要">WARP 分析摘要&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>在建立資安章節大綱時，正文已採用「資安作為風險路由系統」的正向概念，但 frontmatter title 與 &lt;code>_index.md&lt;/code> 索引條保留 &lt;code>資安不是 Checklist：它是風險路由系統&lt;/code>。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>判讀&lt;/td>
 &lt;td>Review frame 套在 body surface，metadata surface 被當成包裝文字；因此「正向陳述優先」實際只覆蓋正文，讀者入口仍使用負向 hook。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>策略&lt;/td>
 &lt;td>把 metadata surface 明列成 review scope：title、description、tags、heading、link label、MOC hook、slug / filename 都要跟正文一起跑 positive wording、focus、grep-ability、cross-link pass。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>結論&lt;/td>
 &lt;td>&lt;code>compositional-writing&lt;/code> 的 multi-pass 規則需要補一個 surface 軸：frame 決定看什麼品質，surface 決定掃哪些文字。Frame × surface 同時完整，review 才能覆蓋文章實際被讀到的位置。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>反向驗證：有些標題可以保留對照句型，條件是正文需要讀者先排除常見誤解，且標題本身同時給出正向概念錨點。這次的正文已能用「資安作為風險路由系統」直接建立錨點，對照句型放在正文的論證段更穩定。&lt;/p>
&lt;hr>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>建立 &lt;code>content/backend/07-security-data-protection/security-as-risk-routing-system.md&lt;/code> 時，文章責任已經寫成「把資安從檢查項目轉成工程路由語言」。正文段落也使用了正向定義：資安路由系統先判斷風險落點，再選擇控制面。&lt;/p>
&lt;p>問題出現在讀者入口：&lt;/p>
&lt;ul>
&lt;li>Frontmatter &lt;code>title&lt;/code> 使用 &lt;code>資安不是 Checklist：它是風險路由系統&lt;/code>&lt;/li>
&lt;li>&lt;code>content/backend/07-security-data-protection/_index.md&lt;/code> 的索引條沿用同一個 link label&lt;/li>
&lt;li>Review 討論集中在正文與章節內容，title / MOC hook 沒被列為同一輪檢查對象&lt;/li>
&lt;/ul>
&lt;p>這個問題的主因是 review surface enumeration 漏列：執行者知道要跑正向陳述檢查，但心中 scope 等於「正文段落」，沒有把 metadata surface 視為同等重要的文字。&lt;/p>
&lt;hr>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="第一步先列出本次產出的所有-surface">第一步：先列出本次產出的所有 surface&lt;/h3>
&lt;p>寫作前先列出本次會產生或修改的文字位置。例：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">content/backend/07-security-data-protection/security-as-risk-routing-system.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">- frontmatter.title
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">- frontmatter.description
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">- body headings
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">- body paragraphs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">- link labels
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">content/backend/07-security-data-protection/_index.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">- table link label
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">- table topic
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">- table responsibility&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這份清單是 review 的 surface enumeration。它補足 &lt;a href="../applicability-scope-must-be-enumerated/">#96 適用範圍要展開成 file enumeration&lt;/a> 的單檔內版本：#96 先列「哪些檔」，本卡再列「檔內哪些文字位置」。&lt;/p>
&lt;h3 id="第二步每一輪-frame-都掃所有-surface">第二步：每一輪 frame 都掃所有 surface&lt;/h3>
&lt;p>Multi-pass review 的每輪 frame 都要套到 surface 清單上：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Frame&lt;/th>
 &lt;th>Body surface&lt;/th>
 &lt;th>Metadata / navigation surface&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>對意圖&lt;/td>
 &lt;td>段落是否回到核心責任&lt;/td>
 &lt;td>Title / description 是否承接同一個核心責任&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>正向陳述 / 機會成本語氣&lt;/td>
 &lt;td>段落是否先建立概念，再補對照&lt;/td>
 &lt;td>Title / MOC hook 是否先給正向錨點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Grep-ability / 命名&lt;/td>
 &lt;td>段首關鍵字是否可搜尋&lt;/td>
 &lt;td>Title、slug、link label 是否能單次 grep 命中&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cross-link 健康度&lt;/td>
 &lt;td>引用是否指向正確卡片&lt;/td>
 &lt;td>&lt;code>_index.md&lt;/code> 索引條是否導向同一個概念入口&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>反例 / 邊界&lt;/td>
 &lt;td>對照段是否保留原因與適用範圍&lt;/td>
 &lt;td>標題若使用對照句型，是否有正文立即承接其原因&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Surface enumeration 讓「我有跑正向陳述 pass」變成可驗證動作，而不只是抽象自我宣告。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>寫作 review 的 surface 包含正文與 metadata surface。</strong> Title、description、frontmatter、heading、link label、MOC 索引條都是讀者入口與 grep 入口；它們和正文共同建立讀者第一個概念錨點。正文通過 multi-pass review 只代表 body surface 收斂，metadata surface 仍要跑同一套意圖、語氣、grep-ability 與索引一致性檢查。</p>
<table>
  <thead>
      <tr>
          <th>Surface</th>
          <th>典型位置</th>
          <th>Review 責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Body surface</td>
          <td>段落、表格、範例、判讀徵兆</td>
          <td>完整論證、段首核心、案例補足</td>
      </tr>
      <tr>
          <td>Metadata surface</td>
          <td><code>title</code>、<code>description</code>、<code>tags</code>、<code>weight</code></td>
          <td>讀者第一眼、搜尋摘要、排序與分類</td>
      </tr>
      <tr>
          <td>Navigation surface</td>
          <td><code>_index.md</code> 索引條、MOC hook、link label</td>
          <td>跨篇路由、下一步判斷、概念入口一致性</td>
      </tr>
      <tr>
          <td>Identity surface</td>
          <td>檔名、slug、canonical link</td>
          <td>可回溯識別、跨工具定位、單次 grep 命中</td>
      </tr>
  </tbody>
</table>
<p>判別問題：「<strong>讀者看到這篇文章之前，會先看到哪些文字？這些文字有沒有跟正文跑同一輪 review？</strong>」</p>
<hr>
<h2 id="warp-分析摘要">WARP 分析摘要</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>觀察</td>
          <td>在建立資安章節大綱時，正文已採用「資安作為風險路由系統」的正向概念，但 frontmatter title 與 <code>_index.md</code> 索引條保留 <code>資安不是 Checklist：它是風險路由系統</code>。</td>
      </tr>
      <tr>
          <td>判讀</td>
          <td>Review frame 套在 body surface，metadata surface 被當成包裝文字；因此「正向陳述優先」實際只覆蓋正文，讀者入口仍使用負向 hook。</td>
      </tr>
      <tr>
          <td>策略</td>
          <td>把 metadata surface 明列成 review scope：title、description、tags、heading、link label、MOC hook、slug / filename 都要跟正文一起跑 positive wording、focus、grep-ability、cross-link pass。</td>
      </tr>
      <tr>
          <td>結論</td>
          <td><code>compositional-writing</code> 的 multi-pass 規則需要補一個 surface 軸：frame 決定看什麼品質，surface 決定掃哪些文字。Frame × surface 同時完整，review 才能覆蓋文章實際被讀到的位置。</td>
      </tr>
  </tbody>
</table>
<p>反向驗證：有些標題可以保留對照句型，條件是正文需要讀者先排除常見誤解，且標題本身同時給出正向概念錨點。這次的正文已能用「資安作為風險路由系統」直接建立錨點，對照句型放在正文的論證段更穩定。</p>
<hr>
<h2 id="情境">情境</h2>
<p>建立 <code>content/backend/07-security-data-protection/security-as-risk-routing-system.md</code> 時，文章責任已經寫成「把資安從檢查項目轉成工程路由語言」。正文段落也使用了正向定義：資安路由系統先判斷風險落點，再選擇控制面。</p>
<p>問題出現在讀者入口：</p>
<ul>
<li>Frontmatter <code>title</code> 使用 <code>資安不是 Checklist：它是風險路由系統</code></li>
<li><code>content/backend/07-security-data-protection/_index.md</code> 的索引條沿用同一個 link label</li>
<li>Review 討論集中在正文與章節內容，title / MOC hook 沒被列為同一輪檢查對象</li>
</ul>
<p>這個問題的主因是 review surface enumeration 漏列：執行者知道要跑正向陳述檢查，但心中 scope 等於「正文段落」，沒有把 metadata surface 視為同等重要的文字。</p>
<hr>
<h2 id="理想做法">理想做法</h2>
<h3 id="第一步先列出本次產出的所有-surface">第一步：先列出本次產出的所有 surface</h3>
<p>寫作前先列出本次會產生或修改的文字位置。例：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">content/backend/07-security-data-protection/security-as-risk-routing-system.md
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">- frontmatter.title
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">- frontmatter.description
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">- body headings
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">- body paragraphs
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">- link labels
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">content/backend/07-security-data-protection/_index.md
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">- table link label
</span></span><span class="line"><span class="ln">10</span><span class="cl">- table topic
</span></span><span class="line"><span class="ln">11</span><span class="cl">- table responsibility</span></span></code></pre></div><p>這份清單是 review 的 surface enumeration。它補足 <a href="../applicability-scope-must-be-enumerated/">#96 適用範圍要展開成 file enumeration</a> 的單檔內版本：#96 先列「哪些檔」，本卡再列「檔內哪些文字位置」。</p>
<h3 id="第二步每一輪-frame-都掃所有-surface">第二步：每一輪 frame 都掃所有 surface</h3>
<p>Multi-pass review 的每輪 frame 都要套到 surface 清單上：</p>
<table>
  <thead>
      <tr>
          <th>Frame</th>
          <th>Body surface</th>
          <th>Metadata / navigation surface</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>對意圖</td>
          <td>段落是否回到核心責任</td>
          <td>Title / description 是否承接同一個核心責任</td>
      </tr>
      <tr>
          <td>正向陳述 / 機會成本語氣</td>
          <td>段落是否先建立概念，再補對照</td>
          <td>Title / MOC hook 是否先給正向錨點</td>
      </tr>
      <tr>
          <td>Grep-ability / 命名</td>
          <td>段首關鍵字是否可搜尋</td>
          <td>Title、slug、link label 是否能單次 grep 命中</td>
      </tr>
      <tr>
          <td>Cross-link 健康度</td>
          <td>引用是否指向正確卡片</td>
          <td><code>_index.md</code> 索引條是否導向同一個概念入口</td>
      </tr>
      <tr>
          <td>反例 / 邊界</td>
          <td>對照段是否保留原因與適用範圍</td>
          <td>標題若使用對照句型，是否有正文立即承接其原因</td>
      </tr>
  </tbody>
</table>
<p>Surface enumeration 讓「我有跑正向陳述 pass」變成可驗證動作，而不只是抽象自我宣告。</p>
<h3 id="第三步用-grep-補字面層掃描">第三步：用 grep 補字面層掃描</h3>
<p>正向陳述是語意判斷，但第一層候選可以用 grep 找出：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">rg -n <span class="s2">&#34;不行|不可以|不是|不要|無法|不能&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  content/backend/07-security-data-protection/security-as-risk-routing-system.md <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  content/backend/07-security-data-protection/_index.md</span></span></code></pre></div><p>grep 命中代表「需要判讀」，不代表自動違規。合法的對照句型要回到 <a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據</a> 的判準：有正向錨點、有對照原因、有適用情境。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="讀者入口會先傳遞舊-frame">讀者入口會先傳遞舊 frame</h3>
<p>Title 與 MOC hook 是讀者先看到的文字。正文即使已經建立正向概念，入口若仍用負向 hook，讀者第一個 mental model 仍會被帶回「排除某種做法」而非「建立某個責任」。入口 frame 會影響後續閱讀方式。</p>
<h3 id="search-surface-會保留錯誤概念錨點">Search surface 會保留錯誤概念錨點</h3>
<p>Title、description、link label 是搜尋結果與 grep 最容易命中的位置。metadata surface 沒跑 grep-ability 與 positive wording，錯誤概念會比正文更容易被找到，長期變成知識庫中的主要入口。</p>
<h3 id="review-報告會產生-coverage-illusion">Review 報告會產生 coverage illusion</h3>
<p>只寫「已跑 positive wording pass」但沒有列 surface，review 報告會暗示整篇文章已覆蓋。實際上只掃 body surface，metadata surface 仍是未驗證區。這是 <a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass scope 要蓋同類風險區</a> 在單檔內的同形問題。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../writing-multi-pass-review/">#83 Writing 的 multi-pass review</a></strong>：#83 定義 frame 軸，本卡補 surface 軸。Frame 回答「用什麼眼睛看」，surface 回答「哪些文字都要被看」。</li>
<li><strong><a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass review 的 scope 要蓋同類風險區</a></strong>：#95 處理跨檔 scope，本卡處理單檔內 surface scope。兩者組合成完整 coverage：file scope × surface scope。</li>
<li><strong><a href="../applicability-scope-must-be-enumerated/">#96 適用範圍要展開成 file enumeration</a></strong>：#96 要求可重現的 file list，本卡要求每個 file 內的 surface list。File enumeration 完成後，還要做 surface enumeration。</li>
<li><strong><a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據</a></strong>：#94 保留合法對照的推理，本卡定義對照句型出現在 title / MOC hook 時的檢查位置與承接責任。</li>
<li><strong><a href="../naming-as-iterated-artifact/">#84 Naming 是 iterated artifact</a></strong>：Title、slug、link label 都是命名。它們需要多輪迭代，在生成後持續用 grep-ability 與讀者入口角度收斂。</li>
<li><strong><a href="../single-source-of-truth/">#44 Single Source of Truth</a></strong>：正文核心概念與 metadata surface 需要共享同一個概念 SSoT。入口文字與正文語意分裂時，讀者會看到兩個 competing source。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>當你完成文章或卡片後，看到以下訊號就要補 surface enumeration：</p>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>正文改成正向概念，title 仍使用排除式 hook</td>
          <td>Metadata surface 漏跑語氣 pass</td>
      </tr>
      <tr>
          <td><code>_index.md</code> 索引條只是沿用第一版標題</td>
          <td>Navigation surface 漏跑對意圖</td>
      </tr>
      <tr>
          <td>Frontmatter description 比正文更像行銷標語</td>
          <td>Search surface 漏跑概念錨點</td>
      </tr>
      <tr>
          <td>Review 紀錄只寫「已檢查文章」但沒列 title / MOC</td>
          <td>Coverage 欠缺驗證依據</td>
      </tr>
      <tr>
          <td>Grep 掃正文通過，搜尋結果仍命中舊句型</td>
          <td>Grep scope 沒包含 metadata</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：技術文章、report 卡片、知識卡片、README、規格文件、skill reference、MOC / <code>_index.md</code></li>
<li><strong>特別適用</strong>：有 frontmatter、sidebar title、SEO description、index table、link label 的內容系統</li>
<li><strong>邊界</strong>：Metadata surface review 是寫作 pass；它需要語意判讀，grep 只負責提出候選</li>
<li><strong>例外</strong>：短訊息、一次性草稿、私人 scratch note 可以只保留 title / body 的最小 surface；production 內容與公開知識庫需要全 surface review</li>
</ul>
<hr>
<h2 id="可操作檢查">可操作檢查</h2>
<p>Production 內容交付前，至少跑這三步：</p>
<ol>
<li>列出這次新增 / 修改檔案的 surface：<code>title</code>、<code>description</code>、heading、body、link label、MOC row。</li>
<li>跑負向詞候選 grep，逐一判讀是否有正向錨點與對照原因。</li>
<li>對照 <code>_index.md</code> 或 MOC，確認索引條、文章標題與正文第一段都指向同一個核心責任。</li>
</ol>
]]></content:encoded></item><item><title>素材庫比例要支撐主情境的反向驗證</title><link>https://tarrragon.github.io/blog/report/source-library-ratio-supports-scenario-validation/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/source-library-ratio-supports-scenario-validation/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>文章主情境負責教推演，素材庫負責支撐反向驗證。&lt;/strong> 當一組文章只展示 4-5 個主情境時，素材庫應保留約 2-3 倍的 field cases 或 source cards，讓每個主情境背後至少有 2-3 個來源可回查。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>4-5 個&lt;/td>
 &lt;td>讓讀者看完後能實際演練或套用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Field cases / source cards&lt;/td>
 &lt;td>10-12 張&lt;/td>
 &lt;td>支撐情境、反向驗證、補壓力變體&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Scenario cards&lt;/td>
 &lt;td>4-5 張&lt;/td>
 &lt;td>把多個來源轉成可重播的中性情境&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Pattern cards&lt;/td>
 &lt;td>5-7 張&lt;/td>
 &lt;td>抽出跨情境共用的做法與判讀欄位&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>比例設計的判別問題是：「&lt;strong>每個主情境背後是否有足夠來源，能支撐反例、變體與下一輪擴寫？&lt;/strong>」&lt;/p>
&lt;hr>
&lt;h2 id="warp-分析摘要">WARP 分析摘要&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>資安文章只需要 4-5 個推演情境，但 field cases 初始只有 5 張，每個 scenario 大多只靠 1 個來源支撐。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>判讀&lt;/td>
 &lt;td>文章可讀性與素材可信度是兩個不同目標。文章展示情境需要少量精選，素材庫需要較多來源來支撐反向驗證與壓力變體。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>策略&lt;/td>
 &lt;td>採「少情境、多素材」比例：scenario 維持 4-5 張，field/source 素材擴到 10-12 張，pattern 維持 5-7 張。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>結論&lt;/td>
 &lt;td>素材庫比例要服務驗證與延伸，而非跟文章情境一比一對齊。source-first 是案例型素材的前置條件。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>反向驗證：素材庫持續擴張也有成本。當每個主情境已有 2-3 個來源、每個 pattern 有 1-2 個支撐案例時，下一步應轉向寫文章、跑 review 或回寫 MOC。&lt;/p>
&lt;hr>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>在擴充資安章節時，主文章已經有足夠規模：紅隊案例庫、藍隊章節、素材庫與推演情境都已成形。下一步要決定「是否還要繼續補素材」。&lt;/p>
&lt;p>當時有兩個看似相近的問題：&lt;/p>
&lt;ol>
&lt;li>文章讀者實際會看到幾個模擬情境？&lt;/li>
&lt;li>作者要保留多少真實案例作為支撐素材？&lt;/li>
&lt;/ol>
&lt;p>如果把兩者合併，容易得到「文章只用 4-5 個情境，所以素材也只要 4-5 個案例」的結論。這個比例對文章篇幅合理，對反向驗證偏薄。每個情境只有一個來源時，情境會跟單一事件強綁，後續很難判斷哪些是共通壓力、哪些只是個案細節。&lt;/p>
&lt;hr>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="第一步分開設計文章情境與素材庫">第一步：分開設計文章情境與素材庫&lt;/h3>
&lt;p>文章情境是讀者路徑，數量要少。素材庫是作者與未來文章的驗證基礎，數量可以較多。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>少量、精選、可串成完整流程&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>素材庫數&lt;/td>
 &lt;td>情境是否有足夠來源支撐&lt;/td>
 &lt;td>來源多於情境，支撐變體與反例&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Pattern 數&lt;/td>
 &lt;td>是否有跨情境共用做法&lt;/td>
 &lt;td>少於素材，多於單篇文章需要&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="第二步先補來源再寫情境">第二步：先補來源，再寫情境&lt;/h3>
&lt;p>Field case 的責任是保存可回溯材料。案例型素材先找來源，再抽出觀察、壓力、控制缺口、判讀訊號與可轉譯情境。&lt;/p>
&lt;p>Scenario card 的責任是把來源轉譯成可演練情境。情境可以合成多個來源的壓力點，但每個主要壓力都要能回查到 field case 或 source card。&lt;/p>
&lt;p>Pattern card 的責任是歸納。模式可以比單一案例更抽象，但要保留支撐來源、適用邊界、判讀訊號與下一步路由。&lt;/p>
&lt;h3 id="第三步用停止條件控制素材庫膨脹">第三步：用停止條件控制素材庫膨脹&lt;/h3>
&lt;p>素材庫需要明確停止條件。停止條件要寫在大綱中，讓作者知道何時從蒐集轉向寫作。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>停止條件&lt;/th>
 &lt;th>下一步&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>每個主情境已有 2-3 個來源&lt;/td>
 &lt;td>寫 scenario 或主文章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>每個 pattern 有 1-2 個支撐案例&lt;/td>
 &lt;td>寫 pattern 卡或回寫文章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>新來源只重複既有壓力&lt;/td>
 &lt;td>留入候選清單，先推進文章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>文章主線開始被素材清單淹沒&lt;/td>
 &lt;td>收斂 MOC，只保留路由與 hook&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="情境會被單一案例綁死">情境會被單一案例綁死&lt;/h3>
&lt;p>每個情境只靠一個來源時，作者很容易把個案細節當成共通結構。讀者需要拿到的是可搬到自己服務裡的中性情境，而非單一事件改寫。&lt;/p>
&lt;h3 id="pattern-抽象層級會偏高">Pattern 抽象層級會偏高&lt;/h3>
&lt;p>只有單一案例支撐的 pattern 容易過早抽象。作者會把一個事件中的做法升級成通用模式，缺少第二個來源檢查它是否真的跨情境成立。&lt;/p>
&lt;h3 id="後續章節缺少延伸材料">後續章節缺少延伸材料&lt;/h3>
&lt;p>文章當下可完成，但下一輪要寫 incident response、deployment、reliability 或治理節奏時，會重新查資料。素材庫比例不足會讓每次擴寫都回到同一個蒐集成本。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../writing-multi-pass-review/">#83 Writing 的 multi-pass review&lt;/a>&lt;/strong>：#83 說寫作要用多輪 frame，本卡補「素材量也要支撐反向驗證 frame」。只有一個來源時，反例 / 邊界 pass 會缺材料。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass review 的 scope 要蓋同類風險區&lt;/a>&lt;/strong>：#95 要求 review scope 蓋同類風險區，本卡把同一精神放到素材庫：source scope 要覆蓋主情境的變體區，並支撐文章會展示的少數案例。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../applicability-scope-must-be-enumerated/">#96 適用範圍要展開成 file enumeration&lt;/a>&lt;/strong>：#96 要求 scope 具體列出，本卡要求素材庫比例具體列出：主情境數、source card 數、scenario 數、pattern 數。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關&lt;/a>&lt;/strong>：素材與文章一比一最方便，但跟「可驗證、可延伸」的意圖不對齊。補足 2-3 倍來源是較高成本但更貼合目標的做法。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精煉&lt;/a>&lt;/strong>：情境數量是字面層，情境是否有足夠變體支撐是行為層。本卡要求用來源覆蓋度判斷推演素材是否足夠。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../metadata-surface-in-writing-review/">#97 Metadata surface 要納入寫作 review 範圍&lt;/a>&lt;/strong>：#97 補 surface 軸，本卡補 material 軸。文章品質不只看正文與入口，也看背後來源是否支撐得住推演。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>看到以下訊號，就要檢查素材庫比例：&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>文章主情境負責教推演，素材庫負責支撐反向驗證。</strong> 當一組文章只展示 4-5 個主情境時，素材庫應保留約 2-3 倍的 field cases 或 source cards，讓每個主情境背後至少有 2-3 個來源可回查。</p>
<table>
  <thead>
      <tr>
          <th>層級</th>
          <th>建議數量</th>
          <th>責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主文章情境</td>
          <td>4-5 個</td>
          <td>讓讀者看完後能實際演練或套用</td>
      </tr>
      <tr>
          <td>Field cases / source cards</td>
          <td>10-12 張</td>
          <td>支撐情境、反向驗證、補壓力變體</td>
      </tr>
      <tr>
          <td>Scenario cards</td>
          <td>4-5 張</td>
          <td>把多個來源轉成可重播的中性情境</td>
      </tr>
      <tr>
          <td>Pattern cards</td>
          <td>5-7 張</td>
          <td>抽出跨情境共用的做法與判讀欄位</td>
      </tr>
  </tbody>
</table>
<p>比例設計的判別問題是：「<strong>每個主情境背後是否有足夠來源，能支撐反例、變體與下一輪擴寫？</strong>」</p>
<hr>
<h2 id="warp-分析摘要">WARP 分析摘要</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>觀察</td>
          <td>資安文章只需要 4-5 個推演情境，但 field cases 初始只有 5 張，每個 scenario 大多只靠 1 個來源支撐。</td>
      </tr>
      <tr>
          <td>判讀</td>
          <td>文章可讀性與素材可信度是兩個不同目標。文章展示情境需要少量精選，素材庫需要較多來源來支撐反向驗證與壓力變體。</td>
      </tr>
      <tr>
          <td>策略</td>
          <td>採「少情境、多素材」比例：scenario 維持 4-5 張，field/source 素材擴到 10-12 張，pattern 維持 5-7 張。</td>
      </tr>
      <tr>
          <td>結論</td>
          <td>素材庫比例要服務驗證與延伸，而非跟文章情境一比一對齊。source-first 是案例型素材的前置條件。</td>
      </tr>
  </tbody>
</table>
<p>反向驗證：素材庫持續擴張也有成本。當每個主情境已有 2-3 個來源、每個 pattern 有 1-2 個支撐案例時，下一步應轉向寫文章、跑 review 或回寫 MOC。</p>
<hr>
<h2 id="情境">情境</h2>
<p>在擴充資安章節時，主文章已經有足夠規模：紅隊案例庫、藍隊章節、素材庫與推演情境都已成形。下一步要決定「是否還要繼續補素材」。</p>
<p>當時有兩個看似相近的問題：</p>
<ol>
<li>文章讀者實際會看到幾個模擬情境？</li>
<li>作者要保留多少真實案例作為支撐素材？</li>
</ol>
<p>如果把兩者合併，容易得到「文章只用 4-5 個情境，所以素材也只要 4-5 個案例」的結論。這個比例對文章篇幅合理，對反向驗證偏薄。每個情境只有一個來源時，情境會跟單一事件強綁，後續很難判斷哪些是共通壓力、哪些只是個案細節。</p>
<hr>
<h2 id="理想做法">理想做法</h2>
<h3 id="第一步分開設計文章情境與素材庫">第一步：分開設計文章情境與素材庫</h3>
<p>文章情境是讀者路徑，數量要少。素材庫是作者與未來文章的驗證基礎，數量可以較多。</p>
<table>
  <thead>
      <tr>
          <th>決策</th>
          <th>主要問題</th>
          <th>數量邏輯</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>文章情境數</td>
          <td>讀者能否讀完並實際演練</td>
          <td>少量、精選、可串成完整流程</td>
      </tr>
      <tr>
          <td>素材庫數</td>
          <td>情境是否有足夠來源支撐</td>
          <td>來源多於情境，支撐變體與反例</td>
      </tr>
      <tr>
          <td>Pattern 數</td>
          <td>是否有跨情境共用做法</td>
          <td>少於素材，多於單篇文章需要</td>
      </tr>
  </tbody>
</table>
<h3 id="第二步先補來源再寫情境">第二步：先補來源，再寫情境</h3>
<p>Field case 的責任是保存可回溯材料。案例型素材先找來源，再抽出觀察、壓力、控制缺口、判讀訊號與可轉譯情境。</p>
<p>Scenario card 的責任是把來源轉譯成可演練情境。情境可以合成多個來源的壓力點，但每個主要壓力都要能回查到 field case 或 source card。</p>
<p>Pattern card 的責任是歸納。模式可以比單一案例更抽象，但要保留支撐來源、適用邊界、判讀訊號與下一步路由。</p>
<h3 id="第三步用停止條件控制素材庫膨脹">第三步：用停止條件控制素材庫膨脹</h3>
<p>素材庫需要明確停止條件。停止條件要寫在大綱中，讓作者知道何時從蒐集轉向寫作。</p>
<table>
  <thead>
      <tr>
          <th>停止條件</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>每個主情境已有 2-3 個來源</td>
          <td>寫 scenario 或主文章</td>
      </tr>
      <tr>
          <td>每個 pattern 有 1-2 個支撐案例</td>
          <td>寫 pattern 卡或回寫文章</td>
      </tr>
      <tr>
          <td>新來源只重複既有壓力</td>
          <td>留入候選清單，先推進文章</td>
      </tr>
      <tr>
          <td>文章主線開始被素材清單淹沒</td>
          <td>收斂 MOC，只保留路由與 hook</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="情境會被單一案例綁死">情境會被單一案例綁死</h3>
<p>每個情境只靠一個來源時，作者很容易把個案細節當成共通結構。讀者需要拿到的是可搬到自己服務裡的中性情境，而非單一事件改寫。</p>
<h3 id="pattern-抽象層級會偏高">Pattern 抽象層級會偏高</h3>
<p>只有單一案例支撐的 pattern 容易過早抽象。作者會把一個事件中的做法升級成通用模式，缺少第二個來源檢查它是否真的跨情境成立。</p>
<h3 id="後續章節缺少延伸材料">後續章節缺少延伸材料</h3>
<p>文章當下可完成，但下一輪要寫 incident response、deployment、reliability 或治理節奏時，會重新查資料。素材庫比例不足會讓每次擴寫都回到同一個蒐集成本。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../writing-multi-pass-review/">#83 Writing 的 multi-pass review</a></strong>：#83 說寫作要用多輪 frame，本卡補「素材量也要支撐反向驗證 frame」。只有一個來源時，反例 / 邊界 pass 會缺材料。</li>
<li><strong><a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass review 的 scope 要蓋同類風險區</a></strong>：#95 要求 review scope 蓋同類風險區，本卡把同一精神放到素材庫：source scope 要覆蓋主情境的變體區，並支撐文章會展示的少數案例。</li>
<li><strong><a href="../applicability-scope-must-be-enumerated/">#96 適用範圍要展開成 file enumeration</a></strong>：#96 要求 scope 具體列出，本卡要求素材庫比例具體列出：主情境數、source card 數、scenario 數、pattern 數。</li>
<li><strong><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></strong>：素材與文章一比一最方便，但跟「可驗證、可延伸」的意圖不對齊。補足 2-3 倍來源是較高成本但更貼合目標的做法。</li>
<li><strong><a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精煉</a></strong>：情境數量是字面層，情境是否有足夠變體支撐是行為層。本卡要求用來源覆蓋度判斷推演素材是否足夠。</li>
<li><strong><a href="../metadata-surface-in-writing-review/">#97 Metadata surface 要納入寫作 review 範圍</a></strong>：#97 補 surface 軸，本卡補 material 軸。文章品質不只看正文與入口，也看背後來源是否支撐得住推演。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>看到以下訊號，就要檢查素材庫比例：</p>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>每個 scenario 只靠 1 個 field case</td>
          <td>反向驗證材料偏薄</td>
      </tr>
      <tr>
          <td>Pattern card 只引用單一案例</td>
          <td>抽象層級可能過早</td>
      </tr>
      <tr>
          <td>文章情境讀起來像某事件改名</td>
          <td>中性轉譯材料不足</td>
      </tr>
      <tr>
          <td>後續章節每次都重新查同類案例</td>
          <td>素材庫沒有承擔延伸責任</td>
      </tr>
      <tr>
          <td>MOC 列出大量素材但沒有分層</td>
          <td>素材庫需要比例與路由設計</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：案例驅動文章、事故復盤、資安推演、架構決策素材庫、研究型技術文章、跨多篇 knowledge base</li>
<li><strong>特別適用</strong>：文章只展示少數情境，但需要真實案例支撐可信度與反向驗證</li>
<li><strong>邊界</strong>：比例是設計準則，實際數量依主題風險、來源密度與文章規模調整</li>
<li><strong>停止條件</strong>：每個主情境已有 2-3 個來源、每個 pattern 有 1-2 個支撐案例後，先寫文章與 review</li>
</ul>
<hr>
<h2 id="可操作檢查">可操作檢查</h2>
<p>建立案例型素材庫時，先跑這份檢查：</p>
<ol>
<li>列出主文章情境數，控制在 4-5 個。</li>
<li>為每個主情境配置 2-3 個 field cases 或 source cards。</li>
<li>檢查每張 scenario card 是否能回查來源。</li>
<li>檢查每張 pattern card 是否至少有 1-2 個支撐案例。</li>
<li>在 MOC 寫明停止條件，避免素材蒐集無限延伸。</li>
</ol>
]]></content:encoded></item><item><title>設計檢討用當下三軸論證、不依賴 hindsight</title><link>https://tarrragon.github.io/blog/report/design-flaw-by-current-axes-not-hindsight/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/design-flaw-by-current-axes-not-hindsight/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>1 個 case&lt;/strong>（&lt;a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故&lt;/a> 的 review 過程）抽出來的假說、不是經過多個獨立 case 驗證的工程原則。具體限制：&lt;/p>
&lt;ul>
&lt;li>「成本對稱性 / 可逆性 / 領域先驗」三軸框架借自 yagni 篇的判斷工具、不是 industry standard&lt;/li>
&lt;li>「hindsight 偏向個人歸因 / 三軸偏向制度歸因」是觀察性分歧、不是必然對立——實際事故報告（aviation / medical incident）也常用 hindsight 同時歸因到制度&lt;/li>
&lt;li>5 個多面向 case（code review / post-mortem / ADR / retrospective / 寫作）是假設性對比、未驗證真實案例中兩種論述的差異&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、把它當「&lt;strong>這個 blog 提倡的判定方式&lt;/strong>」、不當「驗證過的工程原則」。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>本卡提倡的「設計缺陷」判定方式是「&lt;strong>在當下成本對稱條件下選了限制更高的選項&lt;/strong>」、用以替代依賴結局的 hindsight 判定。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>事後諸葛論述（hindsight）&lt;/th>
 &lt;th>當下三軸論證（current axes）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>視角&lt;/td>
 &lt;td>已知結局、回頭看&lt;/td>
 &lt;td>不知結局、看當下選擇&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>判斷依據&lt;/td>
 &lt;td>後來真的需要 X、所以當初該做 X&lt;/td>
 &lt;td>當下三軸（成本對稱性 / 可逆性 / 領域先驗）都指向 X&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>歸因方向&lt;/td>
 &lt;td>設計者個人沒預見&lt;/td>
 &lt;td>工具預設 + 領域知識制度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>教讀者什麼&lt;/td>
 &lt;td>後見之明的具體規則&lt;/td>
 &lt;td>當下能用的判斷工具&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>泛化能力&lt;/td>
 &lt;td>弱（只在類似 case 適用）&lt;/td>
 &lt;td>強（可套到新情境）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>兩種論述讀起來都像在分析「設計缺陷」、但結論不同、可教性也不同。&lt;strong>事後諸葛論述需要結局發生、當下三軸論證在當下就能判斷&lt;/strong>——後者才是 portable 工具。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼-hindsight-不適合做設計缺陷判定">為什麼 hindsight 不適合做設計缺陷判定&lt;/h2>
&lt;h3 id="hindsight-預設了結局不能在當下使用">Hindsight 預設了結局、不能在當下使用&lt;/h3>
&lt;p>事後諸葛論述「StreamController() 被當廣播用了一段時間沒事、加第二個 listener 立刻炸 → 設計缺陷」隱含一個前提：讀者知道後來加了第二個 listener。&lt;/p>
&lt;p>但設計者在當下不知道結局。如果讀者用這個論述當判斷工具、他要等到結局發生才知道「自己做錯了」——這不是判斷工具、是事後檢討。&lt;/p>
&lt;p>當下三軸論述「在零成本差異 + 強領域先驗下選了限制更高的選項 → 設計缺陷」不需要等結局——讀者拿到的是「現在面對這類選擇、跑三軸、就能判斷」的工具。&lt;/p>
&lt;h3 id="把判斷依據放在結局上會誤判類似情境">把判斷依據放在結局上、會誤判類似情境&lt;/h3>
&lt;p>「結局是『後來需要多訂閱』 → 當初該選 broadcast」這個推論、套到不同議題會推出反向結論：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>議題&lt;/th>
 &lt;th>結局&lt;/th>
 &lt;th>Hindsight 推論&lt;/th>
 &lt;th>當下三軸推論&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>事先沒做 plugin、後來真的需要&lt;/td>
 &lt;td>後來需要 plugin&lt;/td>
 &lt;td>當初該建 → 過度設計&lt;/td>
 &lt;td>高成本差、屬 YAGNI 適用 → 當初不做是對的&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>用 single 預設、後來只有一個訂閱者&lt;/td>
 &lt;td>沒事&lt;/td>
 &lt;td>當初選 single 是對的&lt;/td>
 &lt;td>成本對稱、領域先驗強 → 當初仍該選 broadcast、留彈性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>用 sync API、後來都是 async&lt;/td>
 &lt;td>沒事或重構成本高&lt;/td>
 &lt;td>視結局而定&lt;/td>
 &lt;td>看當下三軸：簽章差異對稱、async 領域先驗強&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Hindsight 把「結局」當判斷依據 → 跟「後來剛好不需要」的 case 推出衝突結論。三軸論述用「當下選項屬性」當判斷依據 → 不依賴結局、可一致應用。&lt;/p>
&lt;h3 id="個人歸因-vs-制度歸因觀察性分歧不是必然對立">個人歸因 vs 制度歸因（觀察性分歧、不是必然對立）&lt;/h3>
&lt;p>Hindsight 論述&lt;strong>偏向&lt;/strong>個人歸因——「設計者沒預見」「沒多想」「沒考慮未來」——隱含「個人錯了」。但這不是 hindsight 的必然結果：成熟的事故報告（aviation post-mortem、medical incident report）即使用 hindsight 視角、也常透過 root cause analysis 歸因到系統 / 制度層級。&lt;/p>
&lt;p>當下三軸論述把判斷依據放在外部變數（工具預設、領域常識），歸因&lt;strong>自然偏向&lt;/strong>制度層——「工具預設選錯」「領域知識沒內化進團隊規範」。但寫作者仍可選擇用三軸論證後再歸因到個人（「三軸都指向 broadcast、但設計者選了 single」）。&lt;/p>
&lt;p>兩種論述在歸因方向上有偏差、但不是排他關係。本卡的主張不是「hindsight = 個人歸因、三軸 = 制度歸因」、而是「&lt;strong>三軸論證的歸因預設偏向制度、寫作者要明確選擇歸因層次&lt;/strong>」。&lt;/p>
&lt;p>兩種歸因引導的修補方向不同：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>個人歸因&lt;/strong> → 「下次更仔細」（無法行動的結論）&lt;/li>
&lt;li>&lt;strong>制度歸因&lt;/strong> → 「review checklist 加一條」「lint rule 警告」「架構規範禁掉」（可執行）&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="多面向跨情境的同個結構假設性對比">多面向：跨情境的同個結構（假設性對比）&lt;/h2>
&lt;p>下面 5 個面向是&lt;strong>假設性對比&lt;/strong>——本卡用相同 framework 推到 5 個情境、但只有面向 5（技術文章寫作）有對應的真實 case（dart Stream review）。其他 4 個面向（code review / post-mortem / ADR / 個人 retro）是 framework 在不同情境的推導、未驗證真實案例中兩種論述風格的差異。讀者套用時、優先在「跟本卡 case 結構接近」的情境使用、其他面向先當「待驗證的擴張」。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>1 個 case</strong>（<a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故</a> 的 review 過程）抽出來的假說、不是經過多個獨立 case 驗證的工程原則。具體限制：</p>
<ul>
<li>「成本對稱性 / 可逆性 / 領域先驗」三軸框架借自 yagni 篇的判斷工具、不是 industry standard</li>
<li>「hindsight 偏向個人歸因 / 三軸偏向制度歸因」是觀察性分歧、不是必然對立——實際事故報告（aviation / medical incident）也常用 hindsight 同時歸因到制度</li>
<li>5 個多面向 case（code review / post-mortem / ADR / retrospective / 寫作）是假設性對比、未驗證真實案例中兩種論述的差異</li>
</ul>
<p>讀者使用本卡時、把它當「<strong>這個 blog 提倡的判定方式</strong>」、不當「驗證過的工程原則」。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p>本卡提倡的「設計缺陷」判定方式是「<strong>在當下成本對稱條件下選了限制更高的選項</strong>」、用以替代依賴結局的 hindsight 判定。</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>事後諸葛論述（hindsight）</th>
          <th>當下三軸論證（current axes）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>視角</td>
          <td>已知結局、回頭看</td>
          <td>不知結局、看當下選擇</td>
      </tr>
      <tr>
          <td>判斷依據</td>
          <td>後來真的需要 X、所以當初該做 X</td>
          <td>當下三軸（成本對稱性 / 可逆性 / 領域先驗）都指向 X</td>
      </tr>
      <tr>
          <td>歸因方向</td>
          <td>設計者個人沒預見</td>
          <td>工具預設 + 領域知識制度</td>
      </tr>
      <tr>
          <td>教讀者什麼</td>
          <td>後見之明的具體規則</td>
          <td>當下能用的判斷工具</td>
      </tr>
      <tr>
          <td>泛化能力</td>
          <td>弱（只在類似 case 適用）</td>
          <td>強（可套到新情境）</td>
      </tr>
  </tbody>
</table>
<p>兩種論述讀起來都像在分析「設計缺陷」、但結論不同、可教性也不同。<strong>事後諸葛論述需要結局發生、當下三軸論證在當下就能判斷</strong>——後者才是 portable 工具。</p>
<hr>
<h2 id="為什麼-hindsight-不適合做設計缺陷判定">為什麼 hindsight 不適合做設計缺陷判定</h2>
<h3 id="hindsight-預設了結局不能在當下使用">Hindsight 預設了結局、不能在當下使用</h3>
<p>事後諸葛論述「StreamController() 被當廣播用了一段時間沒事、加第二個 listener 立刻炸 → 設計缺陷」隱含一個前提：讀者知道後來加了第二個 listener。</p>
<p>但設計者在當下不知道結局。如果讀者用這個論述當判斷工具、他要等到結局發生才知道「自己做錯了」——這不是判斷工具、是事後檢討。</p>
<p>當下三軸論述「在零成本差異 + 強領域先驗下選了限制更高的選項 → 設計缺陷」不需要等結局——讀者拿到的是「現在面對這類選擇、跑三軸、就能判斷」的工具。</p>
<h3 id="把判斷依據放在結局上會誤判類似情境">把判斷依據放在結局上、會誤判類似情境</h3>
<p>「結局是『後來需要多訂閱』 → 當初該選 broadcast」這個推論、套到不同議題會推出反向結論：</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>結局</th>
          <th>Hindsight 推論</th>
          <th>當下三軸推論</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>事先沒做 plugin、後來真的需要</td>
          <td>後來需要 plugin</td>
          <td>當初該建 → 過度設計</td>
          <td>高成本差、屬 YAGNI 適用 → 當初不做是對的</td>
      </tr>
      <tr>
          <td>用 single 預設、後來只有一個訂閱者</td>
          <td>沒事</td>
          <td>當初選 single 是對的</td>
          <td>成本對稱、領域先驗強 → 當初仍該選 broadcast、留彈性</td>
      </tr>
      <tr>
          <td>用 sync API、後來都是 async</td>
          <td>沒事或重構成本高</td>
          <td>視結局而定</td>
          <td>看當下三軸：簽章差異對稱、async 領域先驗強</td>
      </tr>
  </tbody>
</table>
<p>Hindsight 把「結局」當判斷依據 → 跟「後來剛好不需要」的 case 推出衝突結論。三軸論述用「當下選項屬性」當判斷依據 → 不依賴結局、可一致應用。</p>
<h3 id="個人歸因-vs-制度歸因觀察性分歧不是必然對立">個人歸因 vs 制度歸因（觀察性分歧、不是必然對立）</h3>
<p>Hindsight 論述<strong>偏向</strong>個人歸因——「設計者沒預見」「沒多想」「沒考慮未來」——隱含「個人錯了」。但這不是 hindsight 的必然結果：成熟的事故報告（aviation post-mortem、medical incident report）即使用 hindsight 視角、也常透過 root cause analysis 歸因到系統 / 制度層級。</p>
<p>當下三軸論述把判斷依據放在外部變數（工具預設、領域常識），歸因<strong>自然偏向</strong>制度層——「工具預設選錯」「領域知識沒內化進團隊規範」。但寫作者仍可選擇用三軸論證後再歸因到個人（「三軸都指向 broadcast、但設計者選了 single」）。</p>
<p>兩種論述在歸因方向上有偏差、但不是排他關係。本卡的主張不是「hindsight = 個人歸因、三軸 = 制度歸因」、而是「<strong>三軸論證的歸因預設偏向制度、寫作者要明確選擇歸因層次</strong>」。</p>
<p>兩種歸因引導的修補方向不同：</p>
<ul>
<li><strong>個人歸因</strong> → 「下次更仔細」（無法行動的結論）</li>
<li><strong>制度歸因</strong> → 「review checklist 加一條」「lint rule 警告」「架構規範禁掉」（可執行）</li>
</ul>
<hr>
<h2 id="多面向跨情境的同個結構假設性對比">多面向：跨情境的同個結構（假設性對比）</h2>
<p>下面 5 個面向是<strong>假設性對比</strong>——本卡用相同 framework 推到 5 個情境、但只有面向 5（技術文章寫作）有對應的真實 case（dart Stream review）。其他 4 個面向（code review / post-mortem / ADR / 個人 retro）是 framework 在不同情境的推導、未驗證真實案例中兩種論述風格的差異。讀者套用時、優先在「跟本卡 case 結構接近」的情境使用、其他面向先當「待驗證的擴張」。</p>
<h3 id="面向-1code-review--pr-審查">面向 1：Code review / PR 審查</h3>
<p>事後諸葛 review：「你這段 code 後來在 X 條件下會炸、所以當初該寫成 Y」</p>
<p>當下三軸 review：「在當下、Y 比 X 多打 N 個字元、領域先驗強烈指向 Y、可逆性中等偏高 → Y 是當下三軸對齊的選擇」</p>
<p>差別：reviewer 不需要等到 bug 發生、就能在 PR 階段給出判斷。Hindsight review 需要等 bug、其實是「事後追究」、不是「事前防護」。</p>
<h3 id="面向-2post-mortem--事故檢討">面向 2：Post-mortem / 事故檢討</h3>
<p>事後諸葛 PM：「Stream 的單訂閱限制在第二個訂閱者出現時暴露、所以是設計缺陷」</p>
<p>當下三軸 PM：「Stream 的單訂閱選擇在當下成本對稱條件下不必要地縮小未來空間、所以是設計缺陷」</p>
<p>差別：第二種論述讓「設計缺陷」這個判定不依賴「結局已發生」、讀者學到的是 portable 判斷工具。團隊裡其他成員看到這份 PM、能套用到沒有相同結局的新議題上。</p>
<h3 id="面向-3架構決策反思adr-retrospective">面向 3：架構決策反思（ADR retrospective）</h3>
<p>事後諸葛 retro：「我們選 SOAP、後來生態系全跑去 REST、所以 SOAP 是錯的」</p>
<p>當下三軸 retro：「選 SOAP 在當時的成本對稱性是 ⋯⋯、領域先驗是 ⋯⋯ → 在那個時間點屬於合理選擇 / 屬於設計缺陷」</p>
<p>差別：能區分「真的當時就該避開」vs「環境後來變了」。前者是設計缺陷、後者是健康的演化、兩者修補方向完全不同。</p>
<h3 id="面向-4個人-retrospective">面向 4：個人 retrospective</h3>
<p>事後諸葛自我檢討：「上次我沒考慮 X、結果出事 → 下次要考慮 X」</p>
<p>當下三軸自我檢討：「上次的選擇在當下三軸論述下對齊嗎？對齊 → 不算判斷力問題、是環境變化；不對齊 → 找出當時該抓到的訊號是什麼」</p>
<p>差別：避免不必要的自我責備、改善方向更精準。「下次要考慮 X」是 case-bound、套到下一個議題（不是 X）反而沒幫助；「下次跑三軸」是 portable。</p>
<h3 id="面向-5技術文章寫作">面向 5：技術文章寫作</h3>
<p>事後諸葛寫作：「[工具] 預設為 [限制版本]、被當 [通用版本] 用了一段時間沒事、後來出問題 → 設計缺陷」</p>
<p>當下三軸寫作：「[工具] 在當下零成本差異條件下選了限制更高的選項、領域先驗指向通用版本 → 設計缺陷」</p>
<p>差別：讀者學到 portable 判斷工具、不只是「這個 case 後來怎樣」的故事。文章的長期價值（被新讀者拿去用在新議題）大幅提升。</p>
<hr>
<h2 id="識別訊號什麼時候你正在用-hindsight-論述">識別訊號：什麼時候你正在用 hindsight 論述</h2>
<h3 id="訊號-1論述需要後來最終這類時序詞">訊號 1：論述需要「後來」「最終」這類時序詞</h3>
<p>「<strong>後來</strong>加了第二個訂閱者才炸」「<strong>最終</strong>發現 plugin 系統不需要」「事故<strong>爆發後</strong>才知道」——這些時序詞標記論述依賴結局。</p>
<p>修法：把時序詞拿掉、論述還站得住嗎？站不住 → 補當下軸的論證。</p>
<h3 id="訊號-2歸因落在個人能力--預見性">訊號 2：歸因落在個人能力 / 預見性</h3>
<p>「<strong>沒預見到</strong>」「<strong>沒考慮到</strong>」「<strong>沒多想</strong>」「<strong>疏忽</strong>」——把判斷錯誤歸給個人能力。當下三軸論述會把歸因放到「工具 / 領域常識」這類外部變數。</p>
<p>修法：把「沒預見到」改成「在當下、工具預設指向 X、領域先驗指向 Y、選擇者選了 Z」——歸因從個人轉到外部結構。</p>
<h3 id="訊號-3結論無法-portable">訊號 3：結論無法 portable</h3>
<p>「下次要考慮 X」——但「X」是這次的具體議題（多訂閱）、套到不同議題（plugin 系統）反而會推出反向結論。</p>
<p>修法：結論寫成「下次跑三軸」「下次跑 checklist」——是工具、不是 case-specific 規則。</p>
<h3 id="訊號-4讀者讀完只記得-case記不住原則">訊號 4：讀者讀完只記得 case、記不住原則</h3>
<p>讀者讀完事後諸葛論述、能複述 case、但問他「下次遇到不同議題怎麼判斷」答不出來——因為原則沒被抽出來、case-bound。</p>
<p>修法：在 case 之後補一段「抽象原則」、原則用語不綁定本 case 的具體名詞。</p>
<hr>
<h2 id="何時-hindsight-論述仍然合理">何時 hindsight 論述仍然合理</h2>
<p>「設計檢討用當下三軸、不依賴 hindsight」這條原則在大多數工程檢討情境成立、但有合理例外：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼 hindsight 仍合理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>真實事故 forensic 重現</td>
          <td>目的是還原時序與因果鏈、結局視角不可避免（但 root cause 仍要用三軸）</td>
      </tr>
      <tr>
          <td>學術 case study</td>
          <td>教學重點是「結局如何揭露結構」、hindsight 是 narrative 風格選擇</td>
      </tr>
      <tr>
          <td>個人日記 / 隨筆</td>
          <td>不是檢討文件、是記錄當下感受、不需要嚴格判斷工具</td>
      </tr>
      <tr>
          <td>純運氣 case（環境完全不可預測）</td>
          <td>例如外部 API 突然 deprecated、三軸無法事先抓 → 用 hindsight 描述合理</td>
      </tr>
      <tr>
          <td>教學「為什麼這個結局重要」</td>
          <td>重點是讓讀者理解結局的影響、不是教 portable 判斷工具</td>
      </tr>
  </tbody>
</table>
<p>判讀：寫之前自問「這份檢討是要產出 portable 判斷工具嗎？」——是 → 嚴格用三軸；否 → hindsight narrative 可接受。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>跟本卡的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></td>
          <td>hindsight 論述比三軸論述好寫（事後資料完整、結局明確）、但離 portable 意圖更遠</td>
      </tr>
      <tr>
          <td>YAGNI 三軸框架（成本對稱性 / 可逆性 / 領域先驗）</td>
          <td>本卡是三軸框架在「設計檢討寫作」面向的應用——把判斷工具寫進文章、而不是只寫結論</td>
      </tr>
      <tr>
          <td>Writing-articles 規則四：事後檢視看判讀品質</td>
          <td>本卡是規則四的進階——不只看判讀品質、還要避免結局視角偏差汙染判讀記錄</td>
      </tr>
      <tr>
          <td>Hindsight bias（認知科學）</td>
          <td>本卡把認知偏誤具體化到工程文章寫作層面、給可執行修法</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>論述用「後來」「最終」「結果」當主語</td>
          <td>改用「在當下、X 比 Y ⋯⋯」</td>
      </tr>
      <tr>
          <td>歸因落在「沒預見」「沒考慮」「沒多想」</td>
          <td>改成「工具預設選什麼 / 領域常識指向什麼 / 三軸怎麼跑」</td>
      </tr>
      <tr>
          <td>結論是「下次要記得 X」</td>
          <td>改成「下次跑三軸 / 跑 checklist」</td>
      </tr>
      <tr>
          <td>讀者複述只能複述 case</td>
          <td>補一段「抽象原則 + 套用到不同 case」</td>
      </tr>
      <tr>
          <td>文章在教「設計缺陷」但讀者要等到自己出事才懂</td>
          <td>補當下三軸論證、讓讀者在事前就能用</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：「設計缺陷」是當下成本對稱條件下選了限制更高的選項、不是事後發現需求變了。寫設計檢討時用三軸論證、避免讓判斷依賴於結局已發生——這樣讀者拿到的是 portable 判斷工具、不只是 case 故事。</p>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡的觸發是修 <a href="../../work-log/dart_stream_controller_single_vs_broadcast/">Dart StreamController：single-subscription vs broadcast 的事故實錄</a> 時的反思。</p>
<p>文章 v1 寫「StreamController() 預設為單訂閱、被當廣播用了一段時間沒事、加第二個 listener 立刻炸」——典型 hindsight 論述。</p>
<p>讀者反問：「如果只有一個人用沒問題、後來才需要多訂閱、這算設計缺陷嗎？」——這個反問正確 catch 了 hindsight 論述的薄弱處（依賴結局、不依賴當下選擇）。</p>
<p>修補後改寫：「在當下零成本差異條件下選了限制更高的選項」+ 加四格表釐清「需求演化 vs 設計缺陷」的分界——不依賴結局、用三軸論述。讀者拿到 portable 判斷工具、不只是 case 故事。</p>
<p>對應本卡：<strong>寫設計檢討時、第一版常常用 hindsight（因為事故已發生、視角自然帶結局）——要刻意 review 改成當下三軸、才會產出 portable 工具</strong>。這個 review 不會自動發生、需要 multi-pass review 流程在「規則三 / 規則四對齊」輪刻意檢查。</p>
]]></content:encoded></item><item><title>口語化修辭在判斷工具型段落會稀釋技術精度</title><link>https://tarrragon.github.io/blog/report/colloquial-rhetoric-erodes-technical-precision/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/colloquial-rhetoric-erodes-technical-precision/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>1 個 case&lt;/strong>（&lt;a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故的 review&lt;/a>）抽出來的觀察。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Keyword bank 是 starting set、不是 exhaustive list&lt;/strong>：列出的口語詞（一輩子 / 碰巧 / 撞牆 / 啊原來）都是這次 dart 篇出現過的、不代表「口語修辭的完整詞庫」。新類型出現時要持續擴充&lt;/li>
&lt;li>&lt;strong>「精度 vs 可讀性」是情境化取捨、不是 zero-sum&lt;/strong>：本卡聚焦「判斷工具型段落」（讀者要從中拿到 portable 工具的論述）、在這類段落精度優先；但 hook / 引言 / narrative 段落口語反而幫讀者進入論述、不適用本卡&lt;/li>
&lt;li>&lt;strong>Self-case 的修補有效性未獨立驗證&lt;/strong>：dart 篇修補後讀起來更精準、但「精準度跟讀者實際理解之間的相關性」沒做使用者測試&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、先判斷段落是否屬於「判斷工具型」——是 → 套用；否 → 評估口語跟可讀性的取捨。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>技術文章的「&lt;strong>判斷工具型段落&lt;/strong>」（讀者用來判斷自己 case 的論述）裡、用詞選擇要能對應到具體技術屬性。口語修辭（「一輩子」「碰巧」「立刻撞牆」「沒事」）讀起來流暢、但在這類段落會稀釋精度——精度標準是「&lt;strong>用詞能不能反推到具體機制 / 條件 / 契約&lt;/strong>」、口語修辭多半不能、寫了等於把判斷工具退化成感性印象。&lt;/p>
&lt;p>下面三個層次的稀釋是觀察到的 pattern——不是窮舉、實際違規模式可能更多：&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>「一輩子只能 X」&lt;/td>
 &lt;td>時間性誇張&lt;/td>
 &lt;td>永遠這樣（無範圍感）&lt;/td>
 &lt;td>生命週期內最多承載 1 次&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「碰巧能用」&lt;/td>
 &lt;td>因果模糊&lt;/td>
 &lt;td>運氣使然&lt;/td>
 &lt;td>觸發條件不滿足、限制處於沉默狀態&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「立刻撞牆」&lt;/td>
 &lt;td>結局描述代替契約描述&lt;/td>
 &lt;td>視覺意象、不知為什麼&lt;/td>
 &lt;td>違反型別契約、執行期 throw&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「沒事」&lt;/td>
 &lt;td>缺失條件描述&lt;/td>
 &lt;td>沒問題&lt;/td>
 &lt;td>限制存在、但沒有可見影響&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「整個炸了」&lt;/td>
 &lt;td>嚴重度誇張&lt;/td>
 &lt;td>知道很糟、不知糟在哪&lt;/td>
 &lt;td>違反契約導致 X 行為&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「啊原來 X」&lt;/td>
 &lt;td>結局視角的驚訝句&lt;/td>
 &lt;td>事後恍然大悟感&lt;/td>
 &lt;td>在 Y 條件下 X 才暴露&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="三個稀釋層次的具體-case">三個稀釋層次的具體 case&lt;/h2>
&lt;h3 id="層次-1時間性誇張">層次 1：時間性誇張&lt;/h3>
&lt;p>&lt;strong>口語版&lt;/strong>：「stream 一輩子只能被 listen 一次」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>「一輩子」沒有對應的技術概念——是「整個 process lifetime」？「stream object lifetime」？「listener cancel 之後也算嗎」？&lt;/li>
&lt;li>讀者要靠猜測決定範圍&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>精度版&lt;/strong>：「stream 在整個生命週期內只允許被 listen 一次（&lt;code>StreamController&lt;/code> object lifetime；&lt;code>cancel()&lt;/code> 之後再 &lt;code>listen()&lt;/code> 仍違反契約、要重建 &lt;code>StreamController&lt;/code>）」&lt;/p>
&lt;p>差別：精度版讓讀者能反推「我這個 case 屬於哪個範圍、會不會踩到」、口語版讀者只能感受「應該很嚴格」。&lt;/p>
&lt;h3 id="層次-2因果模糊">層次 2：因果模糊&lt;/h3>
&lt;p>&lt;strong>口語版&lt;/strong>：「碰巧能用掩蓋了設計缺陷」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>「碰巧」暗示運氣使然、機制不可解釋&lt;/li>
&lt;li>但實際上「能用」有明確的機制：訂閱者數量沒達到觸發違反契約的條件&lt;/li>
&lt;li>用「碰巧」會讓讀者學到「這是運氣問題」、不學到「這是條件未滿足的可預測現象」&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>精度版&lt;/strong>：「訂閱者單一時、限制處於沉默狀態」&lt;/p>
&lt;p>差別：精度版描述「為什麼沒影響」的具體條件、口語版只描述「結果」。讀者能用精度版去判斷自己的 case 何時會觸發、不能用口語版做同樣的判斷。&lt;/p>
&lt;h3 id="層次-3結局描述代替契約描述">層次 3：結局描述代替契約描述&lt;/h3>
&lt;p>&lt;strong>口語版&lt;/strong>：「新加第二個訂閱者就立刻撞牆」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>「撞牆」是視覺意象、不是技術描述&lt;/li>
&lt;li>讀者拿到的是「發生了不好的事」、不是「為什麼發生」「在哪一層發生」&lt;/li>
&lt;li>套到不同 case（如「使用 cancelled stream」「使用 closed controller」）會推不出對應的修法&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>精度版&lt;/strong>：「新加第二個訂閱者直接違反契約、執行期 throw」&lt;/p>
&lt;p>差別：精度版指明「違反的是什麼（契約）」「在哪個時間點（執行期）」「具體後果（throw）」、讀者能 generalize 到其他違反契約的情境。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼口語修辭會出現">為什麼口語修辭會出現&lt;/h2>
&lt;p>技術寫作中口語修辭的出現有三類典型來源：&lt;/p>
&lt;h3 id="來源-1寫的當下感性敘事比技術敘事好寫">來源 1：寫的當下感性敘事比技術敘事好寫&lt;/h3>
&lt;p>「一輩子只能 listen 一次」比「整個 lifecycle 只允許被 listen 一次」少 5 個字、寫起來順、語氣強烈。但精度也差距 5 倍。寫作便利度高的版本通常離精度遠（&lt;a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關&lt;/a> 的同骨——寫得順 ≠ 寫得對）。&lt;/p>
&lt;h3 id="來源-2對讀者直覺感受的妥協">來源 2：對讀者「直覺感受」的妥協&lt;/h3>
&lt;p>「碰巧能用」這類詞讓讀者「立刻有共鳴」、感覺像在讀故事。但技術文章的讀者來這裡找的是判斷工具、不是故事——共鳴感換來精度損失、是錯誤的取捨。&lt;/p>
&lt;h3 id="來源-3誤把事故當下的反應當成論述用詞">來源 3：誤把「事故當下的反應」當成「論述用詞」&lt;/h3>
&lt;p>事故當下工程師的內心 OS 確實是「啊原來這個 mutation 路徑沒帶」「進入頁面就炸」——這些是當下的口語反應。寫成正式論述時要把這些反應翻譯回技術描述、保留意圖（驚訝 / 嚴重程度）但不保留口語形式。&lt;/p>
&lt;hr>
&lt;h2 id="識別訊號什麼時候你在用口語修辭">識別訊號：什麼時候你在用口語修辭&lt;/h2>
&lt;h3 id="訊號-1時間--範圍誇張詞">訊號 1：時間 / 範圍誇張詞&lt;/h3>
&lt;p>「一輩子」「永遠」「整個炸了」「全部 GG」「直接死」——這類詞沒有對應的技術範圍、用了讀者要靠猜測。&lt;/p>
&lt;p>修法：問「具體是哪個範圍 / 哪個生命週期 / 哪個 scope？」、把答案寫進去取代誇張詞。&lt;/p>
&lt;h3 id="訊號-2運氣--巧合語氣">訊號 2：運氣 / 巧合語氣&lt;/h3>
&lt;p>「碰巧」「剛好」「湊巧」「運氣好」——這類詞遮蔽了背後的機制。技術系統的行為幾乎都有可解釋的條件、不是運氣。&lt;/p>
&lt;p>修法：問「為什麼當下沒發生？是哪個條件沒滿足？」、把條件寫出來取代運氣語氣。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>1 個 case</strong>（<a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故的 review</a>）抽出來的觀察。具體限制：</p>
<ul>
<li><strong>Keyword bank 是 starting set、不是 exhaustive list</strong>：列出的口語詞（一輩子 / 碰巧 / 撞牆 / 啊原來）都是這次 dart 篇出現過的、不代表「口語修辭的完整詞庫」。新類型出現時要持續擴充</li>
<li><strong>「精度 vs 可讀性」是情境化取捨、不是 zero-sum</strong>：本卡聚焦「判斷工具型段落」（讀者要從中拿到 portable 工具的論述）、在這類段落精度優先；但 hook / 引言 / narrative 段落口語反而幫讀者進入論述、不適用本卡</li>
<li><strong>Self-case 的修補有效性未獨立驗證</strong>：dart 篇修補後讀起來更精準、但「精準度跟讀者實際理解之間的相關性」沒做使用者測試</li>
</ul>
<p>讀者使用本卡時、先判斷段落是否屬於「判斷工具型」——是 → 套用；否 → 評估口語跟可讀性的取捨。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p>技術文章的「<strong>判斷工具型段落</strong>」（讀者用來判斷自己 case 的論述）裡、用詞選擇要能對應到具體技術屬性。口語修辭（「一輩子」「碰巧」「立刻撞牆」「沒事」）讀起來流暢、但在這類段落會稀釋精度——精度標準是「<strong>用詞能不能反推到具體機制 / 條件 / 契約</strong>」、口語修辭多半不能、寫了等於把判斷工具退化成感性印象。</p>
<p>下面三個層次的稀釋是觀察到的 pattern——不是窮舉、實際違規模式可能更多：</p>
<table>
  <thead>
      <tr>
          <th>口語修辭</th>
          <th>稀釋的層次</th>
          <th>讀者拿到的訊息</th>
          <th>真實技術屬性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「一輩子只能 X」</td>
          <td>時間性誇張</td>
          <td>永遠這樣（無範圍感）</td>
          <td>生命週期內最多承載 1 次</td>
      </tr>
      <tr>
          <td>「碰巧能用」</td>
          <td>因果模糊</td>
          <td>運氣使然</td>
          <td>觸發條件不滿足、限制處於沉默狀態</td>
      </tr>
      <tr>
          <td>「立刻撞牆」</td>
          <td>結局描述代替契約描述</td>
          <td>視覺意象、不知為什麼</td>
          <td>違反型別契約、執行期 throw</td>
      </tr>
      <tr>
          <td>「沒事」</td>
          <td>缺失條件描述</td>
          <td>沒問題</td>
          <td>限制存在、但沒有可見影響</td>
      </tr>
      <tr>
          <td>「整個炸了」</td>
          <td>嚴重度誇張</td>
          <td>知道很糟、不知糟在哪</td>
          <td>違反契約導致 X 行為</td>
      </tr>
      <tr>
          <td>「啊原來 X」</td>
          <td>結局視角的驚訝句</td>
          <td>事後恍然大悟感</td>
          <td>在 Y 條件下 X 才暴露</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="三個稀釋層次的具體-case">三個稀釋層次的具體 case</h2>
<h3 id="層次-1時間性誇張">層次 1：時間性誇張</h3>
<p><strong>口語版</strong>：「stream 一輩子只能被 listen 一次」</p>
<p><strong>問題</strong>：</p>
<ul>
<li>「一輩子」沒有對應的技術概念——是「整個 process lifetime」？「stream object lifetime」？「listener cancel 之後也算嗎」？</li>
<li>讀者要靠猜測決定範圍</li>
</ul>
<p><strong>精度版</strong>：「stream 在整個生命週期內只允許被 listen 一次（<code>StreamController</code> object lifetime；<code>cancel()</code> 之後再 <code>listen()</code> 仍違反契約、要重建 <code>StreamController</code>）」</p>
<p>差別：精度版讓讀者能反推「我這個 case 屬於哪個範圍、會不會踩到」、口語版讀者只能感受「應該很嚴格」。</p>
<h3 id="層次-2因果模糊">層次 2：因果模糊</h3>
<p><strong>口語版</strong>：「碰巧能用掩蓋了設計缺陷」</p>
<p><strong>問題</strong>：</p>
<ul>
<li>「碰巧」暗示運氣使然、機制不可解釋</li>
<li>但實際上「能用」有明確的機制：訂閱者數量沒達到觸發違反契約的條件</li>
<li>用「碰巧」會讓讀者學到「這是運氣問題」、不學到「這是條件未滿足的可預測現象」</li>
</ul>
<p><strong>精度版</strong>：「訂閱者單一時、限制處於沉默狀態」</p>
<p>差別：精度版描述「為什麼沒影響」的具體條件、口語版只描述「結果」。讀者能用精度版去判斷自己的 case 何時會觸發、不能用口語版做同樣的判斷。</p>
<h3 id="層次-3結局描述代替契約描述">層次 3：結局描述代替契約描述</h3>
<p><strong>口語版</strong>：「新加第二個訂閱者就立刻撞牆」</p>
<p><strong>問題</strong>：</p>
<ul>
<li>「撞牆」是視覺意象、不是技術描述</li>
<li>讀者拿到的是「發生了不好的事」、不是「為什麼發生」「在哪一層發生」</li>
<li>套到不同 case（如「使用 cancelled stream」「使用 closed controller」）會推不出對應的修法</li>
</ul>
<p><strong>精度版</strong>：「新加第二個訂閱者直接違反契約、執行期 throw」</p>
<p>差別：精度版指明「違反的是什麼（契約）」「在哪個時間點（執行期）」「具體後果（throw）」、讀者能 generalize 到其他違反契約的情境。</p>
<hr>
<h2 id="為什麼口語修辭會出現">為什麼口語修辭會出現</h2>
<p>技術寫作中口語修辭的出現有三類典型來源：</p>
<h3 id="來源-1寫的當下感性敘事比技術敘事好寫">來源 1：寫的當下感性敘事比技術敘事好寫</h3>
<p>「一輩子只能 listen 一次」比「整個 lifecycle 只允許被 listen 一次」少 5 個字、寫起來順、語氣強烈。但精度也差距 5 倍。寫作便利度高的版本通常離精度遠（<a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a> 的同骨——寫得順 ≠ 寫得對）。</p>
<h3 id="來源-2對讀者直覺感受的妥協">來源 2：對讀者「直覺感受」的妥協</h3>
<p>「碰巧能用」這類詞讓讀者「立刻有共鳴」、感覺像在讀故事。但技術文章的讀者來這裡找的是判斷工具、不是故事——共鳴感換來精度損失、是錯誤的取捨。</p>
<h3 id="來源-3誤把事故當下的反應當成論述用詞">來源 3：誤把「事故當下的反應」當成「論述用詞」</h3>
<p>事故當下工程師的內心 OS 確實是「啊原來這個 mutation 路徑沒帶」「進入頁面就炸」——這些是當下的口語反應。寫成正式論述時要把這些反應翻譯回技術描述、保留意圖（驚訝 / 嚴重程度）但不保留口語形式。</p>
<hr>
<h2 id="識別訊號什麼時候你在用口語修辭">識別訊號：什麼時候你在用口語修辭</h2>
<h3 id="訊號-1時間--範圍誇張詞">訊號 1：時間 / 範圍誇張詞</h3>
<p>「一輩子」「永遠」「整個炸了」「全部 GG」「直接死」——這類詞沒有對應的技術範圍、用了讀者要靠猜測。</p>
<p>修法：問「具體是哪個範圍 / 哪個生命週期 / 哪個 scope？」、把答案寫進去取代誇張詞。</p>
<h3 id="訊號-2運氣--巧合語氣">訊號 2：運氣 / 巧合語氣</h3>
<p>「碰巧」「剛好」「湊巧」「運氣好」——這類詞遮蔽了背後的機制。技術系統的行為幾乎都有可解釋的條件、不是運氣。</p>
<p>修法：問「為什麼當下沒發生？是哪個條件沒滿足？」、把條件寫出來取代運氣語氣。</p>
<h3 id="訊號-3視覺意象--動作比喻">訊號 3：視覺意象 / 動作比喻</h3>
<p>「撞牆」「炸了」「鎖死」「卡住」「當機」（口語的，不是技術術語的 hang/freeze）——這些是事件的視覺描述、不是契約 / 機制描述。</p>
<p>修法：問「在哪一層、違反了什麼、執行期表現是什麼？」、把答案寫出來取代視覺比喻。</p>
<h3 id="訊號-4結局視角的驚訝句">訊號 4：結局視角的驚訝句</h3>
<p>「啊原來」「結果發現」「最後才知道」——這些把讀者帶到「事故已發生、回頭看」的視角、依賴 hindsight。</p>
<p>修法：問「在事前、什麼條件成立時這個 X 才會出現？」、改成事前可判斷的描述。詳細處理見 <a href="../design-flaw-by-current-axes-not-hindsight/">#110 設計檢討用當下三軸論證、不依賴 hindsight</a>。</p>
<h3 id="訊號-5沒事沒問題當成段落結論">訊號 5：「沒事」「沒問題」當成段落結論</h3>
<p>「運作正常」「沒事」「沒問題」「一切看起來都好」——這類詞代替了「在哪些條件下沒可見影響」的具體描述、暗示「不需要進一步審視」。</p>
<p>修法：問「沒影響是因為什麼條件沒觸發？換條件會怎樣？」、把條件寫出來取代「沒事」。</p>
<h3 id="訊號-6下次-x-時做-y結尾段">訊號 6：「下次 X 時、做 Y」結尾段</h3>
<p>「下次看到 X 時、先問 Y」「下次寫 Z 時、想 W」「下次面對 V 時、停下來」——這類段落想給讀者實踐建議、但有兩個結構問題：</p>
<ol>
<li><strong>前綴是 wrapper、不增加資訊</strong>：讀者來讀這段的脈絡通常已經是「正在處理 X」、「下次看到 X 時」對讀者是廢話、把重點推到後面（違反規則五「最重要的話優先說」）</li>
<li><strong>預設讀者會主動回憶</strong>：「下次 X 時做 Y」假設讀者下次會自動想起這條建議、實際上讀者多半不會主動 recall——應該寫成「<strong>判斷工具</strong>」而不是「<strong>回憶指令</strong>」</li>
</ol>
<p>修法：把 wrapper 拿掉、把建議改寫成判斷工具的形式：</p>
<table>
  <thead>
      <tr>
          <th>修補前</th>
          <th>修補後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>下次看到 <code>Bad state</code> 時、不要先想「我寫錯了」</td>
          <td>根因落在 stream 定義端的型別契約、不在訂閱端</td>
      </tr>
      <tr>
          <td>下次寫 test 時、想「這份 file 是唯一 doc 嗎」</td>
          <td>把「這份 file 是模組唯一 doc」當命名的質量門檻</td>
      </tr>
      <tr>
          <td>下次看到自己寫三行 doc、停下來想能不能變型別</td>
          <td>寫到「三行 doc 解釋輸入範圍」這個訊號時、自問能不能變型別簽章</td>
      </tr>
  </tbody>
</table>
<p>差別：修補前是「下次 X 時、做 Y」的 hortative 命令；修補後是「<strong>遇到 X 訊號時、用 Y 工具判斷</strong>」的 reactive 工具。前者依賴讀者主動 recall、後者由訊號觸發判斷。</p>
<p>注意 ≠「描述讀者的具體情境」：</p>
<blockquote>
<p>「讀者讀完事後諸葛論述、能複述 case、但問他<strong>下次遇到不同議題怎麼判斷</strong>答不出來」</p></blockquote>
<p>這個「下次遇到 X」是描述讀者的測驗情境（檢驗論述是否 portable）、不是給讀者的指令——保留合理。</p>
<hr>
<h2 id="何時口語修辭仍然合理">何時口語修辭仍然合理</h2>
<p>「精度優先」這條原則在大多數技術論述情境成立、但有合理例外：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼口語仍合理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>對話 / 訊息 / Slack 討論</td>
          <td>即時溝通、共識在場、口語反而更快建立 mutual understanding</td>
      </tr>
      <tr>
          <td>個人筆記 / scratchpad</td>
          <td>寫給自己看、知道自己當下在想什麼、不需要對他人精度</td>
      </tr>
      <tr>
          <td>故事性引言 / hook 段</td>
          <td>文章開頭吸引讀者、口語可暫時用、但很快要切回精度敘事</td>
      </tr>
      <tr>
          <td>引用當事人的反應 / 直接 quote</td>
          <td>「事故當下工程師說『啊我哪裡寫錯了』」是引用、保留口語反映真實心境</td>
      </tr>
      <tr>
          <td>反例段落（教讀者「不要這樣寫」）</td>
          <td>故意用口語版讓讀者看到差別、然後切到精度版</td>
      </tr>
  </tbody>
</table>
<p>判讀：寫之前自問「讀者拿這段去做技術判斷時、口語修辭會不會讓判斷模糊？」——會 → 翻成精度版；不會 → 口語可接受。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>跟本卡的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></td>
          <td>口語修辭比精度敘事好寫——但精度才是讀者要的工具、便利 vs 對齊的同骨展現</td>
      </tr>
      <tr>
          <td><a href="../design-flaw-by-current-axes-not-hindsight/">#110 設計檢討用當下三軸論證、不依賴 hindsight</a></td>
          <td>「啊原來」「碰巧」這類詞天生帶 hindsight 視角、本卡是 #110 在「字句層級」的延伸</td>
      </tr>
      <tr>
          <td>Compositional-writing 規則一：階段分層（觀察 → 判讀 → 策略 → 執行）</td>
          <td>口語修辭多半混淆四階段——「立刻撞牆」混了觀察跟判讀、要拆開重寫</td>
      </tr>
      <tr>
          <td>Compositional-writing 規則二：商業邏輯先於 CASE</td>
          <td>「碰巧能用」隱藏商業邏輯（為什麼能用）、本卡要求把商業邏輯顯式寫出來</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>段落讀起來「順」「有畫面」「像故事」</td>
          <td>停下來掃口語修辭、問「這個詞對應什麼具體技術屬性？」</td>
      </tr>
      <tr>
          <td>用了「一輩子」「永遠」「整個」這類絕對詞</td>
          <td>換成具體生命週期 / scope</td>
      </tr>
      <tr>
          <td>用了「碰巧」「剛好」這類運氣語氣</td>
          <td>找出背後的機制條件、寫出條件</td>
      </tr>
      <tr>
          <td>用了「撞牆」「炸了」這類視覺意象</td>
          <td>換成「違反 X 契約 / 在 Y 時刻 throw / 觸發 Z error」</td>
      </tr>
      <tr>
          <td>用了「啊原來」「結果發現」</td>
          <td>改成事前可判斷的條件描述</td>
      </tr>
      <tr>
          <td>用了「沒事」當段落結論</td>
          <td>補「在 X 條件下沒影響、換 Y 條件會怎樣」</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：技術文章的用詞要能反推到具體機制 / 條件 / 契約。口語修辭的便利在於寫得順、代價是讀者拿不到判斷工具。寫完每段後跑一次「這個詞對應什麼具體技術屬性？」自問、答不出來的詞就要翻譯。</p>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡的觸發是修 <a href="../../work-log/dart_stream_controller_single_vs_broadcast/">Dart StreamController：single-subscription vs broadcast 的事故實錄</a> 的第二輪審查。</p>
<p>讀者指出該文有四處口語化問題：「stream 一輩子只能被 listen 一次」「進入頁面就炸」「現在只要有人訂閱、把它記錄下來，UI 就能用」「碰巧能用掩蓋了設計缺陷」。修補時的觀察是這些不是孤立問題、是「<strong>口語修辭代替技術描述</strong>」這個共通 frame 在不同句子的展現。</p>
<p>修補後對比：</p>
<table>
  <thead>
      <tr>
          <th>修補前</th>
          <th>修補後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>stream 一輩子只能被 listen 一次</td>
          <td>整個生命週期內只允許被 listen 一次（<code>StreamController</code> object lifetime）</td>
      </tr>
      <tr>
          <td>進入頁面就炸</td>
          <td>第二個訂閱者觸發底層限制</td>
      </tr>
      <tr>
          <td>立刻撞牆</td>
          <td>直接違反契約、執行期 throw</td>
      </tr>
      <tr>
          <td>碰巧能用</td>
          <td>限制處於沉默狀態（觸發條件不滿足）</td>
      </tr>
      <tr>
          <td>啊原來這個 mutation 路徑沒帶</td>
          <td>暴露出某些 mutation 路徑沒填寫該欄位</td>
      </tr>
  </tbody>
</table>
<p>每一組修補都把「口語視覺意象」翻譯回「技術屬性 + 條件 + 契約」。讀者拿到的是可反推的判斷工具、不是感性印象。</p>
<p>對應本卡：<strong>口語修辭的稀釋是字句層級的、容易在第一輪寫作後被忽略——multi-pass review 要在輪 4「Grep-ability / 命名 / 術語」加掃這個 frame、用 grep 找口語詞庫</strong>。</p>
]]></content:encoded></item><item><title>地區用語對齊：寫作前先確定讀者的中文語料</title><link>https://tarrragon.github.io/blog/report/regional-terminology-alignment/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/regional-terminology-alignment/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>1 個 case&lt;/strong>（&lt;a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故的 review&lt;/a> 中讀者點出「副屏」是中國用語）抽出來的觀察。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>詞庫表是分布偏差、不是絕對對立&lt;/strong>：「函數 vs 函式」「介面 vs 接口」這類詞在兩岸都有人用、只是分布偏好不同。本卡的「漂移代價」是觀察性敘述、不是嚴格的語言學分類&lt;/li>
&lt;li>&lt;strong>部分詞的判定可能不準&lt;/strong>：例如「文件」在台灣 IT 圈也常用來指 file（Windows 檔案總管的「文件」資料夾用了二十年）、「視頻」近年也滲透台灣年輕人語料——本卡列為「中國用語」是偏向 IT 業界傳統用法的 heuristic、不適用所有讀者群&lt;/li>
&lt;li>&lt;strong>沒有量化資料支撐「對映成本」&lt;/strong>：本卡描述「累積性的微秒級對映成本」是直覺論述、未做使用者測試&lt;/li>
&lt;li>&lt;strong>預設台灣讀者&lt;/strong>：本卡用「對台灣讀者寫作」當預設、實際讀者群可能跨地區、預設單一地區可能 over-narrow&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、把詞庫表當「&lt;strong>這個 blog 為台灣 IT 工程師讀者預設的用詞偏好&lt;/strong>」、不當「兩岸標準語料對照表」。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>中文技術寫作的用詞精度受&lt;strong>讀者的地區語料&lt;/strong>影響——同一個概念在繁中跟簡中可能用完全不同的詞、或用同一個詞但語意稍微偏移。寫作前先確定讀者的中文語料、避免用對方語料中不存在或意思偏移的詞。&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>屏 / 副屏&lt;/td>
 &lt;td>讀者要多花一次對映、且暗示寫作者地區&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>檔案系統&lt;/td>
 &lt;td>檔案 / 資料夾&lt;/td>
 &lt;td>文件 / 文件夾&lt;/td>
 &lt;td>「文件」在繁中既可指 document（公文書）、也可指 file（檔案總管的「文件」資料夾）、用法分歧&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>預設值&lt;/td>
 &lt;td>預設&lt;/td>
 &lt;td>默認&lt;/td>
 &lt;td>「默認」在繁中是「沉默接受」、語意不同&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>品質 / 質量&lt;/td>
 &lt;td>品質&lt;/td>
 &lt;td>質量&lt;/td>
 &lt;td>「質量」在繁中是 mass / weight、技術文章誤用嚴重&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>視訊 / 影片&lt;/td>
 &lt;td>影片 / 視訊&lt;/td>
 &lt;td>視頻 / 視屏&lt;/td>
 &lt;td>「視頻」在繁中傳統較少用、但近年滲透增加&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>程式設計術語&lt;/td>
 &lt;td>函式 / 變數&lt;/td>
 &lt;td>函數 / 變量&lt;/td>
 &lt;td>「函數」「函式」兩岸都通用、但業界（尤其 Dart / Swift / TypeScript 社群）偏好「函式」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>業務術語&lt;/td>
 &lt;td>訂單 / 結帳&lt;/td>
 &lt;td>訂單 / 收銀&lt;/td>
 &lt;td>「收銀」兩邊通用、但「結帳」在繁中更常用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>介面 / 接口&lt;/td>
 &lt;td>介面&lt;/td>
 &lt;td>接口&lt;/td>
 &lt;td>「介面」在繁中明確指 interface&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>內存 / 記憶體&lt;/td>
 &lt;td>記憶體&lt;/td>
 &lt;td>內存&lt;/td>
 &lt;td>「內存」在繁中是「內部存放」、不是 memory&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>技術文章的精度標準是「&lt;strong>讀者用自己的語料能正確 parse 你的句子&lt;/strong>」。用錯地區用語、輕則增加讀者的對映成本（雖然可讀但不順）、重則造成語意誤判（如「文件」當 file 用、繁中讀者預期是 document）。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼地區用語會漂移">為什麼地區用語會漂移&lt;/h2>
&lt;h3 id="來源-1訓練語料--參考材料來源">來源 1：訓練語料 / 參考材料來源&lt;/h3>
&lt;p>技術寫作者常從中國技術社群、AI 工具（早期 LLM 的中文訓練資料以簡中為主）、open source 文件抓參考材料。複製時容易帶進原語料的用詞。&lt;/p>
&lt;h3 id="來源-2技術圈的-stack-overflow-效應">來源 2：技術圈的 Stack Overflow 效應&lt;/h3>
&lt;p>部分技術術語在簡中社群有大量內容、繁中相對少。寫作時搜尋資料、看到簡中版本的解釋、不自覺套用對方用詞。&lt;/p>
&lt;h3 id="來源-3讀得懂就好的低估">來源 3：「讀得懂就好」的低估&lt;/h3>
&lt;p>「副屏 vs 副螢幕、讀者應該都看得懂」——這個假設在「個別詞」層級成立、但在「整篇文章」層級會累積：每個詞累積一次對映成本、整篇加起來幾十個詞、讀者的認知負擔會增加。&lt;/p>
&lt;h3 id="來源-4跨地區團隊的混合語料">來源 4：跨地區團隊的混合語料&lt;/h3>
&lt;p>跨地區團隊（台灣 + 中國 + 香港 + 馬來西亞）的工程師常混用兩邊用詞。內部溝通沒問題、但寫成對外文章時要選定一個地區的語料對齊。&lt;/p>
&lt;hr>
&lt;h2 id="識別訊號什麼時候你在用錯地區用語">識別訊號：什麼時候你在用錯地區用語&lt;/h2>
&lt;h3 id="訊號-1技術術語有兩個常見譯法">訊號 1：技術術語有兩個常見譯法&lt;/h3>
&lt;p>「函式 vs 函數」「介面 vs 接口」「預設 vs 默認」「記憶體 vs 內存」——這類詞兩邊都有用、但分布偏向不同地區。&lt;/p>
&lt;p>修法：選定讀者地區的版本、全篇統一。對台灣讀者寫作時用「函式 / 介面 / 預設 / 記憶體」。&lt;/p>
&lt;h3 id="訊號-2硬體--業務名詞用了單字版本">訊號 2：硬體 / 業務名詞用了單字版本&lt;/h3>
&lt;p>「屏」「網盤」「U 盤」「光盤」——簡中習慣用單字、繁中習慣用兩字以上。&lt;/p>
&lt;p>修法：「螢幕 / 雲端硬碟 / USB 隨身碟 / 光碟」。&lt;/p>
&lt;h3 id="訊號-3質量當品質用">訊號 3:「質量」當品質用&lt;/h3>
&lt;p>「程式碼質量」「服務質量」——繁中「質量」是 mass、用「品質」較精確。&lt;/p>
&lt;p>修法：technical quality → 品質；mass / weight → 質量。&lt;/p>
&lt;h3 id="訊號-4視頻--視屏用在繁中文章">訊號 4：「視頻 / 視屏」用在繁中文章&lt;/h3>
&lt;p>「教學視頻」「示範視屏」——繁中傳統用「影片」、但「視頻」近年滲透。對 IT 工程師讀者寫作時、用「影片」更貼合主流偏好。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>1 個 case</strong>（<a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故的 review</a> 中讀者點出「副屏」是中國用語）抽出來的觀察。具體限制：</p>
<ul>
<li><strong>詞庫表是分布偏差、不是絕對對立</strong>：「函數 vs 函式」「介面 vs 接口」這類詞在兩岸都有人用、只是分布偏好不同。本卡的「漂移代價」是觀察性敘述、不是嚴格的語言學分類</li>
<li><strong>部分詞的判定可能不準</strong>：例如「文件」在台灣 IT 圈也常用來指 file（Windows 檔案總管的「文件」資料夾用了二十年）、「視頻」近年也滲透台灣年輕人語料——本卡列為「中國用語」是偏向 IT 業界傳統用法的 heuristic、不適用所有讀者群</li>
<li><strong>沒有量化資料支撐「對映成本」</strong>：本卡描述「累積性的微秒級對映成本」是直覺論述、未做使用者測試</li>
<li><strong>預設台灣讀者</strong>：本卡用「對台灣讀者寫作」當預設、實際讀者群可能跨地區、預設單一地區可能 over-narrow</li>
</ul>
<p>讀者使用本卡時、把詞庫表當「<strong>這個 blog 為台灣 IT 工程師讀者預設的用詞偏好</strong>」、不當「兩岸標準語料對照表」。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p>中文技術寫作的用詞精度受<strong>讀者的地區語料</strong>影響——同一個概念在繁中跟簡中可能用完全不同的詞、或用同一個詞但語意稍微偏移。寫作前先確定讀者的中文語料、避免用對方語料中不存在或意思偏移的詞。</p>
<table>
  <thead>
      <tr>
          <th>概念類別</th>
          <th>繁中（台灣）</th>
          <th>簡中（中國）</th>
          <th>漂移代價</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>硬體 / 顯示</td>
          <td>螢幕 / 副螢幕</td>
          <td>屏 / 副屏</td>
          <td>讀者要多花一次對映、且暗示寫作者地區</td>
      </tr>
      <tr>
          <td>檔案系統</td>
          <td>檔案 / 資料夾</td>
          <td>文件 / 文件夾</td>
          <td>「文件」在繁中既可指 document（公文書）、也可指 file（檔案總管的「文件」資料夾）、用法分歧</td>
      </tr>
      <tr>
          <td>預設值</td>
          <td>預設</td>
          <td>默認</td>
          <td>「默認」在繁中是「沉默接受」、語意不同</td>
      </tr>
      <tr>
          <td>品質 / 質量</td>
          <td>品質</td>
          <td>質量</td>
          <td>「質量」在繁中是 mass / weight、技術文章誤用嚴重</td>
      </tr>
      <tr>
          <td>視訊 / 影片</td>
          <td>影片 / 視訊</td>
          <td>視頻 / 視屏</td>
          <td>「視頻」在繁中傳統較少用、但近年滲透增加</td>
      </tr>
      <tr>
          <td>程式設計術語</td>
          <td>函式 / 變數</td>
          <td>函數 / 變量</td>
          <td>「函數」「函式」兩岸都通用、但業界（尤其 Dart / Swift / TypeScript 社群）偏好「函式」</td>
      </tr>
      <tr>
          <td>業務術語</td>
          <td>訂單 / 結帳</td>
          <td>訂單 / 收銀</td>
          <td>「收銀」兩邊通用、但「結帳」在繁中更常用</td>
      </tr>
      <tr>
          <td>介面 / 接口</td>
          <td>介面</td>
          <td>接口</td>
          <td>「介面」在繁中明確指 interface</td>
      </tr>
      <tr>
          <td>內存 / 記憶體</td>
          <td>記憶體</td>
          <td>內存</td>
          <td>「內存」在繁中是「內部存放」、不是 memory</td>
      </tr>
  </tbody>
</table>
<p>技術文章的精度標準是「<strong>讀者用自己的語料能正確 parse 你的句子</strong>」。用錯地區用語、輕則增加讀者的對映成本（雖然可讀但不順）、重則造成語意誤判（如「文件」當 file 用、繁中讀者預期是 document）。</p>
<hr>
<h2 id="為什麼地區用語會漂移">為什麼地區用語會漂移</h2>
<h3 id="來源-1訓練語料--參考材料來源">來源 1：訓練語料 / 參考材料來源</h3>
<p>技術寫作者常從中國技術社群、AI 工具（早期 LLM 的中文訓練資料以簡中為主）、open source 文件抓參考材料。複製時容易帶進原語料的用詞。</p>
<h3 id="來源-2技術圈的-stack-overflow-效應">來源 2：技術圈的 Stack Overflow 效應</h3>
<p>部分技術術語在簡中社群有大量內容、繁中相對少。寫作時搜尋資料、看到簡中版本的解釋、不自覺套用對方用詞。</p>
<h3 id="來源-3讀得懂就好的低估">來源 3：「讀得懂就好」的低估</h3>
<p>「副屏 vs 副螢幕、讀者應該都看得懂」——這個假設在「個別詞」層級成立、但在「整篇文章」層級會累積：每個詞累積一次對映成本、整篇加起來幾十個詞、讀者的認知負擔會增加。</p>
<h3 id="來源-4跨地區團隊的混合語料">來源 4：跨地區團隊的混合語料</h3>
<p>跨地區團隊（台灣 + 中國 + 香港 + 馬來西亞）的工程師常混用兩邊用詞。內部溝通沒問題、但寫成對外文章時要選定一個地區的語料對齊。</p>
<hr>
<h2 id="識別訊號什麼時候你在用錯地區用語">識別訊號：什麼時候你在用錯地區用語</h2>
<h3 id="訊號-1技術術語有兩個常見譯法">訊號 1：技術術語有兩個常見譯法</h3>
<p>「函式 vs 函數」「介面 vs 接口」「預設 vs 默認」「記憶體 vs 內存」——這類詞兩邊都有用、但分布偏向不同地區。</p>
<p>修法：選定讀者地區的版本、全篇統一。對台灣讀者寫作時用「函式 / 介面 / 預設 / 記憶體」。</p>
<h3 id="訊號-2硬體--業務名詞用了單字版本">訊號 2：硬體 / 業務名詞用了單字版本</h3>
<p>「屏」「網盤」「U 盤」「光盤」——簡中習慣用單字、繁中習慣用兩字以上。</p>
<p>修法：「螢幕 / 雲端硬碟 / USB 隨身碟 / 光碟」。</p>
<h3 id="訊號-3質量當品質用">訊號 3:「質量」當品質用</h3>
<p>「程式碼質量」「服務質量」——繁中「質量」是 mass、用「品質」較精確。</p>
<p>修法：technical quality → 品質；mass / weight → 質量。</p>
<h3 id="訊號-4視頻--視屏用在繁中文章">訊號 4：「視頻 / 視屏」用在繁中文章</h3>
<p>「教學視頻」「示範視屏」——繁中傳統用「影片」、但「視頻」近年滲透。對 IT 工程師讀者寫作時、用「影片」更貼合主流偏好。</p>
<h3 id="訊號-5文件當-file-用的歧義">訊號 5：「文件」當 file 用的歧義</h3>
<p>「打開這個文件」「保存文件」——繁中的「文件」用法分歧（IT 業界常用「檔案」指 file、但日常 / Windows 檔案總管也用「文件」指資料夾）。寫作時若指 file、用「檔案」更明確。</p>
<p>修法：file → 檔案（避免歧義）；document（公文 / 報告）→ 文件。</p>
<hr>
<h2 id="何時混用--不嚴格對齊仍然合理">何時混用 / 不嚴格對齊仍然合理</h2>
<p>「地區用語對齊」這條原則在公開技術文章成立、但有合理例外：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼可以混用</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>引用第三方資料 / quote</td>
          <td>引用 Apple Developer 的中文文件用「默認」、保留原文準確性比對齊重要</td>
      </tr>
      <tr>
          <td>業界共同術語（不分地區）</td>
          <td>「Bug」「commit」「pull request」這類本身就是英文、不在語料漂移範圍</td>
      </tr>
      <tr>
          <td>內部團隊溝通 / 工作日誌</td>
          <td>寫給知道讀者語料的特定群體、混用不損精度</td>
      </tr>
      <tr>
          <td>描述對方地區的具體系統</td>
          <td>「微信公眾號」「百度網盤」是大陸專有名詞、不該翻成台灣用詞</td>
      </tr>
      <tr>
          <td>引用作者自身用詞 / 個人風格保留</td>
          <td>訪談記錄 / 個人 blog 保留作者自己的語感是 narrative 選擇</td>
      </tr>
  </tbody>
</table>
<p>判讀：寫之前自問「讀者地區是否單一？我的用詞是否會讓讀者多花認知對映？」——是 → 嚴格對齊；否 → 混用可接受。</p>
<hr>
<h2 id="推到術語選擇的更上位原則">推到「術語選擇」的更上位原則</h2>
<p>地區用語對齊是「術語選擇」的子問題。更上位的原則：</p>
<blockquote>
<p>每個技術詞、寫之前都該確認「<strong>讀者語料是否包含這個詞</strong>」。</p></blockquote>
<p>這個自問適用於：</p>
<ul>
<li><strong>地區漂移</strong>：本卡主題（繁中 vs 簡中）</li>
<li><strong>學術 vs 業界用詞</strong>：「方法論」（學術）vs「做法」（業界）</li>
<li><strong>新舊術語</strong>：「響應式設計」（舊）vs「reactive 設計」（業界新）</li>
<li><strong>中文 vs 英文</strong>：技術術語第一次出現要不要保留原文錨點（見 <a href="../terminology-keeps-original-anchor/">#107 術語翻譯要保留原文錨點</a>）</li>
<li><strong>完整名詞頭</strong>：壓縮中文術語要保留 head noun（見 <a href="../compressed-chinese-terms-need-head-noun/">#108 中文壓縮術語要保留完整名詞頭</a>）</li>
</ul>
<p>地區漂移是這個自問的第一層應用——讀者語料的最大差異訊號。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>跟本卡的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../terminology-keeps-original-anchor/">#107 術語翻譯要保留原文錨點</a></td>
          <td>兩卡都處理「讀者語料 ↔ 寫作用詞」對齊、本卡聚焦地區、#107 聚焦中英對應</td>
      </tr>
      <tr>
          <td><a href="../compressed-chinese-terms-need-head-noun/">#108 中文壓縮術語要保留完整名詞頭</a></td>
          <td>本卡是「術語完整性」的地區層、#108 是「術語完整性」的壓縮層</td>
      </tr>
      <tr>
          <td><a href="../translation-must-preserve-concept-role/">#109 術語翻譯要保留概念角色</a></td>
          <td>本卡是「概念→中文」的地區層、#109 是「概念→中文」的角色層</td>
      </tr>
      <tr>
          <td><a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度</a></td>
          <td>兩卡都處理「字句層級的精度」、本卡是地區漂移、#111 是修辭漂移</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>用「屏 / 默認 / 質量 / 視頻 / 文件」這類詞</td>
          <td>換成「螢幕 / 預設 / 品質 / 影片 / 檔案」</td>
      </tr>
      <tr>
          <td>文章寫給台灣讀者、但混用兩邊用詞</td>
          <td>全篇 grep 替換、選定一個地區語料</td>
      </tr>
      <tr>
          <td>從中國技術文章複製範例 / 解釋</td>
          <td>翻譯時連用詞一起翻、不只翻句子</td>
      </tr>
      <tr>
          <td>用了某詞但不確定是不是地區漂移</td>
          <td>grep 「某詞 + 台灣 / 香港 + 中文」看用法分布</td>
      </tr>
      <tr>
          <td>內部討論用 A、寫對外文章用 B</td>
          <td>對外文章固定用讀者地區的版本、內部討論可寬鬆</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：技術寫作的精度標準是「讀者用自己的語料能正確 parse」。地區用語漂移是累積性的閱讀流暢度損失——單一詞對映成本不大、但整篇加起來顯著。寫前先確定讀者地區、寫完跑一次 grep 對齊。</p>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡的觸發是修 <a href="../../work-log/dart_stream_controller_single_vs_broadcast/">Dart StreamController：single-subscription vs broadcast 的事故實錄</a> 時、讀者指出「副屏」是中國用語、台灣應該用「副螢幕」。</p>
<p>修補時 grep 全文、發現「副屏」出現 9 處——不是孤立的一個詞、是整篇貫穿的用詞選擇。修補方式是 batch replace。</p>
<p>對應本卡：<strong>地區漂移多半不是孤立的、會在整篇文章貫穿——修補要用 grep 而不是逐句改。寫作前先確定讀者地區、寫完跑一次地區用語 sweep</strong>。</p>
]]></content:encoded></item><item><title>商業邏輯論述要 self-contained：不依賴 code 才能被理解</title><link>https://tarrragon.github.io/blog/report/prose-self-contained-without-code-reference/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/prose-self-contained-without-code-reference/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>1 個 case&lt;/strong>（&lt;a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故的 review&lt;/a> 中讀者指出「事件 payload 第二段」依賴 code 看過）抽出來的觀察。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Scope 限縮在概念說明 / 架構決策 / 設計檢討類文章&lt;/strong>：教學類、tutorial 類、code walkthrough 類文章的讀者本來就會逐行對映 code、本卡不適用——這幾類文章的論述跟 code 緊密交織是合理 narrative&lt;/li>
&lt;li>&lt;strong>「翻譯成業務角色」也有讀者熟悉度的邊界&lt;/strong>：用「鏡像訂閱者」「狀態變更 service」這類角色名詞替代「那個 controller」、對熟悉 POS 跟 pub-sub 的讀者通順、對不熟的讀者仍是空名詞。修法是「換 reference 類型」、不是「徹底解決 self-contained」&lt;/li>
&lt;li>&lt;strong>跟規則二（商業邏輯先於 CASE）的關係要精準&lt;/strong>：規則二講「層次順序」（先商業邏輯後 CASE）、本卡講「論述自包含」（不依賴 code reference）。兩者有重疊但不完全相同——本卡是規則二在「字句層 reference 處理」的子場景、不是規則二的全面延伸&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、先判斷文章類型——概念說明 / 架構決策 / 設計檢討 → 套用；教學 / tutorial → 評估「跟 code 交織」是否合理 narrative。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>概念說明 / 架構決策 / 設計檢討類文章的論述段（不放 code 的段落）要 &lt;strong>self-contained&lt;/strong>——用名詞 / 角色 / 條件描述業務邏輯、不依賴讀者去翻附近的 code block。讀者跳過所有 code block 仍能理解論述、是「商業邏輯先於 CASE」（compositional-writing 規則二）在「字句層 reference 處理」的子場景應用。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>依賴 code 的論述&lt;/th>
 &lt;th>Self-contained 論述&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>引用方式&lt;/td>
 &lt;td>「事件 payload 第二段帶了那個欄位」&lt;/td>
 &lt;td>「事件 payload 包含『當前完整列表』+『最後變動品項』兩段」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>主詞&lt;/td>
 &lt;td>「那個 controller」「剛才的 service」&lt;/td>
 &lt;td>「副螢幕鏡像 controller」「狀態變更 service」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>讀者前提&lt;/td>
 &lt;td>已經看過 code、記得結構&lt;/td>
 &lt;td>不需要看 code、只看論述&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>失敗模式&lt;/td>
 &lt;td>讀者翻不到 reference 對應位置 → 卡住或誤讀&lt;/td>
 &lt;td>讀者直接 parse 論述、不被 code 結構綁住&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>修補擴散&lt;/td>
 &lt;td>code 改了、論述自動 outdated&lt;/td>
 &lt;td>code 改了、論述仍然有效&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>self-contained 論述的價值在於&lt;strong>論述本身就是完整的、code 是 case 補充而非依賴&lt;/strong>。讀者用論述就能 reproduce 思考過程、code 提供具體驗證。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼依賴-code-的論述會出現">為什麼依賴 code 的論述會出現&lt;/h2>
&lt;h3 id="來源-1寫的人有-code-在腦中預設讀者也有">來源 1：寫的人有 code 在腦中、預設讀者也有&lt;/h3>
&lt;p>寫作者通常已經看過或寫過 code、所以在論述段用「那個 payload 第二段」這類 reference 對自己沒負擔。但讀者可能：&lt;/p>
&lt;ul>
&lt;li>跳過 code 直接讀論述（多數讀者習慣）&lt;/li>
&lt;li>看了 code 但沒記住具體結構&lt;/li>
&lt;li>不熟 Dart / 該專案、看 code 也 parse 不出 payload 結構&lt;/li>
&lt;/ul>
&lt;p>依賴 code 的論述把這些讀者擋在門外、強迫他們翻 code 對映、認知負擔顯著上升。&lt;/p>
&lt;h3 id="來源-2把對話風格搬進文章">來源 2：把對話風格搬進文章&lt;/h3>
&lt;p>「現在只要有人訂閱、把它記錄下來、UI 就能用」——這是對話風格、預設聽者跟說話者共享 context。寫成文章時要把 context 補進去：「需要新增一個訂閱者讀這段資訊、再把它對應到 UI 上的視覺標記」。&lt;/p>
&lt;h3 id="來源-3論述跟-code-段過於緊密交織">來源 3：論述跟 code 段過於緊密交織&lt;/h3>
&lt;p>文章在寫「先給 code、然後論述、然後再給 code」的交織結構時、論述容易自然 reference 上面 code 的具體行。讀者跳過 code 就斷掉。&lt;/p>
&lt;h3 id="來源-4誤把業務邏輯當成code-行為">來源 4：誤把「業務邏輯」當成「code 行為」&lt;/h3>
&lt;p>「業務邏輯」是「為什麼這件事存在 / 服務什麼需求」、「code 行為」是「具體怎麼跑」。依賴 code 的論述把兩者混在一起、讀者難以分離兩個層次。&lt;/p>
&lt;hr>
&lt;h2 id="識別訊號什麼時候你寫了依賴-code-的論述">識別訊號：什麼時候你寫了依賴 code 的論述&lt;/h2>
&lt;h3 id="訊號-1論述用那個這個剛才的上面的當主詞">訊號 1：論述用「那個」「這個」「剛才的」「上面的」當主詞&lt;/h3>
&lt;p>「那個 service」「這個 payload」「剛才的 controller」——這類代詞依賴讀者剛才看過 code。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>1 個 case</strong>（<a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故的 review</a> 中讀者指出「事件 payload 第二段」依賴 code 看過）抽出來的觀察。具體限制：</p>
<ul>
<li><strong>Scope 限縮在概念說明 / 架構決策 / 設計檢討類文章</strong>：教學類、tutorial 類、code walkthrough 類文章的讀者本來就會逐行對映 code、本卡不適用——這幾類文章的論述跟 code 緊密交織是合理 narrative</li>
<li><strong>「翻譯成業務角色」也有讀者熟悉度的邊界</strong>：用「鏡像訂閱者」「狀態變更 service」這類角色名詞替代「那個 controller」、對熟悉 POS 跟 pub-sub 的讀者通順、對不熟的讀者仍是空名詞。修法是「換 reference 類型」、不是「徹底解決 self-contained」</li>
<li><strong>跟規則二（商業邏輯先於 CASE）的關係要精準</strong>：規則二講「層次順序」（先商業邏輯後 CASE）、本卡講「論述自包含」（不依賴 code reference）。兩者有重疊但不完全相同——本卡是規則二在「字句層 reference 處理」的子場景、不是規則二的全面延伸</li>
</ul>
<p>讀者使用本卡時、先判斷文章類型——概念說明 / 架構決策 / 設計檢討 → 套用；教學 / tutorial → 評估「跟 code 交織」是否合理 narrative。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p>概念說明 / 架構決策 / 設計檢討類文章的論述段（不放 code 的段落）要 <strong>self-contained</strong>——用名詞 / 角色 / 條件描述業務邏輯、不依賴讀者去翻附近的 code block。讀者跳過所有 code block 仍能理解論述、是「商業邏輯先於 CASE」（compositional-writing 規則二）在「字句層 reference 處理」的子場景應用。</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>依賴 code 的論述</th>
          <th>Self-contained 論述</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>引用方式</td>
          <td>「事件 payload 第二段帶了那個欄位」</td>
          <td>「事件 payload 包含『當前完整列表』+『最後變動品項』兩段」</td>
      </tr>
      <tr>
          <td>主詞</td>
          <td>「那個 controller」「剛才的 service」</td>
          <td>「副螢幕鏡像 controller」「狀態變更 service」</td>
      </tr>
      <tr>
          <td>讀者前提</td>
          <td>已經看過 code、記得結構</td>
          <td>不需要看 code、只看論述</td>
      </tr>
      <tr>
          <td>失敗模式</td>
          <td>讀者翻不到 reference 對應位置 → 卡住或誤讀</td>
          <td>讀者直接 parse 論述、不被 code 結構綁住</td>
      </tr>
      <tr>
          <td>修補擴散</td>
          <td>code 改了、論述自動 outdated</td>
          <td>code 改了、論述仍然有效</td>
      </tr>
  </tbody>
</table>
<p>self-contained 論述的價值在於<strong>論述本身就是完整的、code 是 case 補充而非依賴</strong>。讀者用論述就能 reproduce 思考過程、code 提供具體驗證。</p>
<hr>
<h2 id="為什麼依賴-code-的論述會出現">為什麼依賴 code 的論述會出現</h2>
<h3 id="來源-1寫的人有-code-在腦中預設讀者也有">來源 1：寫的人有 code 在腦中、預設讀者也有</h3>
<p>寫作者通常已經看過或寫過 code、所以在論述段用「那個 payload 第二段」這類 reference 對自己沒負擔。但讀者可能：</p>
<ul>
<li>跳過 code 直接讀論述（多數讀者習慣）</li>
<li>看了 code 但沒記住具體結構</li>
<li>不熟 Dart / 該專案、看 code 也 parse 不出 payload 結構</li>
</ul>
<p>依賴 code 的論述把這些讀者擋在門外、強迫他們翻 code 對映、認知負擔顯著上升。</p>
<h3 id="來源-2把對話風格搬進文章">來源 2：把對話風格搬進文章</h3>
<p>「現在只要有人訂閱、把它記錄下來、UI 就能用」——這是對話風格、預設聽者跟說話者共享 context。寫成文章時要把 context 補進去：「需要新增一個訂閱者讀這段資訊、再把它對應到 UI 上的視覺標記」。</p>
<h3 id="來源-3論述跟-code-段過於緊密交織">來源 3：論述跟 code 段過於緊密交織</h3>
<p>文章在寫「先給 code、然後論述、然後再給 code」的交織結構時、論述容易自然 reference 上面 code 的具體行。讀者跳過 code 就斷掉。</p>
<h3 id="來源-4誤把業務邏輯當成code-行為">來源 4：誤把「業務邏輯」當成「code 行為」</h3>
<p>「業務邏輯」是「為什麼這件事存在 / 服務什麼需求」、「code 行為」是「具體怎麼跑」。依賴 code 的論述把兩者混在一起、讀者難以分離兩個層次。</p>
<hr>
<h2 id="識別訊號什麼時候你寫了依賴-code-的論述">識別訊號：什麼時候你寫了依賴 code 的論述</h2>
<h3 id="訊號-1論述用那個這個剛才的上面的當主詞">訊號 1：論述用「那個」「這個」「剛才的」「上面的」當主詞</h3>
<p>「那個 service」「這個 payload」「剛才的 controller」——這類代詞依賴讀者剛才看過 code。</p>
<p>修法：把代詞換成具體名詞 + 角色描述（「狀態變更 service」「事件 payload」「副螢幕鏡像 controller」）。</p>
<h3 id="訊號-2用-code-結構描述第二段那個欄位">訊號 2：用 code 結構描述（「第二段」「那個欄位」）</h3>
<p>「payload 第二段」「那個 nullable 欄位」「上面 method 的 return value」——這類描述依賴讀者看過 code 的具體結構。</p>
<p>修法:把 code 結構描述翻譯成業務角色描述。「payload 第二段」→「最後變動品項欄位（給需要追蹤單筆變動的訂閱者用）」。</p>
<h3 id="訊號-3時序連接詞依賴-code-順序">訊號 3：時序連接詞依賴 code 順序</h3>
<p>「先&hellip;然後&hellip;接著&hellip;」如果這個時序對應上面 code 的執行順序、論述跟 code 綁太緊。</p>
<p>修法：把時序敘述為「在 X 條件下、Y 動作觸發 Z 結果」、不依賴 code 的具體順序。</p>
<h3 id="訊號-4論述只有就好就能就行">訊號 4：論述只有「就好」「就能」「就行」</h3>
<p>「現在只要有人訂閱、UI 就能用」「修改一行就好」——這類「就」字句<strong>在依賴 code 補足背景條件時</strong>有問題。但「修一行就好」如果背景條件已在前文說明、用「就」表達精簡是合理的——區分標準是「沒有 code 也讀得通嗎」、不是字面有「就」就違規。</p>
<p>修法：背景條件不在前文時、把省略的條件補回去；背景條件已在前文時、保留「就」沒問題。「在訂閱端讀取這段資訊、加一個視覺標記的綁定、即可在 UI 上呈現」。</p>
<h3 id="訊號-5跳過-code-block-後段落讀不通">訊號 5：跳過 code block 後段落讀不通</h3>
<p>最直接的測試方法：把所有 code block 拿掉、再讀一次論述、看是否仍能理解。</p>
<p>讀不通 → 論述依賴 code、要修補。</p>
<hr>
<h2 id="修法把-reference-翻成-self-contained-描述">修法：把 reference 翻成 self-contained 描述</h2>
<h3 id="修法-1用名詞替代代詞">修法 1：用名詞替代代詞</h3>
<p>修補前：</p>
<blockquote>
<p>「那個 service 對外發送事件、payload 第二段帶了這次變動是哪筆。」</p></blockquote>
<p>修補後：</p>
<blockquote>
<p>「狀態變更 service 對外發送的事件 payload 包含兩段：當前完整商品列表、最後變動的具體品項。第二段是『最後變動品項』。」</p></blockquote>
<h3 id="修法-2用角色替代位置">修法 2：用角色替代「位置」</h3>
<p>修補前：</p>
<blockquote>
<p>「上面 code 第三行那個 listener 拿到的是 nullable。」</p></blockquote>
<p>修補後：</p>
<blockquote>
<p>「副螢幕的訂閱者收到的事件 payload 中、第二段（最後變動品項）可能為 null（移除或清空操作的情境）。」</p></blockquote>
<h3 id="修法-3用條件替代時序">修法 3：用條件替代時序</h3>
<p>修補前：</p>
<blockquote>
<p>「先建立 controller、然後 listen、接著 add 事件、再 cancel。」</p></blockquote>
<p>修補後:</p>
<blockquote>
<p>「在 controller 建立後、訂閱者可呼叫 <code>.listen()</code> 註冊；註冊完成後、controller 才能 <code>.add()</code> 事件給訂閱者；訂閱者呼叫 <code>.cancel()</code> 解除註冊後、後續 <code>.listen()</code> 對 single-subscription 仍然違反契約。」</p></blockquote>
<h3 id="修法-4把就好展開成具體條件">修法 4：把「就好」展開成具體條件</h3>
<p>修補前：</p>
<blockquote>
<p>「現在只要有人訂閱、把它記錄下來、UI 就能用。」</p></blockquote>
<p>修補後：</p>
<blockquote>
<p>「新需求只要新增一個訂閱者讀這段資訊、再把它對應到 UI 上的視覺標記即可——介面不需要變動、payload 結構不需要調整、實作範圍只限於新增訂閱端。」</p></blockquote>
<hr>
<h2 id="何時論述可以依賴-code">何時論述可以依賴 code</h2>
<p>「論述要 self-contained」這條原則在概念說明 / 架構決策 / 設計檢討類文章成立、但有合理例外：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼可以依賴 code</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Code walkthrough / line-by-line</td>
          <td>文章本身就是 code 解說、讀者預設會逐行對映</td>
      </tr>
      <tr>
          <td>簡短 inline 引用 specific 行為</td>
          <td>「<code>stream.listen()</code> 第一個參數是 callback」這類引用本身就是 code 字面</td>
      </tr>
      <tr>
          <td>Tutorial 教學步驟</td>
          <td>「跑這個指令、你會看到 X 輸出、接著做 Y」是 hands-on 教學風格</td>
      </tr>
      <tr>
          <td>Code review 評論</td>
          <td>評論本身就是針對某行 code、上下文是 inline 共享的</td>
      </tr>
  </tbody>
</table>
<p>判讀：寫之前自問「我的文章是『教讀者怎麼讀這份 code』還是『教讀者一個概念 / 框架』？」——前者可依賴 code、後者要 self-contained。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>跟本卡的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Compositional-writing 規則二：商業邏輯先於 CASE</td>
          <td>本卡是規則二在「字句層 reference 處理」的子場景——規則二講層次順序、本卡講論述不依賴 code reference。兩者有重疊但不完全相同</td>
      </tr>
      <tr>
          <td><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></td>
          <td>用「那個 payload」是寫作便利、self-contained 論述需要刻意翻譯——同骨展現</td>
      </tr>
      <tr>
          <td><a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度</a></td>
          <td>「就好」「就能」這類字句既是口語也是依賴 code、本卡跟 #111 在這層重疊</td>
      </tr>
      <tr>
          <td><a href="../design-flaw-by-current-axes-not-hindsight/">#110 設計檢討用當下三軸論證、不依賴 hindsight</a></td>
          <td>三卡都是「論述要能讓讀者拿來用」的不同層次——當下視角 / 精度 / self-contained</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>論述用「那個 / 這個 / 剛才」當主詞</td>
          <td>換成具體名詞 + 角色描述</td>
      </tr>
      <tr>
          <td>論述提到「第 X 段 / 第 Y 行 / 那個欄位」</td>
          <td>翻譯成業務角色描述</td>
      </tr>
      <tr>
          <td>段落用「就好 / 就能 / 就行」結尾</td>
          <td>把省略的條件補回去</td>
      </tr>
      <tr>
          <td>把 code block 拿掉後論述讀不通</td>
          <td>整段重寫成 self-contained</td>
      </tr>
      <tr>
          <td>寫的時候有 code 在記憶中、覺得「不用解釋」</td>
          <td>預設讀者跳過 code、強迫自己用文字描述</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：技術文章的論述要 self-contained——讀者跳過所有 code block 仍能理解論述、是「商業邏輯先於 CASE」的延伸實踐。寫完後跑一次「拿掉 code block 還讀得通嗎」自測、讀不通 → 翻譯成 self-contained 描述。</p>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡的觸發是修 <a href="../../work-log/dart_stream_controller_single_vs_broadcast/">Dart StreamController：single-subscription vs broadcast 的事故實錄</a> 時、讀者指出某段論述「重點混淆 + 過於口語 + 預設讀者看過原始碼」。</p>
<p>問題段（修補前）：</p>
<blockquote>
<p>「技術上這需求很乾淨：service 早就在事件 payload 第二段帶了『這次變動是哪筆』，現在只要有人訂閱、把它記錄下來，UI 就能用。於是收銀主畫面的 controller 加了第二個訂閱。」</p></blockquote>
<p>問題分析：</p>
<ul>
<li>「事件 payload 第二段」依賴讀者看過 code 結構</li>
<li>「就能用」「就好」省略了具體條件</li>
<li>「於是 X 加了 Y」對話風格、不是論述風格</li>
</ul>
<p>修補後：</p>
<blockquote>
<p>「這個需求剛好對應 service 已經備妥但尚未被消費的資訊——service 對外的事件 payload 從原始設計就分兩段：一段是『當前完整的商品列表』、另一段是『這次變動的具體品項』。第二段是當初為『需要追蹤單筆變動的訂閱者』預留的擴充欄位、過去幾個月一直沒被消費。新需求只要新增一個訂閱者讀這段資訊、再把它對應到 UI 上的視覺標記即可——介面不需要變動、payload 結構不需要調整、實作範圍只限於新增訂閱端。」</p></blockquote>
<p>修補後的論述用「角色描述（『需要追蹤單筆變動的訂閱者』）」替代了「位置描述（『第二段』）」、補回了省略的條件（「介面不需要變動、payload 結構不需要調整、實作範圍只限於新增訂閱端」）。讀者即使跳過所有 code block 也能理解這段論述。</p>
<p>對應本卡：<strong>論述依賴 code 是「寫的人有 code 在腦中」的便利選擇——multi-pass review 要在輪 5「反例 / 邊界」加掃 self-contained frame、用「拿掉 code 還讀得通嗎」自測</strong>。</p>
]]></content:encoded></item><item><title>Multi-pass review 的 frame 顆粒度盲點：抽象規則 → 具體訊號的轉譯不完整</title><link>https://tarrragon.github.io/blog/report/multi-pass-review-frame-granularity-blindspot/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/multi-pass-review-frame-granularity-blindspot/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>1 個 case&lt;/strong>（&lt;a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故&lt;/a> 的 review 過程跑 4 輪後仍漏 catch 4 類字句層問題）抽出來的假說。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>樣本量極小&lt;/strong>：「multi-pass review framework 顆粒度盲點」這個結論基於 1 次 review、不是多次跨主題 review 觀察到的 systematic pattern。可能是這個 reviewer（我）有特定盲點、不是 framework 本身的問題&lt;/li>
&lt;li>&lt;strong>三機制有效性未驗證&lt;/strong>：keyword bank / reader simulation / self-criticism 三機制是 proposed mechanisms、未實際跑下一篇文章驗證能 catch 之前漏掉的問題類型&lt;/li>
&lt;li>&lt;strong>「reader simulation 由同 reviewer 執行」的根本質疑沒解決&lt;/strong>：拿掉 code block 重讀、聽起來合理、但同一個人是否真能模擬「沒看過 code 的讀者視角」是疑問——記憶不會因為 code block 隱藏而消失。本卡提的修法是 partial fix、不是 root cause solution&lt;/li>
&lt;li>&lt;strong>「同一 reviewer 跑多輪 catch 高度相同」是直覺論述&lt;/strong>：沒有實證、是直覺推論&lt;/li>
&lt;li>&lt;strong>跟其他卡互相 cross-link 形成迴圈論證&lt;/strong>：本卡引 #110 / #111 / #113、但這幾張卡都源自同次事件、互相驗證有 selection bias 風險&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、把它當「&lt;strong>從一次 review 失誤抽出的盲點假說&lt;/strong>」、不當「驗證過的 review framework 升級方案」。三機制是 starting point、有效性需要後續案例累積驗證。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>Multi-pass review 用「規則 frame」掃描、有效抓「結構性違反」（規則順序、論述結構、邊界段缺失）、但&lt;strong>這次 case 顯示對「字句層的具體訊號」覆蓋不足&lt;/strong>——同個規則底下有大量具體訊號、reviewer 用記憶 sweep 容易漏掉一部分（這次 1 個 case 觀察、是否 systematic 有待累積）。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>缺口類型&lt;/th>
 &lt;th>Multi-pass 用「規則 frame」能抓&lt;/th>
 &lt;th>Multi-pass 用「規則 frame」抓不到&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>結構性違反&lt;/td>
 &lt;td>段落順序、論述結構、邊界段缺失&lt;/td>
 &lt;td>—&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>規則對齊&lt;/td>
 &lt;td>「應該 / 必須」絕對主義（明顯）&lt;/td>
 &lt;td>「碰巧 / 撞牆 / 一輩子」口語修辭（同樣違反但不明顯）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>用詞精度&lt;/td>
 &lt;td>術語原文錨點（contract / 領域先驗）&lt;/td>
 &lt;td>地區漂移（屏 / 螢幕、默認 / 預設）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>論述自包含性&lt;/td>
 &lt;td>H2 後加商業邏輯導引&lt;/td>
 &lt;td>段落內依賴 code（「payload 第二段」）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>句型結構&lt;/td>
 &lt;td>反例段落補正向錨點（明顯）&lt;/td>
 &lt;td>「不是 A 而是 B」結構（隱性違反）+ 廢話前綴 wrapper&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵差異是「規則理解」vs「具體訊號比對」：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>規則理解&lt;/strong>：reviewer 知道「正向陳述優先」這條規則&lt;/li>
&lt;li>&lt;strong>具體訊號比對&lt;/strong>：reviewer 要逐句檢查所有可能違反該規則的具體句型&lt;/li>
&lt;/ul>
&lt;p>抽象規則 → 具體訊號的轉譯沒做完整、就會 systematic miss 一整類字句層問題。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼規則-frame抓不到字句層問題">為什麼「規則 frame」抓不到字句層問題&lt;/h2>
&lt;h3 id="問題-1抽象規則沒展開成具體訊號清單">問題 1：抽象規則沒展開成具體訊號清單&lt;/h3>
&lt;p>每條規則有大量可能的違反句型——例如「規則五：最重要的話優先說」可能違反句型：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>違反句型&lt;/th>
 &lt;th>具體案例&lt;/th>
 &lt;th>在哪裡常見&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>廢話前綴 / wrapper&lt;/td>
 &lt;td>「下次看到 X 時、做 Y」&lt;/td>
 &lt;td>結尾段、heuristic 段&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>觀察先 / 定義後&lt;/td>
 &lt;td>「實務上常看到：[code]」&lt;/td>
 &lt;td>起點段&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>否定先 / 肯定後&lt;/td>
 &lt;td>「不要先想 A、先想 B」&lt;/td>
 &lt;td>除錯思維、check list&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>條件先 / 結論後&lt;/td>
 &lt;td>「在 X、Y、Z 條件下、結論是 W」&lt;/td>
 &lt;td>推導段&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>修飾先 / 主詞後&lt;/td>
 &lt;td>「考慮所有可能後、做 X」&lt;/td>
 &lt;td>提案段&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>reviewer 用「規則五」這個 frame 掃描、靠記憶找「這段有沒有違反規則五」——多半只 catch「觀察先 / 定義後」這個明顯 case、漏 catch 廢話前綴跟否定先行。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>1 個 case</strong>（<a href="../../work-log/dart_stream_controller_single_vs_broadcast/">dart Stream 事故</a> 的 review 過程跑 4 輪後仍漏 catch 4 類字句層問題）抽出來的假說。具體限制：</p>
<ul>
<li><strong>樣本量極小</strong>：「multi-pass review framework 顆粒度盲點」這個結論基於 1 次 review、不是多次跨主題 review 觀察到的 systematic pattern。可能是這個 reviewer（我）有特定盲點、不是 framework 本身的問題</li>
<li><strong>三機制有效性未驗證</strong>：keyword bank / reader simulation / self-criticism 三機制是 proposed mechanisms、未實際跑下一篇文章驗證能 catch 之前漏掉的問題類型</li>
<li><strong>「reader simulation 由同 reviewer 執行」的根本質疑沒解決</strong>：拿掉 code block 重讀、聽起來合理、但同一個人是否真能模擬「沒看過 code 的讀者視角」是疑問——記憶不會因為 code block 隱藏而消失。本卡提的修法是 partial fix、不是 root cause solution</li>
<li><strong>「同一 reviewer 跑多輪 catch 高度相同」是直覺論述</strong>：沒有實證、是直覺推論</li>
<li><strong>跟其他卡互相 cross-link 形成迴圈論證</strong>：本卡引 #110 / #111 / #113、但這幾張卡都源自同次事件、互相驗證有 selection bias 風險</li>
</ul>
<p>讀者使用本卡時、把它當「<strong>從一次 review 失誤抽出的盲點假說</strong>」、不當「驗證過的 review framework 升級方案」。三機制是 starting point、有效性需要後續案例累積驗證。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p>Multi-pass review 用「規則 frame」掃描、有效抓「結構性違反」（規則順序、論述結構、邊界段缺失）、但<strong>這次 case 顯示對「字句層的具體訊號」覆蓋不足</strong>——同個規則底下有大量具體訊號、reviewer 用記憶 sweep 容易漏掉一部分（這次 1 個 case 觀察、是否 systematic 有待累積）。</p>
<table>
  <thead>
      <tr>
          <th>缺口類型</th>
          <th>Multi-pass 用「規則 frame」能抓</th>
          <th>Multi-pass 用「規則 frame」抓不到</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>結構性違反</td>
          <td>段落順序、論述結構、邊界段缺失</td>
          <td>—</td>
      </tr>
      <tr>
          <td>規則對齊</td>
          <td>「應該 / 必須」絕對主義（明顯）</td>
          <td>「碰巧 / 撞牆 / 一輩子」口語修辭（同樣違反但不明顯）</td>
      </tr>
      <tr>
          <td>用詞精度</td>
          <td>術語原文錨點（contract / 領域先驗）</td>
          <td>地區漂移（屏 / 螢幕、默認 / 預設）</td>
      </tr>
      <tr>
          <td>論述自包含性</td>
          <td>H2 後加商業邏輯導引</td>
          <td>段落內依賴 code（「payload 第二段」）</td>
      </tr>
      <tr>
          <td>句型結構</td>
          <td>反例段落補正向錨點（明顯）</td>
          <td>「不是 A 而是 B」結構（隱性違反）+ 廢話前綴 wrapper</td>
      </tr>
  </tbody>
</table>
<p>關鍵差異是「規則理解」vs「具體訊號比對」：</p>
<ul>
<li><strong>規則理解</strong>：reviewer 知道「正向陳述優先」這條規則</li>
<li><strong>具體訊號比對</strong>：reviewer 要逐句檢查所有可能違反該規則的具體句型</li>
</ul>
<p>抽象規則 → 具體訊號的轉譯沒做完整、就會 systematic miss 一整類字句層問題。</p>
<hr>
<h2 id="為什麼規則-frame抓不到字句層問題">為什麼「規則 frame」抓不到字句層問題</h2>
<h3 id="問題-1抽象規則沒展開成具體訊號清單">問題 1：抽象規則沒展開成具體訊號清單</h3>
<p>每條規則有大量可能的違反句型——例如「規則五：最重要的話優先說」可能違反句型：</p>
<table>
  <thead>
      <tr>
          <th>違反句型</th>
          <th>具體案例</th>
          <th>在哪裡常見</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>廢話前綴 / wrapper</td>
          <td>「下次看到 X 時、做 Y」</td>
          <td>結尾段、heuristic 段</td>
      </tr>
      <tr>
          <td>觀察先 / 定義後</td>
          <td>「實務上常看到：[code]」</td>
          <td>起點段</td>
      </tr>
      <tr>
          <td>否定先 / 肯定後</td>
          <td>「不要先想 A、先想 B」</td>
          <td>除錯思維、check list</td>
      </tr>
      <tr>
          <td>條件先 / 結論後</td>
          <td>「在 X、Y、Z 條件下、結論是 W」</td>
          <td>推導段</td>
      </tr>
      <tr>
          <td>修飾先 / 主詞後</td>
          <td>「考慮所有可能後、做 X」</td>
          <td>提案段</td>
      </tr>
  </tbody>
</table>
<p>reviewer 用「規則五」這個 frame 掃描、靠記憶找「這段有沒有違反規則五」——多半只 catch「觀察先 / 定義後」這個明顯 case、漏 catch 廢話前綴跟否定先行。</p>
<h3 id="問題-2缺乏-grep-keyword-bank">問題 2：缺乏 grep keyword bank</h3>
<p>字句層問題有大量可 grep 的具體詞——但 reviewer 沒有 keyword bank、靠肉眼掃。例如：</p>
<table>
  <thead>
      <tr>
          <th>規則類別</th>
          <th>可 grep 的具體詞</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>口語修辭</td>
          <td>一輩子 / 永遠 / 碰巧 / 剛好 / 撞牆 / 炸 / 鎖死 / 啊原來</td>
      </tr>
      <tr>
          <td>廢話前綴</td>
          <td>下次看到 / 下次寫 / 下次面對 / 下次遇到 / 之後再</td>
      </tr>
      <tr>
          <td>否定先行</td>
          <td>不要先 / 不是 A 而是 B / 不該 / 不能</td>
      </tr>
      <tr>
          <td>地區漂移</td>
          <td>屏 / 默認 / 質量 / 視頻 / 文件（當 file 用）</td>
      </tr>
      <tr>
          <td>依賴 code</td>
          <td>那個 / 這個 / 剛才的 / 上面的 / 第 X 段 / 就好 / 就能</td>
      </tr>
  </tbody>
</table>
<p>每輪 review 用 grep 比對固定 keyword list、不靠 reviewer 記憶——能消除「靠記憶找違規」的 systematic miss。</p>
<h3 id="問題-3reviewer-自我審查的視角盲點">問題 3：reviewer 自我審查的視角盲點</h3>
<p>reviewer 讀自己寫的東西、會自動 fill in 上下文、感受不到讀者的真實閱讀體驗。例如：</p>
<ul>
<li>「事件 payload 第二段帶了 X」——reviewer 寫的時候腦中有 code、知道「第二段」是什麼、感覺通順</li>
<li>讀者讀的時候沒有 code 在腦中、「第二段」是空的 reference、卡住</li>
</ul>
<p>這個視角差異是 multi-pass review 的結構性盲點——同一個 reviewer 跑多輪、視角始終是寫作者視角、不是讀者視角。</p>
<h3 id="問題-4multi-pass-缺-self-criticism-輪">問題 4：Multi-pass 缺 self-criticism 輪</h3>
<p>每輪 review 都是 forward checking（這篇對齊規則嗎？）、沒做 backward critique（規則本身在這個情境是否夠細？有沒有 miss 的 frame？）。</p>
<p>如果規則框架本身不夠細、跑再多輪都掃不到 frame 之外的問題。</p>
<hr>
<h2 id="多面向四類-missed-問題的分類">多面向：四類 missed 問題的分類</h2>
<p>這次跑完 4 輪 multi-pass review、漏 catch 的 4 類問題：</p>
<h3 id="miss-類型-1口語修辭規則七--規則五的字句層子場景">Miss 類型 1：口語修辭（規則七 / 規則五的字句層子場景）</h3>
<p>漏 catch 的具體訊號:「一輩子只能 listen 一次」「碰巧能用」「立刻撞牆」「啊原來」「炸了」</p>
<p><strong>為什麼漏</strong>：「規則七：機會成本語氣」掃了「應該/必須/不行」、沒掃「一輩子/碰巧/撞牆」這類修辭詞。修辭詞跟絕對主義詞屬於不同 keyword set、reviewer 沒同時掃。</p>
<p><strong>修法</strong>：建立「口語修辭 keyword bank」、輪 4「術語精度」加掃。</p>
<h3 id="miss-類型-2地區漂移規則四術語的子場景">Miss 類型 2：地區漂移（規則四「術語」的子場景）</h3>
<p>漏 catch 的具體訊號：「副屏」（中國用語、繁中應該用「副螢幕」）</p>
<p><strong>為什麼漏</strong>：輪 4「術語檢查」聚焦在「中文 / 原文錨點」、沒掃「繁中 / 簡中漂移」。reviewer 預設「讀者地區」是台灣、但沒 explicit 用 keyword bank 比對。</p>
<p><strong>修法</strong>：建立「地區用語對齊 keyword bank」（屏 / 默認 / 質量 / 視頻 / 文件 / 函數 / 介面 / 內存）、輪 4 加掃。</p>
<h3 id="miss-類型-3依賴-code-論述規則二商業邏輯先於-case-的延伸">Miss 類型 3：依賴 code 論述（規則二商業邏輯先於 CASE 的延伸）</h3>
<p>漏 catch 的具體訊號：「事件 payload 第二段帶了 X」「就好 / 就能」</p>
<p><strong>為什麼漏</strong>：規則二被理解成「H2 後加商業邏輯導引」、沒延伸到「論述本身不依賴 code」。reviewer 寫的時候腦中有 code、感受不到「依賴 code」的閱讀體驗。</p>
<p><strong>修法</strong>：加「reader simulation」frame——拿掉所有 code block、再讀一次論述、看是否仍能理解。</p>
<h3 id="miss-類型-4廢話前綴--否定先行規則五--規則六的字句層子場景">Miss 類型 4：廢話前綴 + 否定先行（規則五 + 規則六的字句層子場景）</h3>
<p>漏 catch 的具體訊號：「下次看到 X 時、不要先想 Y」這類 hortative 結尾段</p>
<p><strong>為什麼漏</strong>：規則五「最重要的話優先說」被理解成「核心原則先 / 例子後」、沒延伸到「廢話前綴 wrapper 句子」。規則六「正向陳述」被理解成「反例段落補正向錨點」、沒延伸到「『不是 A 而是 B』結構」。</p>
<p><strong>修法</strong>：建立「廢話前綴 + 否定先行 keyword bank」、輪 5 加掃。</p>
<hr>
<h2 id="修補-multi-pass-review-框架的三個機制">修補 multi-pass review 框架的三個機制</h2>
<h3 id="機制-1keyword-bank具體訊號清單">機制 1：Keyword bank（具體訊號清單）</h3>
<p>每條規則展開成可 grep 的 keyword list、每輪 review 用 grep 比對、不靠 reviewer 記憶。</p>
<p>範例 keyword bank（節選）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">口語修辭：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  一輩子 / 永遠 / 碰巧 / 剛好 / 撞牆 / 炸 / 鎖死 / 啊原來 / 沒事 / 乾淨
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">廢話前綴 / 否定先行：
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  下次看到 / 下次寫 / 下次面對 / 下次遇到 / 不要先 / 不是 X 而是 Y
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">地區漂移（繁中讀者）：
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  屏 / 默認 / 質量 / 視頻 / 文件（當 file）/ 函數 / 接口 / 內存 / 視頻
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">依賴 code 訊號：
</span></span><span class="line"><span class="ln">11</span><span class="cl">  那個 / 這個 / 剛才的 / 上面的 / 第 X 段 / 就好 / 就能 / 就行</span></span></code></pre></div><p>每篇文章 review 時跑這些 grep、把 hit 列出來、決定保留或修補。</p>
<h3 id="機制-2reader-simulation-輪">機制 2：Reader simulation 輪</h3>
<p>加一輪「假設讀者沒有上下文、能不能讀懂這段論述」、嘗試換視角。具體做法：</p>
<ul>
<li><strong>拿掉所有 code block 後重讀</strong>：論述是否 self-contained？</li>
<li><strong>跳到段落中間直接讀</strong>：不依賴前文、能不能 parse？</li>
<li><strong>隨機抽段給陌生讀者讀</strong>：cold-read 能不能拿到關鍵資訊？</li>
</ul>
<p><strong>已知限制</strong>：同一 reviewer 即使拿掉 code block、記憶仍在、無法完全模擬「沒看過 code 的讀者視角」。這個機制是 partial fix——能 catch 部分上下文依賴、但不是 root cause solution。最終解法仍需引入外部讀者反饋（cold-read by 真實讀者）。</p>
<h3 id="機制-3self-criticism-輪">機制 3：Self-criticism 輪</h3>
<p>加一輪「我這份規則本身在這個情境是否夠細、有沒有 miss 的 frame？」、強迫 reviewer 反向審視框架本身。具體 prompt：</p>
<ul>
<li>「我跑的 N 輪、catch 的問題類型有哪些？」</li>
<li>「同個規則底下、還有哪些可能違反句型沒被掃到？」</li>
<li>「如果讀者報告 X 類問題、是哪輪該 catch 但沒 catch？」</li>
<li>「framework 本身是否有 known blind spot？」</li>
</ul>
<p>self-criticism 輪不是「再跑一次規則 frame」、是「<strong>檢視 frame 本身的覆蓋度</strong>」。</p>
<hr>
<h2 id="為什麼這些機制不能被再仔細一輪取代">為什麼這些機制不能被「再仔細一輪」取代</h2>
<h3 id="再仔細一輪的同-frame-盲點">「再仔細一輪」的同 frame 盲點</h3>
<p>reviewer 跑同一個 frame 兩次、catch 的東西<strong>多半</strong>高度相同——因為視角、知識、注意力分配相同。（這是直覺論述、未做受控實驗驗證；但跟「換 frame」的設計動機一致——multi-pass 的核心就是「同 frame 重看 catch 不到新問題」）Multi-pass review 的核心是「每輪換 frame」、不是「同 frame 多跑幾次」。</p>
<p>但<strong>換 frame ≠ 換規則</strong>——reviewer 可能換規則但用同樣的視角、同樣的記憶 sweep、catch 的東西相同。要真正換 frame、需要：</p>
<ul>
<li><strong>換工具</strong>：keyword bank 取代肉眼掃（機制 1）</li>
<li><strong>換視角</strong>：模擬讀者取代 reviewer 視角（機制 2）</li>
<li><strong>換層次</strong>：審視 framework 取代套用 framework（機制 3）</li>
</ul>
<p>三個機制各自處理「同一 reviewer 跑多輪仍 miss」的不同來源。</p>
<h3 id="hindsight-視角的反向印證">Hindsight 視角的反向印證</h3>
<p><a href="../design-flaw-by-current-axes-not-hindsight/">#110 設計檢討用當下三軸論證、不依賴 hindsight</a> 的核心議題是「事後諸葛論述」會混淆「設計缺陷 vs 需求演化」。同樣的 hindsight 風險也存在於 review 流程：</p>
<ul>
<li><strong>Hindsight 視角</strong>：「讀者反饋了 → 補進規則」——把規則當成「事故後補的 patch」</li>
<li><strong>當下三軸視角</strong>：「framework 本身是否夠細到 catch 這類問題？」——把 framework 當成預設工具、用 self-criticism 反向審視</li>
</ul>
<p>兩種視角的差別跟 #110 的差別同骨：前者依賴結局（讀者反饋）、後者用當下框架審視（self-criticism）。</p>
<hr>
<h2 id="識別訊號什麼時候你的-review-framework-不夠細">識別訊號：什麼時候你的 review framework 不夠細</h2>
<h3 id="訊號-1讀者反饋的問題類型在-framework-裡找不到對應-frame">訊號 1：讀者反饋的問題類型在 framework 裡找不到對應 frame</h3>
<p>讀者指出「廢話前綴」問題、reviewer 翻 framework 找對應 frame——找到「規則五最重要的話優先說」、但這條規則沒展開到「廢話前綴」這個具體子場景。</p>
<p>修法：把問題類型加進 framework 的 keyword bank、下次同類問題能被 grep catch。</p>
<h3 id="訊號-2跑了-n-輪相同類型的問題仍重複出現">訊號 2：跑了 N 輪、相同類型的問題仍重複出現</h3>
<p>字句層問題（口語修辭、地區漂移）跑了 4 輪 review 仍漏——表示 framework 沒 catch 這個層次。</p>
<p>修法：加 keyword bank（機制 1）、不靠 reviewer 記憶。</p>
<h3 id="訊號-3reviewer-自我審查感覺通順讀者反映卡住">訊號 3：reviewer 自我審查感覺通順、讀者反映卡住</h3>
<p>「事件 payload 第二段」對 reviewer 通順、對讀者卡住——視角差異。</p>
<p>修法：加 reader simulation 輪（機制 2）。</p>
<h3 id="訊號-4相同-framework-跑不同主題catch-的問題類型差異不大">訊號 4：相同 framework 跑不同主題、catch 的問題類型差異不大</h3>
<p>framework 不會自我批判——跑 100 篇文章、catch 的都是 framework 內的 frame、framework 外的問題永遠看不見。</p>
<p>修法：加 self-criticism 輪（機制 3）、定期審視 framework 本身的覆蓋度。</p>
<hr>
<h2 id="何時不需要這些補強機制">何時不需要這些補強機制</h2>
<p>「multi-pass review 需要 keyword bank + reader simulation + self-criticism」這條原則在 production 教學文章 / 設計檢討文章成立、但有合理例外：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼不需要</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>短篇 note / 即時更新</td>
          <td>預期讀者群小、不擴散、字句層問題影響有限</td>
      </tr>
      <tr>
          <td>個人筆記</td>
          <td>reviewer = reader、視角差異不存在</td>
      </tr>
      <tr>
          <td>Review framework 已成熟、團隊內化</td>
          <td>keyword bank 已經內化成 reviewer 的反射、不需要 explicit 工具</td>
      </tr>
      <tr>
          <td>Framework 規模太小</td>
          <td>framework 只有 3-5 條規則時、self-criticism 容易出 false positive</td>
      </tr>
  </tbody>
</table>
<p>判讀：寫之前自問「這篇文章的讀者群有多大？字句層問題擴散的代價有多高？」——大 / 高 → 嚴格用三機制；小 / 低 → 可放寬。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>跟本卡的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../writing-multi-pass-review/">#83 Multi-pass review</a></td>
          <td>本卡是 #83 的延伸——#83 講「每輪換 frame」、本卡講「frame 本身要夠細、且需要工具 / 視角 / 層次三軸補強」</td>
      </tr>
      <tr>
          <td><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></td>
          <td>用「規則 frame 掃描」是 reviewer 的寫作便利、用「keyword bank + reader simulation」是費力但精準</td>
      </tr>
      <tr>
          <td><a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass review 的 scope 要蓋同類風險區</a></td>
          <td>#95 處理「scope 軸」（review 多廣）、本卡處理「frame 顆粒度軸」（規則展開多細）、兩軸正交</td>
      </tr>
      <tr>
          <td><a href="../design-flaw-by-current-axes-not-hindsight/">#110 設計檢討用當下三軸論證、不依賴 hindsight</a></td>
          <td>hindsight 視角會把 review framework 當「補丁」、self-criticism 用當下框架審視、跟 #110 同骨</td>
      </tr>
      <tr>
          <td><a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度</a></td>
          <td>#111 是字句層的「具體訊號」之一、本卡是「為什麼字句層訊號被 framework 漏 catch」的 meta 層</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>讀者反饋了 framework 裡找不到對應 frame</td>
          <td>加進 keyword bank、補進 framework 的 frame 列表</td>
      </tr>
      <tr>
          <td>跑 N 輪後同類問題仍出現</td>
          <td>framework 不夠細、加機制 1（keyword bank）</td>
      </tr>
      <tr>
          <td>reviewer 通順 / 讀者卡住</td>
          <td>加機制 2（reader simulation 輪）</td>
      </tr>
      <tr>
          <td>framework 從來沒被質疑過</td>
          <td>加機制 3（self-criticism 輪）、定期審視 framework 本身</td>
      </tr>
      <tr>
          <td>多輪 review 跑完還是同 reviewer</td>
          <td>引入外部讀者反饋、或刻意換視角（不同 IDE / 不同字體 / 跳段順序讀）</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：multi-pass review 用「規則 frame」掃描有效抓結構性違反、抓不到字句層具體訊號。要 catch 字句層、需要把規則展開成 keyword bank、加 reader simulation 視角、加 self-criticism 反向審視 framework 本身——三個機制各自處理同 reviewer 跑多輪仍 miss 的不同來源。</p>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡的觸發是修 <a href="../../work-log/dart_stream_controller_single_vs_broadcast/">Dart StreamController：single-subscription vs broadcast 的事故實錄</a> 時、跑了 4 輪 multi-pass review 後仍漏 catch 4 類字句層問題、由讀者點出。</p>
<p>讀者反饋的問題類型：</p>
<ol>
<li>口語化修辭（「一輩子只能 listen 一次」「立刻撞牆」「啊原來」「碰巧能用」）</li>
<li>地區用語漂移（「副屏」是中國用語、台灣用「副螢幕」）</li>
<li>依賴 code 論述（「事件 payload 第二段帶了」預設讀者看過 code）</li>
<li>廢話前綴 + 否定先行（「下次看到 X 時、不要先想 Y、先問 Z」）</li>
</ol>
<p>這 4 類問題對應的 frame 在 framework 裡都有（規則七機會成本、輪 4 術語、規則二商業邏輯、規則五最重要的話優先說）——但都沒展開到具體訊號層、所以 reviewer 跑了 4 輪都漏 catch。</p>
<p>對應本卡：<strong>framework 的覆蓋度盲點不能靠「再仔細一輪」修補——同一 reviewer 跑同 framework 多輪、catch 的東西高度相同。要真正擴大覆蓋度、需要 keyword bank（換工具）+ reader simulation（換視角）+ self-criticism（換層次）三個機制</strong>。</p>
<p>對 multi-pass review framework 的修補方向：把這 4 類問題加進對應 frame 的 keyword bank、加 reader simulation 輪當輪 8、加 self-criticism 輪當輪 9（或在每輪結尾加 self-criticism 子段）。</p>
]]></content:encoded></item><item><title>教材目標先於決策框架</title><link>https://tarrragon.github.io/blog/report/teaching-goal-before-decision-frame/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/teaching-goal-before-decision-frame/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>教材目標要先於決策框架。教學內容的責任是讓讀者建立某個領域的心智模型、操作語意、常見壓力與演進路徑；決策框架的責任是幫讀者在理解過程中抓住風險、成本與取捨。&lt;/p>
&lt;p>決策框架是教學工具，教材目標是上位目的。當一套 Backend 教材被描述成「服務能力、風險、成本與決策」時，這個描述能提醒作者補足必要判準；上位目標仍要明確寫成「教讀者理解後端服務如何運作、如何組合、如何演進」。&lt;/p>
&lt;h2 id="warp-分析摘要">WARP 分析摘要&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>Anchor&lt;/td>
 &lt;td>這次問題的錨點從「Backend 是否有足夠決策內容」上移到「Backend 是否完成教學設計」。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Step 0&lt;/td>
 &lt;td>現有資料足以判斷：Backend 已有大量內容、案例、vendor index 與 migration playbook，但主入口仍偏能力地圖與決策語言。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Widen&lt;/td>
 &lt;td>選項有三種：繼續寫服務選型、繼續寫 vendor / migration、先補教材目標與學習路線。第三種最貼合教學錨點。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reality Test&lt;/td>
 &lt;td>對照 LLM 與 Go 目錄，成熟教材都先說讀者要學會什麼，再安排心智模型、工具、實作與延伸。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Prepare&lt;/td>
 &lt;td>若後續 Backend 文章持續以「如何決策」起手，要用本卡重評估是否把教學目標降級成 governance frame。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>反向驗證：決策框架仍然必要。後端服務本身牽涉資料一致性、成本、事故與資安，教材需要同時講概念與取捨，讀者才有可操作判準。本卡的重點是層級排序：教材目標在上，決策框架在內。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>Backend 內容已累積到一定規模後，評估方向時容易把現有語言當成目標本身。前一輪評估把 Backend 的原始定位概括成「服務能力、風險、成本與決策」，這個概括抓到了內容中的重要維度，但讀者指出更準確的定位是「教學」。&lt;/p>
&lt;p>這個修正揭露了兩層差異：&lt;/p>
&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>讀者學完後，是否理解後端服務如何共同支撐 production system？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>決策框架&lt;/td>
 &lt;td>讀者理解每個服務時，是否知道能力、風險、成本與取捨？&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>第一層決定教材方向，第二層服務第一層。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="先寫教材要讓讀者學會什麼">先寫教材要讓讀者學會什麼&lt;/h3>
&lt;p>教材入口要先回答讀者學習成果。Backend 的學習成果應寫成「能看懂一個後端服務問題該交給哪類能力處理，並理解多個能力如何串接」；Redis / Kafka / Kubernetes 的優缺點比較則放在這個學習成果之下。&lt;/p>
&lt;p>較穩定的教材目標句是：&lt;/p>
&lt;blockquote>
&lt;p>Backend 教材教讀者理解後端服務如何承擔資料、流量、交接、觀測、部署、可靠性、資安、事故與容量責任，並學會把這些能力組合成可操作、可演進的 production system。&lt;/p>&lt;/blockquote>
&lt;h3 id="再放入必要認知框架">再放入必要認知框架&lt;/h3>
&lt;p>服務能力、風險、成本與決策應該保留在每篇文章內，它們是段落責任，系列標題則承擔教材目標。它們回答的是「理解這個服務時有哪些必要判準」。&lt;/p>
&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>讓讀者知道錯用或失效時會造成什麼後果&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>成本&lt;/td>
 &lt;td>讓讀者知道引入服務後誰要維護、支付與驗證&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>決策&lt;/td>
 &lt;td>讓讀者知道何時選、何時不選、何時回退&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="用內容結構保護教學目標">用內容結構保護教學目標&lt;/h3>
&lt;p>每個教學模組應先有學習路線，再有服務清單。服務清單是素材，學習路線才是教材。當文章先列 vendor、工具與 migration backlog，讀者會自然把教材理解成產品百科或選型資料庫。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="教材會變成決策備忘錄">教材會變成決策備忘錄&lt;/h3>
&lt;p>決策備忘錄能幫已經有背景的人判斷取捨，教材則要幫讀者建立概念。讀者看到大量「何時選 X」與「X 的成本」時，可能知道該問什麼問題，仍需要補上 X 在系統裡承擔什麼責任。&lt;/p>
&lt;h3 id="內容會被-vendor-與-migration-慣性帶走">內容會被 vendor 與 migration 慣性帶走&lt;/h3>
&lt;p>Vendor 頁與 migration playbook 很容易量產，因為每篇都有明確對象。教材目標放在上層時，內容會往「更清楚的學習梯度」收斂；教材目標缺位時，內容會自然往「更多服務、更多遷移」擴張。&lt;/p>
&lt;h3 id="讀者學習路線會被能力地圖取代">讀者學習路線會被能力地圖取代&lt;/h3>
&lt;p>能力地圖對作者有用，因為作者已知道整體結構。讀者需要的是先後順序：先理解什麼，再看什麼，遇到哪種問題跳到哪裡。缺少學習路線時，讀者會在能力地圖中自行找路，學習成本變高。&lt;/p>
&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;a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關&lt;/a>&lt;/td>
 &lt;td>把教材目標寫成決策框架很方便，因為它抽象且好列欄位；但便利描述未必對齊「教學」意圖。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="../prose-self-contained-without-code-reference/">#113 商業邏輯論述要 self-contained&lt;/a>&lt;/td>
 &lt;td>教材目標也要 self-contained；入口頁要直接說明 Backend 是教學，讓讀者在進入章節前取得學習錨點。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="../writing-review-multi-axis-completeness/">#126 寫作 review 是多軸完整性&lt;/a>&lt;/td>
 &lt;td>教材目標是 review 的 Anchor 軸。若 review 只看內容覆蓋，會漏掉「這是否仍是教材」這個上位問題。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="../content-structure-by-max-diff-dimension/">#127 Process content 結構由最大差異維度決定&lt;/a>&lt;/td>
 &lt;td>#127 說 process content 結構由差異維度決定；本卡補教材 content 的上位結構由學習目標決定。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&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>入口頁像服務清單或 vendor roadmap&lt;/td>
 &lt;td>補學習路線與讀者旅程&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>每篇文章都能做取捨分析，但讀者不知道先讀哪篇&lt;/td>
 &lt;td>補模組梯度與貫穿式案例&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Migration / vendor backlog 持續增加，主線教學沒有變清楚&lt;/td>
 &lt;td>暫停量產，回到教材設計&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Review 只問「內容有沒有覆蓋」&lt;/td>
 &lt;td>加問「這段是否服務教材目標」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>核心原則&lt;/strong>：教材要先定義學習成果，再放入決策框架。服務能力、風險、成本與決策是理解 Backend 的必要工具，但教材的上位目標是教讀者建立後端服務的心智模型與操作語意。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p>教材目標要先於決策框架。教學內容的責任是讓讀者建立某個領域的心智模型、操作語意、常見壓力與演進路徑；決策框架的責任是幫讀者在理解過程中抓住風險、成本與取捨。</p>
<p>決策框架是教學工具，教材目標是上位目的。當一套 Backend 教材被描述成「服務能力、風險、成本與決策」時，這個描述能提醒作者補足必要判準；上位目標仍要明確寫成「教讀者理解後端服務如何運作、如何組合、如何演進」。</p>
<h2 id="warp-分析摘要">WARP 分析摘要</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anchor</td>
          <td>這次問題的錨點從「Backend 是否有足夠決策內容」上移到「Backend 是否完成教學設計」。</td>
      </tr>
      <tr>
          <td>Step 0</td>
          <td>現有資料足以判斷：Backend 已有大量內容、案例、vendor index 與 migration playbook，但主入口仍偏能力地圖與決策語言。</td>
      </tr>
      <tr>
          <td>Widen</td>
          <td>選項有三種：繼續寫服務選型、繼續寫 vendor / migration、先補教材目標與學習路線。第三種最貼合教學錨點。</td>
      </tr>
      <tr>
          <td>Reality Test</td>
          <td>對照 LLM 與 Go 目錄，成熟教材都先說讀者要學會什麼，再安排心智模型、工具、實作與延伸。</td>
      </tr>
      <tr>
          <td>Prepare</td>
          <td>若後續 Backend 文章持續以「如何決策」起手，要用本卡重評估是否把教學目標降級成 governance frame。</td>
      </tr>
  </tbody>
</table>
<p>反向驗證：決策框架仍然必要。後端服務本身牽涉資料一致性、成本、事故與資安，教材需要同時講概念與取捨，讀者才有可操作判準。本卡的重點是層級排序：教材目標在上，決策框架在內。</p>
<h2 id="情境">情境</h2>
<p>Backend 內容已累積到一定規模後，評估方向時容易把現有語言當成目標本身。前一輪評估把 Backend 的原始定位概括成「服務能力、風險、成本與決策」，這個概括抓到了內容中的重要維度，但讀者指出更準確的定位是「教學」。</p>
<p>這個修正揭露了兩層差異：</p>
<table>
  <thead>
      <tr>
          <th>層級</th>
          <th>問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>教材目標</td>
          <td>讀者學完後，是否理解後端服務如何共同支撐 production system？</td>
      </tr>
      <tr>
          <td>決策框架</td>
          <td>讀者理解每個服務時，是否知道能力、風險、成本與取捨？</td>
      </tr>
  </tbody>
</table>
<p>第一層決定教材方向，第二層服務第一層。</p>
<h2 id="理想做法">理想做法</h2>
<h3 id="先寫教材要讓讀者學會什麼">先寫教材要讓讀者學會什麼</h3>
<p>教材入口要先回答讀者學習成果。Backend 的學習成果應寫成「能看懂一個後端服務問題該交給哪類能力處理，並理解多個能力如何串接」；Redis / Kafka / Kubernetes 的優缺點比較則放在這個學習成果之下。</p>
<p>較穩定的教材目標句是：</p>
<blockquote>
<p>Backend 教材教讀者理解後端服務如何承擔資料、流量、交接、觀測、部署、可靠性、資安、事故與容量責任，並學會把這些能力組合成可操作、可演進的 production system。</p></blockquote>
<h3 id="再放入必要認知框架">再放入必要認知框架</h3>
<p>服務能力、風險、成本與決策應該保留在每篇文章內，它們是段落責任，系列標題則承擔教材目標。它們回答的是「理解這個服務時有哪些必要判準」。</p>
<table>
  <thead>
      <tr>
          <th>必要概念</th>
          <th>教學責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務能力</td>
          <td>讓讀者知道這類服務負責哪段系統責任</td>
      </tr>
      <tr>
          <td>風險</td>
          <td>讓讀者知道錯用或失效時會造成什麼後果</td>
      </tr>
      <tr>
          <td>成本</td>
          <td>讓讀者知道引入服務後誰要維護、支付與驗證</td>
      </tr>
      <tr>
          <td>決策</td>
          <td>讓讀者知道何時選、何時不選、何時回退</td>
      </tr>
  </tbody>
</table>
<h3 id="用內容結構保護教學目標">用內容結構保護教學目標</h3>
<p>每個教學模組應先有學習路線，再有服務清單。服務清單是素材，學習路線才是教材。當文章先列 vendor、工具與 migration backlog，讀者會自然把教材理解成產品百科或選型資料庫。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="教材會變成決策備忘錄">教材會變成決策備忘錄</h3>
<p>決策備忘錄能幫已經有背景的人判斷取捨，教材則要幫讀者建立概念。讀者看到大量「何時選 X」與「X 的成本」時，可能知道該問什麼問題，仍需要補上 X 在系統裡承擔什麼責任。</p>
<h3 id="內容會被-vendor-與-migration-慣性帶走">內容會被 vendor 與 migration 慣性帶走</h3>
<p>Vendor 頁與 migration playbook 很容易量產，因為每篇都有明確對象。教材目標放在上層時，內容會往「更清楚的學習梯度」收斂；教材目標缺位時，內容會自然往「更多服務、更多遷移」擴張。</p>
<h3 id="讀者學習路線會被能力地圖取代">讀者學習路線會被能力地圖取代</h3>
<p>能力地圖對作者有用，因為作者已知道整體結構。讀者需要的是先後順序：先理解什麼，再看什麼，遇到哪種問題跳到哪裡。缺少學習路線時，讀者會在能力地圖中自行找路，學習成本變高。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../ease-of-writing-vs-intent-alignment/">#67 寫作便利度跟意圖對齊反相關</a></td>
          <td>把教材目標寫成決策框架很方便，因為它抽象且好列欄位；但便利描述未必對齊「教學」意圖。</td>
      </tr>
      <tr>
          <td><a href="../prose-self-contained-without-code-reference/">#113 商業邏輯論述要 self-contained</a></td>
          <td>教材目標也要 self-contained；入口頁要直接說明 Backend 是教學，讓讀者在進入章節前取得學習錨點。</td>
      </tr>
      <tr>
          <td><a href="../writing-review-multi-axis-completeness/">#126 寫作 review 是多軸完整性</a></td>
          <td>教材目標是 review 的 Anchor 軸。若 review 只看內容覆蓋，會漏掉「這是否仍是教材」這個上位問題。</td>
      </tr>
      <tr>
          <td><a href="../content-structure-by-max-diff-dimension/">#127 Process content 結構由最大差異維度決定</a></td>
          <td>#127 說 process content 結構由差異維度決定；本卡補教材 content 的上位結構由學習目標決定。</td>
      </tr>
  </tbody>
</table>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>系列定位只剩能力、風險、成本、決策</td>
          <td>重新寫教材目標句，先說讀者要學會什麼</td>
      </tr>
      <tr>
          <td>入口頁像服務清單或 vendor roadmap</td>
          <td>補學習路線與讀者旅程</td>
      </tr>
      <tr>
          <td>每篇文章都能做取捨分析，但讀者不知道先讀哪篇</td>
          <td>補模組梯度與貫穿式案例</td>
      </tr>
      <tr>
          <td>Migration / vendor backlog 持續增加，主線教學沒有變清楚</td>
          <td>暫停量產，回到教材設計</td>
      </tr>
      <tr>
          <td>Review 只問「內容有沒有覆蓋」</td>
          <td>加問「這段是否服務教材目標」</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：教材要先定義學習成果，再放入決策框架。服務能力、風險、成本與決策是理解 Backend 的必要工具，但教材的上位目標是教讀者建立後端服務的心智模型與操作語意。</p>
]]></content:encoded></item><item><title>教材完整性要用讀者旅程驗證</title><link>https://tarrragon.github.io/blog/report/teaching-completeness-by-learner-journey/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/teaching-completeness-by-learner-journey/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>教材完整性要用讀者旅程驗證。章節數、案例數、vendor 頁數與 knowledge card 數量能證明素材充足；完成設計的教材還能回答不同讀者「我該從哪裡開始、按什麼順序讀、讀完能做什麼」。&lt;/p>
&lt;p>讀者旅程是教材的 routing layer。它把素材庫、主章、案例、實作與進階專題組成學習路線，讓讀者直接取得順序，而非從內容地圖中自行推導。&lt;/p>
&lt;h2 id="warp-分析摘要">WARP 分析摘要&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>Anchor&lt;/td>
 &lt;td>評估 Backend 是否完成教學設計，要看讀者能否找到學習路線，內容量只是前置條件。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Step 0&lt;/td>
 &lt;td>對照 LLM / Go / Go advanced，成熟入口都明確列出目標讀者、學習路線、模組分工與主題導讀。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Widen&lt;/td>
 &lt;td>可用三種指標：內容覆蓋、結構覆蓋、讀者旅程覆蓋。教材完整性應以第三種為主。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reality Test&lt;/td>
 &lt;td>Backend 目前有內容覆蓋與結構覆蓋，但讀者路線仍偏弱；LLM 與 Go 則能讓讀者依目的選路。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Prepare&lt;/td>
 &lt;td>若後續新增章節後只能說出內容清單、說不出 3-5 條讀者路線，代表教材設計仍在素材整理階段。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>反向驗證：讀者旅程與完整目錄各有責任。完整目錄仍是查閱與維護入口；讀者旅程是學習入口。兩者分工是「目錄服務作者與回查，旅程服務學習」。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>Backend 內容已經具備大量材料：主章、案例庫、vendor 頁、migration playbook、knowledge cards 都很完整。若只用內容覆蓋判斷，很容易得到「教學內容已經完成」的結論。&lt;/p>
&lt;p>對照 LLM 與 Go 後，真正差異浮現：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>教材&lt;/th>
 &lt;th>完整性訊號&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>LLM&lt;/td>
 &lt;td>依目的分路線：本地 Mac、PC GPU、理論、應用、安全&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Go&lt;/td>
 &lt;td>依學習梯度排序：哲學、基礎、型別、標準庫、並發、測試、實戰、重構&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Go advanced&lt;/td>
 &lt;td>依角色分路線：並發服務維護者、WebSocket/API 開發者、效能與可靠性工程師&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Backend&lt;/td>
 &lt;td>目前主要依能力分類：資料庫、快取、queue、觀測、部署、可靠性、資安、事故、效能&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Backend 的能力分類正確；下一層要補讀者旅程。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="第一步先列讀者旅程">第一步：先列讀者旅程&lt;/h3>
&lt;p>教材入口應先列 3-5 條讀者路線，每條路線都要有起點、順序與完成狀態。&lt;/p>
&lt;p>Backend 可用的路線範例：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>想理解 backend 服務分工&lt;/td>
 &lt;td>00 → knowledge cards → 01/02/03 概念章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API 到資料流&lt;/td>
 &lt;td>想設計 API 背後的 DB / cache / queue&lt;/td>
 &lt;td>01 → 02 → 03 → 04 evidence&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Production 操作&lt;/td>
 &lt;td>想學觀測、部署、可靠性與事故&lt;/td>
 &lt;td>04 → 05 → 06 → 08&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Security / data protection&lt;/td>
 &lt;td>想理解權限、資料、偵測與回應&lt;/td>
 &lt;td>07 → 04 audit evidence → 08 security incident&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Vendor / migration&lt;/td>
 &lt;td>已懂分類、要比較工具或遷移&lt;/td>
 &lt;td>對應 vendors/ → migration playbook → 案例&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這些路線主要重組現有內容，把內容地圖整理成讀者可走的路。&lt;/p>
&lt;h3 id="第二步為每條路線定義讀完能做什麼">第二步：為每條路線定義讀完能做什麼&lt;/h3>
&lt;p>學習路線要有完成判準。只列「讀 A、讀 B、讀 C」仍像目錄；加上「讀完能判斷什麼」才是教學設計。&lt;/p>
&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>能把一個需求分類成 state、cache、queue、observability、deployment 或 reliability 問題&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API 到資料流&lt;/td>
 &lt;td>能說明一次 checkout 如何跨 DB、cache、queue 與 evidence package&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Production 操作&lt;/td>
 &lt;td>能把 release、alert、gate、incident decision log 串成閉環&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Security / data protection&lt;/td>
 &lt;td>能從身份、資料、入口、秘密與 audit evidence 判讀控制面&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Vendor / migration&lt;/td>
 &lt;td>能先判斷分類責任，再比較具體服務與遷移成本&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="第三步用旅程檢查內容缺口">第三步：用旅程檢查內容缺口&lt;/h3>
&lt;p>內容缺口要從旅程反推。若某條路線中間需要讀者自己跳轉，就代表教材設計有洞。&lt;/p>
&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>路線跨模組時只靠零散 link&lt;/td>
 &lt;td>缺少串接章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>路線完成後沒有實作或案例&lt;/td>
 &lt;td>缺少可操作收束&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>vendor / migration 入口早於分類心智模型&lt;/td>
 &lt;td>進階材料壓過主線&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="內容越多讀者越難開始">內容越多，讀者越難開始&lt;/h3>
&lt;p>素材量增加會讓作者覺得教材完整，但讀者面對大量章節時需要的是順序。沒有讀者旅程時，內容量越大，入口成本越高。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p>教材完整性要用讀者旅程驗證。章節數、案例數、vendor 頁數與 knowledge card 數量能證明素材充足；完成設計的教材還能回答不同讀者「我該從哪裡開始、按什麼順序讀、讀完能做什麼」。</p>
<p>讀者旅程是教材的 routing layer。它把素材庫、主章、案例、實作與進階專題組成學習路線，讓讀者直接取得順序，而非從內容地圖中自行推導。</p>
<h2 id="warp-分析摘要">WARP 分析摘要</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anchor</td>
          <td>評估 Backend 是否完成教學設計，要看讀者能否找到學習路線，內容量只是前置條件。</td>
      </tr>
      <tr>
          <td>Step 0</td>
          <td>對照 LLM / Go / Go advanced，成熟入口都明確列出目標讀者、學習路線、模組分工與主題導讀。</td>
      </tr>
      <tr>
          <td>Widen</td>
          <td>可用三種指標：內容覆蓋、結構覆蓋、讀者旅程覆蓋。教材完整性應以第三種為主。</td>
      </tr>
      <tr>
          <td>Reality Test</td>
          <td>Backend 目前有內容覆蓋與結構覆蓋，但讀者路線仍偏弱；LLM 與 Go 則能讓讀者依目的選路。</td>
      </tr>
      <tr>
          <td>Prepare</td>
          <td>若後續新增章節後只能說出內容清單、說不出 3-5 條讀者路線，代表教材設計仍在素材整理階段。</td>
      </tr>
  </tbody>
</table>
<p>反向驗證：讀者旅程與完整目錄各有責任。完整目錄仍是查閱與維護入口；讀者旅程是學習入口。兩者分工是「目錄服務作者與回查，旅程服務學習」。</p>
<h2 id="情境">情境</h2>
<p>Backend 內容已經具備大量材料：主章、案例庫、vendor 頁、migration playbook、knowledge cards 都很完整。若只用內容覆蓋判斷，很容易得到「教學內容已經完成」的結論。</p>
<p>對照 LLM 與 Go 後，真正差異浮現：</p>
<table>
  <thead>
      <tr>
          <th>教材</th>
          <th>完整性訊號</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>LLM</td>
          <td>依目的分路線：本地 Mac、PC GPU、理論、應用、安全</td>
      </tr>
      <tr>
          <td>Go</td>
          <td>依學習梯度排序：哲學、基礎、型別、標準庫、並發、測試、實戰、重構</td>
      </tr>
      <tr>
          <td>Go advanced</td>
          <td>依角色分路線：並發服務維護者、WebSocket/API 開發者、效能與可靠性工程師</td>
      </tr>
      <tr>
          <td>Backend</td>
          <td>目前主要依能力分類：資料庫、快取、queue、觀測、部署、可靠性、資安、事故、效能</td>
      </tr>
  </tbody>
</table>
<p>Backend 的能力分類正確；下一層要補讀者旅程。</p>
<h2 id="理想做法">理想做法</h2>
<h3 id="第一步先列讀者旅程">第一步：先列讀者旅程</h3>
<p>教材入口應先列 3-5 條讀者路線，每條路線都要有起點、順序與完成狀態。</p>
<p>Backend 可用的路線範例：</p>
<table>
  <thead>
      <tr>
          <th>路線</th>
          <th>適合讀者</th>
          <th>閱讀順序</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>系統心智模型</td>
          <td>想理解 backend 服務分工</td>
          <td>00 → knowledge cards → 01/02/03 概念章</td>
      </tr>
      <tr>
          <td>API 到資料流</td>
          <td>想設計 API 背後的 DB / cache / queue</td>
          <td>01 → 02 → 03 → 04 evidence</td>
      </tr>
      <tr>
          <td>Production 操作</td>
          <td>想學觀測、部署、可靠性與事故</td>
          <td>04 → 05 → 06 → 08</td>
      </tr>
      <tr>
          <td>Security / data protection</td>
          <td>想理解權限、資料、偵測與回應</td>
          <td>07 → 04 audit evidence → 08 security incident</td>
      </tr>
      <tr>
          <td>Vendor / migration</td>
          <td>已懂分類、要比較工具或遷移</td>
          <td>對應 vendors/ → migration playbook → 案例</td>
      </tr>
  </tbody>
</table>
<p>這些路線主要重組現有內容，把內容地圖整理成讀者可走的路。</p>
<h3 id="第二步為每條路線定義讀完能做什麼">第二步：為每條路線定義讀完能做什麼</h3>
<p>學習路線要有完成判準。只列「讀 A、讀 B、讀 C」仍像目錄；加上「讀完能判斷什麼」才是教學設計。</p>
<table>
  <thead>
      <tr>
          <th>路線</th>
          <th>完成判準</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>系統心智模型</td>
          <td>能把一個需求分類成 state、cache、queue、observability、deployment 或 reliability 問題</td>
      </tr>
      <tr>
          <td>API 到資料流</td>
          <td>能說明一次 checkout 如何跨 DB、cache、queue 與 evidence package</td>
      </tr>
      <tr>
          <td>Production 操作</td>
          <td>能把 release、alert、gate、incident decision log 串成閉環</td>
      </tr>
      <tr>
          <td>Security / data protection</td>
          <td>能從身份、資料、入口、秘密與 audit evidence 判讀控制面</td>
      </tr>
      <tr>
          <td>Vendor / migration</td>
          <td>能先判斷分類責任，再比較具體服務與遷移成本</td>
      </tr>
  </tbody>
</table>
<h3 id="第三步用旅程檢查內容缺口">第三步：用旅程檢查內容缺口</h3>
<p>內容缺口要從旅程反推。若某條路線中間需要讀者自己跳轉，就代表教材設計有洞。</p>
<table>
  <thead>
      <tr>
          <th>缺口訊號</th>
          <th>代表問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>路線需要讀者自己從十幾篇找下一篇</td>
          <td>缺少導讀</td>
      </tr>
      <tr>
          <td>路線跨模組時只靠零散 link</td>
          <td>缺少串接章</td>
      </tr>
      <tr>
          <td>路線完成後沒有實作或案例</td>
          <td>缺少可操作收束</td>
      </tr>
      <tr>
          <td>vendor / migration 入口早於分類心智模型</td>
          <td>進階材料壓過主線</td>
      </tr>
  </tbody>
</table>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="內容越多讀者越難開始">內容越多，讀者越難開始</h3>
<p>素材量增加會讓作者覺得教材完整，但讀者面對大量章節時需要的是順序。沒有讀者旅程時，內容量越大，入口成本越高。</p>
<h3 id="作者會誤把-backlog-完成當成教材完成">作者會誤把 backlog 完成當成教材完成</h3>
<p>Vendor backlog、migration backlog 與案例庫都有清楚項目，很容易形成完成感。教學完成感應該來自「讀者能走完一條路線」；作者清單完成只是素材面的進度。</p>
<h3 id="review-會偏向覆蓋率不看學習梯度">Review 會偏向覆蓋率，不看學習梯度</h3>
<p>審查時若只問「哪些主題還沒寫」，會自然補更多主題。讀者旅程 frame 會改問「這些主題排列後，讀者是否能從低負擔走到高負擔」。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../cards-as-living-system-iteration/">#81 卡片系統的迭代浮現</a></td>
          <td>讀者旅程是卡片 / 主章 / 案例累積後浮現的 meta-layer，不應在素材不足時硬設，也不應在素材充足後缺席。</td>
      </tr>
      <tr>
          <td><a href="../metadata-surface-in-writing-review/">#97 Metadata surface 要納入寫作 review 範圍</a></td>
          <td>讀者旅程是系列級 metadata surface；它是讀者進入內容前最先看到的 routing 文字。</td>
      </tr>
      <tr>
          <td><a href="../routing-layer-chapter-recognition/">#119 章節已有 routing skeleton 走補強段</a></td>
          <td>本卡把 routing layer 從單章提升到系列入口。系列入口已有能力地圖時，下一步是補旅程路由。</td>
      </tr>
      <tr>
          <td><a href="../writing-review-multi-axis-completeness/">#126 寫作 review 是多軸完整性</a></td>
          <td>教材 review 要新增 learner journey 軸；surface、scope、cadence 之外還要檢查教材是否能被學習。</td>
      </tr>
      <tr>
          <td><a href="../teaching-goal-before-decision-frame/">#130 教材目標先於決策框架</a></td>
          <td>#130 定義上位目標，本卡定義如何驗證該目標是否落到讀者路線。</td>
      </tr>
  </tbody>
</table>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>入口頁能列完整模組，讀者路線仍缺席</td>
          <td>補「學習路線」段</td>
      </tr>
      <tr>
          <td>讀者需要自己判斷先看主章、案例還是 vendor</td>
          <td>補起點與完成判準</td>
      </tr>
      <tr>
          <td>章節很多但沒有「讀完能做什麼」</td>
          <td>補每條路線的學習成果</td>
      </tr>
      <tr>
          <td>新增內容多集中在 backlog，而非導讀</td>
          <td>暫停新增素材，先整理 routing</td>
      </tr>
      <tr>
          <td>對照成熟教材時，只能對到目錄，對不到旅程</td>
          <td>教學設計尚未完成</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：教材完整性由讀者旅程驗證，內容覆蓋率只是一個輸入。成熟教材能讓不同目的的讀者找到起點、順序與完成判準；內容地圖服務查閱，讀者旅程服務學習。</p>
]]></content:encoded></item><item><title>貫穿式案例是服務教材的教學骨架</title><link>https://tarrragon.github.io/blog/report/throughline-case-as-teaching-spine/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/throughline-case-as-teaching-spine/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>服務型教材需要貫穿式案例作為教學骨架。資料庫、快取、queue、觀測、部署、可靠性、資安、事故與容量都可以獨立成章，但讀者真正需要學會的是這些能力如何在同一個服務裡交接、互相約束並共同演進。&lt;/p>
&lt;p>貫穿式案例是一條可重播的服務演進路徑，而非單一大型專案手冊。它用同一個中性服務情境反覆穿過多個模組，讓讀者看到每個模組處理的是同一個系統在不同壓力下的責任切面。&lt;/p>
&lt;h2 id="warp-分析摘要">WARP 分析摘要&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>Anchor&lt;/td>
 &lt;td>Backend 教材要教的是後端服務如何共同支撐 production system，單章正確不足以證明整體教學成立。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Step 0&lt;/td>
 &lt;td>現有 Backend 已有多個服務路徑示範與 artifact backbone，但還缺系列入口層明示的貫穿式案例。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Widen&lt;/td>
 &lt;td>可選方式有能力分類、讀者旅程、貫穿式案例。三者可疊加：能力分類是目錄，讀者旅程是路線，貫穿式案例是演練骨架。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reality Test&lt;/td>
 &lt;td>Go 用簡化通知服務承接語法到實戰，LLM 用本地 LLM 工作流承接心智模型到工具；Backend 也需要同類骨架。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Prepare&lt;/td>
 &lt;td>若後續章節各自引用不同情境，讀者仍難以看出 DB / cache / queue / observability / incident 如何在同一服務內交接。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>反向驗證：貫穿式案例要維持中性、簡化、可替換，並明示它是教學載體；讀者理解案例所需的背景要由文章提供，而非內部專案知識。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>Backend 已有多篇服務路徑示範，例如 schema migration evidence、cache migration rollback、queue retry replay、checkout API evidence package、release gate、credential rotation 與 incident decision log。這些文章各自能說明一段能力，但它們在入口層還沒有被明確收斂成一條「讀者可以跟著走」的服務演進路線。&lt;/p>
&lt;p>對照 Go 與 LLM：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>教材&lt;/th>
 &lt;th>貫穿骨架&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Go&lt;/td>
 &lt;td>從小程式走到簡化即時通知服務&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Go advanced&lt;/td>
 &lt;td>用長時間運行服務、WebSocket、event-driven service 當重複情境&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM&lt;/td>
 &lt;td>用本地 LLM 寫 code 工作流，把硬體、推論伺服器、模型、IDE、安全串起來&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Backend&lt;/td>
 &lt;td>目前多個 artifact 示範分散存在，尚未在入口層組成一條主案例&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Backend 的內容特性更需要貫穿式案例，因為它處理的是多個外部服務的協作教材，範圍大於單一語言或單一工具。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="第一步選一個中性服務作為載體">第一步：選一個中性服務作為載體&lt;/h3>
&lt;p>貫穿式案例應該選讀者容易理解、又能自然觸發多個 Backend 模組的服務。較穩定的候選是 &lt;code>checkout / order / payment / notification&lt;/code> 類流程。&lt;/p>
&lt;p>這條服務路徑可承接：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模組&lt;/th>
 &lt;th>在案例中的責任&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>01 Database&lt;/td>
 &lt;td>order / payment 狀態、schema migration、reconciliation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>02 Cache&lt;/td>
 &lt;td>商品、價格或 entitlement 的 freshness 與 origin protection&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>03 Queue&lt;/td>
 &lt;td>order_created / payment_confirmed 的 retry、DLQ、replay&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>04 Observability&lt;/td>
 &lt;td>checkout evidence package、trace、dashboard、query link&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>05 Deployment&lt;/td>
 &lt;td>checkout service rollout、drain、rollback&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>06 Reliability&lt;/td>
 &lt;td>provider dependency release gate、load / chaos / regression&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>07 Security&lt;/td>
 &lt;td>webhook secret rotation、PII masking、audit evidence&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>08 Incident&lt;/td>
 &lt;td>payment incident decision log、write-back、action item&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>09 Performance&lt;/td>
 &lt;td>peak checkout capacity、saturation、cost per request&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="第二步把案例拆成多個可重播-episode">第二步：把案例拆成多個可重播 episode&lt;/h3>
&lt;p>貫穿式案例要避免寫成一篇巨文。較穩定的做法是拆成 episode，每個 episode 對應一個模組責任。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Episode&lt;/th>
 &lt;th>問題&lt;/th>
 &lt;th>主要模組&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>E1&lt;/td>
 &lt;td>新增付款狀態欄位&lt;/td>
 &lt;td>01 + 04 + 08&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>E2&lt;/td>
 &lt;td>商品價格快取失效與回源保護&lt;/td>
 &lt;td>02 + 04 + 06&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>E3&lt;/td>
 &lt;td>訂單事件 consumer 失敗與 replay&lt;/td>
 &lt;td>03 + 06 + 08&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>E4&lt;/td>
 &lt;td>Checkout service rollout&lt;/td>
 &lt;td>05 + 04 + 08&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>E5&lt;/td>
 &lt;td>Payment provider timeout 變更&lt;/td>
 &lt;td>06 + 04 + 09&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>E6&lt;/td>
 &lt;td>Webhook secret rotation&lt;/td>
 &lt;td>07 + 04 + 08&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>E7&lt;/td>
 &lt;td>Flash-sale peak readiness&lt;/td>
 &lt;td>09 + 02 + 03 + 06&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Episode 讓讀者看到「同一服務在不同壓力下需要不同模組」，同時保留單篇文章的原子性。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p>服務型教材需要貫穿式案例作為教學骨架。資料庫、快取、queue、觀測、部署、可靠性、資安、事故與容量都可以獨立成章，但讀者真正需要學會的是這些能力如何在同一個服務裡交接、互相約束並共同演進。</p>
<p>貫穿式案例是一條可重播的服務演進路徑，而非單一大型專案手冊。它用同一個中性服務情境反覆穿過多個模組，讓讀者看到每個模組處理的是同一個系統在不同壓力下的責任切面。</p>
<h2 id="warp-分析摘要">WARP 分析摘要</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anchor</td>
          <td>Backend 教材要教的是後端服務如何共同支撐 production system，單章正確不足以證明整體教學成立。</td>
      </tr>
      <tr>
          <td>Step 0</td>
          <td>現有 Backend 已有多個服務路徑示範與 artifact backbone，但還缺系列入口層明示的貫穿式案例。</td>
      </tr>
      <tr>
          <td>Widen</td>
          <td>可選方式有能力分類、讀者旅程、貫穿式案例。三者可疊加：能力分類是目錄，讀者旅程是路線，貫穿式案例是演練骨架。</td>
      </tr>
      <tr>
          <td>Reality Test</td>
          <td>Go 用簡化通知服務承接語法到實戰，LLM 用本地 LLM 工作流承接心智模型到工具；Backend 也需要同類骨架。</td>
      </tr>
      <tr>
          <td>Prepare</td>
          <td>若後續章節各自引用不同情境，讀者仍難以看出 DB / cache / queue / observability / incident 如何在同一服務內交接。</td>
      </tr>
  </tbody>
</table>
<p>反向驗證：貫穿式案例要維持中性、簡化、可替換，並明示它是教學載體；讀者理解案例所需的背景要由文章提供，而非內部專案知識。</p>
<h2 id="情境">情境</h2>
<p>Backend 已有多篇服務路徑示範，例如 schema migration evidence、cache migration rollback、queue retry replay、checkout API evidence package、release gate、credential rotation 與 incident decision log。這些文章各自能說明一段能力，但它們在入口層還沒有被明確收斂成一條「讀者可以跟著走」的服務演進路線。</p>
<p>對照 Go 與 LLM：</p>
<table>
  <thead>
      <tr>
          <th>教材</th>
          <th>貫穿骨架</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Go</td>
          <td>從小程式走到簡化即時通知服務</td>
      </tr>
      <tr>
          <td>Go advanced</td>
          <td>用長時間運行服務、WebSocket、event-driven service 當重複情境</td>
      </tr>
      <tr>
          <td>LLM</td>
          <td>用本地 LLM 寫 code 工作流，把硬體、推論伺服器、模型、IDE、安全串起來</td>
      </tr>
      <tr>
          <td>Backend</td>
          <td>目前多個 artifact 示範分散存在，尚未在入口層組成一條主案例</td>
      </tr>
  </tbody>
</table>
<p>Backend 的內容特性更需要貫穿式案例，因為它處理的是多個外部服務的協作教材，範圍大於單一語言或單一工具。</p>
<h2 id="理想做法">理想做法</h2>
<h3 id="第一步選一個中性服務作為載體">第一步：選一個中性服務作為載體</h3>
<p>貫穿式案例應該選讀者容易理解、又能自然觸發多個 Backend 模組的服務。較穩定的候選是 <code>checkout / order / payment / notification</code> 類流程。</p>
<p>這條服務路徑可承接：</p>
<table>
  <thead>
      <tr>
          <th>模組</th>
          <th>在案例中的責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>01 Database</td>
          <td>order / payment 狀態、schema migration、reconciliation</td>
      </tr>
      <tr>
          <td>02 Cache</td>
          <td>商品、價格或 entitlement 的 freshness 與 origin protection</td>
      </tr>
      <tr>
          <td>03 Queue</td>
          <td>order_created / payment_confirmed 的 retry、DLQ、replay</td>
      </tr>
      <tr>
          <td>04 Observability</td>
          <td>checkout evidence package、trace、dashboard、query link</td>
      </tr>
      <tr>
          <td>05 Deployment</td>
          <td>checkout service rollout、drain、rollback</td>
      </tr>
      <tr>
          <td>06 Reliability</td>
          <td>provider dependency release gate、load / chaos / regression</td>
      </tr>
      <tr>
          <td>07 Security</td>
          <td>webhook secret rotation、PII masking、audit evidence</td>
      </tr>
      <tr>
          <td>08 Incident</td>
          <td>payment incident decision log、write-back、action item</td>
      </tr>
      <tr>
          <td>09 Performance</td>
          <td>peak checkout capacity、saturation、cost per request</td>
      </tr>
  </tbody>
</table>
<h3 id="第二步把案例拆成多個可重播-episode">第二步：把案例拆成多個可重播 episode</h3>
<p>貫穿式案例要避免寫成一篇巨文。較穩定的做法是拆成 episode，每個 episode 對應一個模組責任。</p>
<table>
  <thead>
      <tr>
          <th>Episode</th>
          <th>問題</th>
          <th>主要模組</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>E1</td>
          <td>新增付款狀態欄位</td>
          <td>01 + 04 + 08</td>
      </tr>
      <tr>
          <td>E2</td>
          <td>商品價格快取失效與回源保護</td>
          <td>02 + 04 + 06</td>
      </tr>
      <tr>
          <td>E3</td>
          <td>訂單事件 consumer 失敗與 replay</td>
          <td>03 + 06 + 08</td>
      </tr>
      <tr>
          <td>E4</td>
          <td>Checkout service rollout</td>
          <td>05 + 04 + 08</td>
      </tr>
      <tr>
          <td>E5</td>
          <td>Payment provider timeout 變更</td>
          <td>06 + 04 + 09</td>
      </tr>
      <tr>
          <td>E6</td>
          <td>Webhook secret rotation</td>
          <td>07 + 04 + 08</td>
      </tr>
      <tr>
          <td>E7</td>
          <td>Flash-sale peak readiness</td>
          <td>09 + 02 + 03 + 06</td>
      </tr>
  </tbody>
</table>
<p>Episode 讓讀者看到「同一服務在不同壓力下需要不同模組」，同時保留單篇文章的原子性。</p>
<h3 id="第三步讓每章都回到同一條服務路徑">第三步：讓每章都回到同一條服務路徑</h3>
<p>每篇主章不需要都重述整個案例，但要能指出它在貫穿案例中的位置。這樣讀者可從任一章回到主線，也可按主線依序讀。</p>
<p>最小寫法：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="ln">1</span><span class="cl">本章在貫穿式 checkout 案例中處理 E3：訂單事件 consumer 失敗後，如何判斷投遞、處理與恢復語意。</span></span></code></pre></div><p>這句話把章節放回教學骨架，避免單章漂成孤立知識點。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="章節各自正確但整體難學">章節各自正確，但整體難學</h3>
<p>資料庫、快取、queue、觀測與事故章節都可以各自寫得正確。讀者看過它們如何在同一條服務路徑交接後，平行知識才會組成 production system 的整體模型。</p>
<h3 id="案例庫會停在素材層">案例庫會停在素材層</h3>
<p>大量 case 能支撐反向驗證，但 case 本身不會自動形成學習路線。貫穿式案例的責任是把素材庫轉成讀者可重播的主情境。</p>
<h3 id="vendor--migration-內容會太早成為主角">Vendor / migration 內容會太早成為主角</h3>
<p>讀者在還沒理解服務交接前讀 vendor 或 migration，容易把具體工具當成主線。貫穿式案例能先建立「問題如何跨模組流動」，再讓 vendor / migration 成為進階專題。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../source-library-ratio-supports-scenario-validation/">#98 素材庫比例要支撐主情境的反向驗證</a></td>
          <td>#98 說素材庫要支撐主情境；本卡定義服務教材的主情境應有一條貫穿式案例。</td>
      </tr>
      <tr>
          <td><a href="../case-citation-three-part-structure/">#120 案例引用三段式段落結構</a></td>
          <td>貫穿式案例在單段引用時仍要遵守概念定義 → case 引用 → 通用展開，不讓 case 取代概念。</td>
      </tr>
      <tr>
          <td><a href="../routing-layer-chapter-recognition/">#119 章節已有 routing skeleton 走補強段</a></td>
          <td>貫穿式案例是系列級 routing skeleton。後續擴章要補 episode 與路由，保留既有主線。</td>
      </tr>
      <tr>
          <td><a href="../teaching-goal-before-decision-frame/">#130 教材目標先於決策框架</a></td>
          <td>#130 定義教材目標，本卡提供讓目標落地的案例骨架。</td>
      </tr>
      <tr>
          <td><a href="../teaching-completeness-by-learner-journey/">#131 教材完整性要用讀者旅程驗證</a></td>
          <td>讀者旅程回答「怎麼讀」，貫穿式案例回答「沿著什麼服務情境練」。</td>
      </tr>
  </tbody>
</table>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>模組章節很多，但讀者不知道它們怎麼串成一個服務</td>
          <td>補貫穿式案例</td>
      </tr>
      <tr>
          <td>每篇文章都用不同業務情境，跨章記憶成本高</td>
          <td>收斂到 1 條主案例 + 少量變體</td>
      </tr>
      <tr>
          <td>案例庫豐富但主文章仍像概念清單</td>
          <td>把案例轉成可重播 episode</td>
      </tr>
      <tr>
          <td>Vendor / migration 內容比服務主線更顯眼</td>
          <td>用貫穿案例重新定義進階專題入口</td>
      </tr>
      <tr>
          <td>跨模組 link 多，但沒有共同 user journey</td>
          <td>補 episode map 與主線導讀</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：服務型教材要有貫穿式案例。能力分類讓作者整理內容，讀者旅程讓讀者知道怎麼讀，貫穿式案例讓讀者看到多個能力如何在同一個 production service 中交接與演進。</p>
]]></content:encoded></item><item><title>服務頁教材合約</title><link>https://tarrragon.github.io/blog/report/service-page-teaching-contract/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/service-page-teaching-contract/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>服務頁教材合約的責任是把「某個服務是什麼」寫成「讀者能學會什麼」。服務頁可以討論 PostgreSQL、SQLite、MongoDB、Redis、Kafka、Kubernetes、Okta 或 k6，但文章目標應是教讀者理解該服務承擔的系統責任、服務對象、操作語意、失敗訊號與替代邊界。&lt;/p>
&lt;p>服務頁教材合約把 vendor profile 升級成可教學的單篇文章。Vendor profile 描述功能、價格、適用場景與競品；服務頁教材還要讓讀者取得一個可遷移的心智模型，讀完後能把同一套判讀方式帶到相鄰服務。&lt;/p>
&lt;p>這份合約約束的是教學功能，不約束章節模板。Go 目錄提供的是討論細節、漸進教學、操作判讀與邊界意識的成熟度參照；Backend 服務頁要達到同等教學深度，但 SQLite、MongoDB、PostgreSQL、Redis、Kafka 或 Okta 的章節順序可以完全不同。&lt;/p>
&lt;h2 id="warp-分析摘要">WARP 分析摘要&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>Anchor&lt;/td>
 &lt;td>這次決策錨點從「服務清單是否完整」上移到「Backend 服務頁是否已達教材層級」。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Step 0&lt;/td>
 &lt;td>現有資料足以判斷：Backend vendor index 已完整，但服務頁正文成熟度不均；Go 目錄提供單篇教材成熟度參照。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Widen&lt;/td>
 &lt;td>選項有三種：統一章節模板、完全自由撰寫、定義教學功能合約。第三種能保護教學深度，也能保留服務差異。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reality Test&lt;/td>
 &lt;td>抽樣 Redis、Kafka、Kubernetes、Okta 接近成熟教材；PostgreSQL、SQLite、MongoDB、k6 需要依服務對象重設教學路線。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Prepare&lt;/td>
 &lt;td>若缺少合約就批量補正文，服務頁容易回到產品介紹、選型摘要或容量分析，教學完整度會持續漂移。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>反向驗證：章節統一會傷害服務頁。Go 目錄的價值是提供成熟教材的功能檢查，Backend 服務頁仍依自己的服務責任、讀者對象、案例壓力與操作比例安排標題。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>Backend 已完成總體教學設計、checkout episode map、vendor index audit 與各分類服務順序同步。下一步評估時，讀者提出更高標準：每個服務的探討內容與教學量級，應接近一篇成熟技術教材，讓選型摘要與 vendor backlog 成為教材材料。&lt;/p>
&lt;p>這個標準指向教學深度，而不是統一章節。SQLite 服務的讀者可能在意 embedded state、local-first、測試資料與低操作成本；MongoDB 服務的讀者可能在意 document shape、schema governance、index 與 transaction boundary。兩篇都要達到成熟教材深度，但學習路線應由服務對象決定。&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;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>索引完成&lt;/td>
 &lt;td>服務存在於 &lt;code>vendors/_index.md&lt;/code>，有類型與撰寫批次&lt;/td>
 &lt;td>只證明有入口，尚未形成教材&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>大綱完成&lt;/td>
 &lt;td>服務頁有定位、目標、操作、進階、排錯、案例與路由骨架&lt;/td>
 &lt;td>可以開寫，但仍需檢查段落深度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>教材完成&lt;/td>
 &lt;td>每段能教讀者判讀服務責任、操作訊號、替代邊界與失敗模式&lt;/td>
 &lt;td>可作為長期教材單篇交付&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>服務頁若只停在第一層，讀者會看到很多服務名稱；若能到第三層，讀者會理解服務能力如何在 production system 中承擔責任。&lt;/p>
&lt;h2 id="服務頁教材功能合約">服務頁教材功能合約&lt;/h2>
&lt;h3 id="教學功能先於章節格式">教學功能先於章節格式&lt;/h3>
&lt;p>服務頁教材合約約束的是功能而不是格式。成熟服務頁要具備學習目標、核心概念、操作形狀、判讀訊號、替代邊界、案例回寫與下一步路由；這些功能可以出現在不同標題、不同順序與不同敘事密度中。&lt;/p>
&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>可以是服務定位、服務對象、資料形狀、流量形狀或控制面責任&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>操作形狀&lt;/td>
 &lt;td>可以是 CLI / API、schema 設計、工作流、平台操作或治理流程&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>判讀訊號&lt;/td>
 &lt;td>可以是 metrics、logs、query、事件、audit trail、cost signal 或人工流程訊號&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代邊界&lt;/td>
 &lt;td>可以是同類服務比較、相鄰分類路由、或規模 / 組織能力分界&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>案例回寫&lt;/td>
 &lt;td>可以是公開案例、反例、規模對照或 checkout episode&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>章節名稱要服務該服務的學習路線。SQLite 可以先談「正式狀態能否在單機成立」，MongoDB 可以先談「document shape 與 schema governance」，PostgreSQL 可以先談「SQL baseline 與 transaction」，這三篇不應被壓成同一套段落順序。&lt;/p>
&lt;h3 id="學習目標要先於服務介紹">學習目標要先於服務介紹&lt;/h3>
&lt;p>服務頁開頭要先說讀者讀完後能做什麼判斷。產品名稱與服務定位很重要，但學習目標決定文章是否是教材。&lt;/p>
&lt;p>成熟服務頁至少要回答：&lt;/p>
&lt;ul>
&lt;li>讀者能辨識這個服務承擔哪類 backend 責任。&lt;/li>
&lt;li>讀者能知道這個服務解哪種壓力，承擔哪種操作成本。&lt;/li>
&lt;li>讀者能用訊號判斷服務健康、退化或失配。&lt;/li>
&lt;li>讀者能知道何時改走相鄰服務。&lt;/li>
&lt;/ul>
&lt;h3 id="概念段要建立服務專屬心智模型">概念段要建立服務專屬心智模型&lt;/h3>
&lt;p>概念段的責任是建立讀者能帶走的模型。Redis 頁不只教 Redis command，還要教「可重建副本如何保護 origin」；Kafka 頁不只教 topic，還要教「event log、consumer progress 與 replay window」；Kubernetes 頁不只教 YAML，還要教「workload lifecycle、readiness、traffic 與 rollback contract」。&lt;/p>
&lt;p>服務專屬心智模型要貼近服務對象。SQLite 面向小型正式狀態、local data、edge 與測試資料；MongoDB 面向 document model、聚合查詢、索引與 schema governance；PostgreSQL 面向 SQL baseline、transaction、query boundary 與 schema evolution。三者同屬 database，教學路線仍可完全不同。&lt;/p>
&lt;h3 id="操作段要服務判讀">操作段要服務判讀&lt;/h3>
&lt;p>操作段的責任是讓讀者理解日常決策形狀。指令、設定、console 或 CLI 範例可以存在，但每個例子都要回到訊號、風險或下一步判斷。&lt;/p>
&lt;p>較穩定的操作段功能包含：&lt;/p>
&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>說明服務平常怎麼被維護、監控與調整&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>失敗快速判讀&lt;/td>
 &lt;td>說明異常發生時先看哪些訊號&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Evidence route&lt;/td>
 &lt;td>說明哪些結果要交給 observability / gate&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="替代邊界要讓服務回到能力地圖">替代邊界要讓服務回到能力地圖&lt;/h3>
&lt;p>服務頁要寫「何時改走其他服務」。這段把服務放回能力地圖：正式狀態回 database、可重建副本回 cache、durable replay 回 queue、traffic lifecycle 回 deployment、release evidence 回 reliability、identity control 回 security、協作交接回 incident。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p>服務頁教材合約的責任是把「某個服務是什麼」寫成「讀者能學會什麼」。服務頁可以討論 PostgreSQL、SQLite、MongoDB、Redis、Kafka、Kubernetes、Okta 或 k6，但文章目標應是教讀者理解該服務承擔的系統責任、服務對象、操作語意、失敗訊號與替代邊界。</p>
<p>服務頁教材合約把 vendor profile 升級成可教學的單篇文章。Vendor profile 描述功能、價格、適用場景與競品；服務頁教材還要讓讀者取得一個可遷移的心智模型，讀完後能把同一套判讀方式帶到相鄰服務。</p>
<p>這份合約約束的是教學功能，不約束章節模板。Go 目錄提供的是討論細節、漸進教學、操作判讀與邊界意識的成熟度參照；Backend 服務頁要達到同等教學深度，但 SQLite、MongoDB、PostgreSQL、Redis、Kafka 或 Okta 的章節順序可以完全不同。</p>
<h2 id="warp-分析摘要">WARP 分析摘要</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anchor</td>
          <td>這次決策錨點從「服務清單是否完整」上移到「Backend 服務頁是否已達教材層級」。</td>
      </tr>
      <tr>
          <td>Step 0</td>
          <td>現有資料足以判斷：Backend vendor index 已完整，但服務頁正文成熟度不均；Go 目錄提供單篇教材成熟度參照。</td>
      </tr>
      <tr>
          <td>Widen</td>
          <td>選項有三種：統一章節模板、完全自由撰寫、定義教學功能合約。第三種能保護教學深度，也能保留服務差異。</td>
      </tr>
      <tr>
          <td>Reality Test</td>
          <td>抽樣 Redis、Kafka、Kubernetes、Okta 接近成熟教材；PostgreSQL、SQLite、MongoDB、k6 需要依服務對象重設教學路線。</td>
      </tr>
      <tr>
          <td>Prepare</td>
          <td>若缺少合約就批量補正文，服務頁容易回到產品介紹、選型摘要或容量分析，教學完整度會持續漂移。</td>
      </tr>
  </tbody>
</table>
<p>反向驗證：章節統一會傷害服務頁。Go 目錄的價值是提供成熟教材的功能檢查，Backend 服務頁仍依自己的服務責任、讀者對象、案例壓力與操作比例安排標題。</p>
<h2 id="情境">情境</h2>
<p>Backend 已完成總體教學設計、checkout episode map、vendor index audit 與各分類服務順序同步。下一步評估時，讀者提出更高標準：每個服務的探討內容與教學量級，應接近一篇成熟技術教材，讓選型摘要與 vendor backlog 成為教材材料。</p>
<p>這個標準指向教學深度，而不是統一章節。SQLite 服務的讀者可能在意 embedded state、local-first、測試資料與低操作成本；MongoDB 服務的讀者可能在意 document shape、schema governance、index 與 transaction boundary。兩篇都要達到成熟教材深度，但學習路線應由服務對象決定。</p>
<p>這個提醒揭露了三種不同完成度：</p>
<table>
  <thead>
      <tr>
          <th>完成度</th>
          <th>訊號</th>
          <th>風險</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>索引完成</td>
          <td>服務存在於 <code>vendors/_index.md</code>，有類型與撰寫批次</td>
          <td>只證明有入口，尚未形成教材</td>
      </tr>
      <tr>
          <td>大綱完成</td>
          <td>服務頁有定位、目標、操作、進階、排錯、案例與路由骨架</td>
          <td>可以開寫，但仍需檢查段落深度</td>
      </tr>
      <tr>
          <td>教材完成</td>
          <td>每段能教讀者判讀服務責任、操作訊號、替代邊界與失敗模式</td>
          <td>可作為長期教材單篇交付</td>
      </tr>
  </tbody>
</table>
<p>服務頁若只停在第一層，讀者會看到很多服務名稱；若能到第三層，讀者會理解服務能力如何在 production system 中承擔責任。</p>
<h2 id="服務頁教材功能合約">服務頁教材功能合約</h2>
<h3 id="教學功能先於章節格式">教學功能先於章節格式</h3>
<p>服務頁教材合約約束的是功能而不是格式。成熟服務頁要具備學習目標、核心概念、操作形狀、判讀訊號、替代邊界、案例回寫與下一步路由；這些功能可以出現在不同標題、不同順序與不同敘事密度中。</p>
<table>
  <thead>
      <tr>
          <th>教學功能</th>
          <th>可變形態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>學習目標</td>
          <td>可以是「本章目標」、開場學習成果、或讀法段</td>
      </tr>
      <tr>
          <td>核心概念</td>
          <td>可以是服務定位、服務對象、資料形狀、流量形狀或控制面責任</td>
      </tr>
      <tr>
          <td>操作形狀</td>
          <td>可以是 CLI / API、schema 設計、工作流、平台操作或治理流程</td>
      </tr>
      <tr>
          <td>判讀訊號</td>
          <td>可以是 metrics、logs、query、事件、audit trail、cost signal 或人工流程訊號</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>可以是同類服務比較、相鄰分類路由、或規模 / 組織能力分界</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>可以是公開案例、反例、規模對照或 checkout episode</td>
      </tr>
  </tbody>
</table>
<p>章節名稱要服務該服務的學習路線。SQLite 可以先談「正式狀態能否在單機成立」，MongoDB 可以先談「document shape 與 schema governance」，PostgreSQL 可以先談「SQL baseline 與 transaction」，這三篇不應被壓成同一套段落順序。</p>
<h3 id="學習目標要先於服務介紹">學習目標要先於服務介紹</h3>
<p>服務頁開頭要先說讀者讀完後能做什麼判斷。產品名稱與服務定位很重要，但學習目標決定文章是否是教材。</p>
<p>成熟服務頁至少要回答：</p>
<ul>
<li>讀者能辨識這個服務承擔哪類 backend 責任。</li>
<li>讀者能知道這個服務解哪種壓力，承擔哪種操作成本。</li>
<li>讀者能用訊號判斷服務健康、退化或失配。</li>
<li>讀者能知道何時改走相鄰服務。</li>
</ul>
<h3 id="概念段要建立服務專屬心智模型">概念段要建立服務專屬心智模型</h3>
<p>概念段的責任是建立讀者能帶走的模型。Redis 頁不只教 Redis command，還要教「可重建副本如何保護 origin」；Kafka 頁不只教 topic，還要教「event log、consumer progress 與 replay window」；Kubernetes 頁不只教 YAML，還要教「workload lifecycle、readiness、traffic 與 rollback contract」。</p>
<p>服務專屬心智模型要貼近服務對象。SQLite 面向小型正式狀態、local data、edge 與測試資料；MongoDB 面向 document model、聚合查詢、索引與 schema governance；PostgreSQL 面向 SQL baseline、transaction、query boundary 與 schema evolution。三者同屬 database，教學路線仍可完全不同。</p>
<h3 id="操作段要服務判讀">操作段要服務判讀</h3>
<p>操作段的責任是讓讀者理解日常決策形狀。指令、設定、console 或 CLI 範例可以存在，但每個例子都要回到訊號、風險或下一步判斷。</p>
<p>較穩定的操作段功能包含：</p>
<table>
  <thead>
      <tr>
          <th>操作面</th>
          <th>教學責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>最短判讀路徑</td>
          <td>讓讀者快速判斷是否該考慮這個服務</td>
      </tr>
      <tr>
          <td>日常操作形狀</td>
          <td>說明服務平常怎麼被維護、監控與調整</td>
      </tr>
      <tr>
          <td>失敗快速判讀</td>
          <td>說明異常發生時先看哪些訊號</td>
      </tr>
      <tr>
          <td>Evidence route</td>
          <td>說明哪些結果要交給 observability / gate</td>
      </tr>
  </tbody>
</table>
<h3 id="替代邊界要讓服務回到能力地圖">替代邊界要讓服務回到能力地圖</h3>
<p>服務頁要寫「何時改走其他服務」。這段把服務放回能力地圖：正式狀態回 database、可重建副本回 cache、durable replay 回 queue、traffic lifecycle 回 deployment、release evidence 回 reliability、identity control 回 security、協作交接回 incident。</p>
<h3 id="案例回寫要提供情境壓力">案例回寫要提供情境壓力</h3>
<p>案例回寫的責任是讓服務頁有真實壓力來源。案例要提供流量形狀、資料形狀、組織能力、失敗代價或回退路徑；案例只停在「某公司使用 X」時，對教材幫助有限。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="服務頁會變成產品百科">服務頁會變成產品百科</h3>
<p>產品百科容易累積功能、版本、價格與競品資訊，讀者可以查到很多答案，但仍難以建立系統責任模型。服務頁教材合約要求每個資訊都回到教學責任。</p>
<h3 id="統一模板會抹平服務對象">統一模板會抹平服務對象</h3>
<p>統一模板會把同分類服務壓成相同讀法，讓服務對象消失。SQLite、MongoDB、DynamoDB、PostgreSQL 都在 database 分類，但它們回答的讀者問題不同；用同一套章節順序處理，會讓 embedded state、document model、access pattern 與 SQL transaction 的差異變成表格欄位，而不是學習路線。</p>
<h3 id="內容會被選型語氣帶走">內容會被選型語氣帶走</h3>
<p>選型語氣會問「什麼情境選 X」，但教材還要問「X 在系統中承擔什麼責任」。只寫選型，讀者能做局部選擇；補上教材合約，讀者能理解整個 backend 能力地圖。</p>
<h3 id="大量服務頁會產生完成錯覺">大量服務頁會產生完成錯覺</h3>
<p>服務頁數量增加會帶來覆蓋感，但覆蓋不等於完成。125 個服務頁如果只有入口與摘要，仍是素材庫；每篇具備學習目標、操作判讀與案例回寫後，才是教材。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<table>
  <thead>
      <tr>
          <th>原則</th>
          <th>關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="../teaching-goal-before-decision-frame/">#130 教材目標先於決策框架</a></td>
          <td>#130 定義教材的上位目標；本卡把上位目標落到「單篇服務頁」的教學功能合約。</td>
      </tr>
      <tr>
          <td><a href="../teaching-completeness-by-learner-journey/">#131 教材完整性要用讀者旅程驗證</a></td>
          <td>#131 用讀者旅程檢查系列完整性；本卡用單篇教材合約檢查服務頁是否能獨立教會一個服務能力。</td>
      </tr>
      <tr>
          <td><a href="../throughline-case-as-teaching-spine/">#132 貫穿式案例是服務教材的教學骨架</a></td>
          <td>#132 提供跨模組案例主線；本卡要求每篇服務頁能回寫至少一段 case route 或明確標示案例缺口。</td>
      </tr>
      <tr>
          <td><a href="../metadata-surface-in-writing-review/">#97 Metadata surface 要納入寫作 review 範圍</a></td>
          <td>服務頁教材合約也要檢查 title、description、heading、index entry 與下一步路由，避免正文與入口語意不一致。</td>
      </tr>
      <tr>
          <td><a href="../writing-review-multi-axis-completeness/">#126 寫作 review 是多軸完整性</a></td>
          <td>服務頁 review 要同時看教材目標、服務責任、操作訊號、案例回寫、metadata surface 與跨模組路由。</td>
      </tr>
      <tr>
          <td><a href="../cadence-homogenization-in-batch-writing/">#122 Cadence 同質化是模板的隱形維度</a></td>
          <td>本卡補服務頁的結構層防護：教學功能要完整，章節順序要依服務對象與責任形狀調整，避免批量服務頁同質化。</td>
      </tr>
  </tbody>
</table>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務頁只有定位、適用場景與競品比較</td>
          <td>補本章目標、操作形狀、排錯判讀與案例回寫</td>
      </tr>
      <tr>
          <td>服務頁內容很豐富，但缺少清楚學習路線</td>
          <td>依服務對象重排 heading</td>
      </tr>
      <tr>
          <td>排錯段只有常見錯誤列表</td>
          <td>改成「訊號 → 判讀 → 下一步路由」</td>
      </tr>
      <tr>
          <td>案例段只列公司名稱</td>
          <td>補案例提供的壓力、失敗代價或回退條件</td>
      </tr>
      <tr>
          <td>服務頁讀完仍不知道下一步讀哪裡</td>
          <td>補上游概念、平行服務、下游 artifact 與 case route</td>
      </tr>
      <tr>
          <td>批量服務頁都套同一標題但失去分類語言</td>
          <td>回到分類責任調整段落順序</td>
      </tr>
      <tr>
          <td>同分類服務頁看起來像同一篇文章換名詞</td>
          <td>重新辨識每個服務的讀者對象、服務責任與操作語境</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：服務頁完成的標準是讀者能透過單篇文章學會一個服務能力。成熟服務頁要同時提供學習目標、概念模型、操作判讀、替代邊界、案例回寫與下一步路由。</p>
]]></content:encoded></item><item><title>Sibling Coverage Asymmetry Blindspot：Priority 評估漏掉的「對稱性維度」</title><link>https://tarrragon.github.io/blog/report/sibling-coverage-asymmetry-blindspot-in-priority/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/sibling-coverage-asymmetry-blindspot-in-priority/</guid><description>&lt;h2 id="核心priority-評估的-sibling-對稱性盲點">核心：Priority 評估的 sibling 對稱性盲點&lt;/h2>
&lt;p>當批量 A 跟批量 B 是 &lt;em>sibling&lt;/em>（同類 vendor / 同類角色 / 應有對等 coverage）、但 A 後寫卻超過 B、心智模型容易 collapse 到「A 是 reference template / B 是 baseline」的角色分配、忽略 &lt;em>B 才該 ≥ A coverage 的對稱性 priority&lt;/em>。Priority 列表往往跳過 B、列其他「新領域擴張」選項。&lt;/p>
&lt;p>問題不在 &lt;em>推某個 vendor&lt;/em>、在 &lt;em>priority 評估維度漏掉 sibling symmetry&lt;/em>。&lt;/p>
&lt;h2 id="casemysql-18-篇-vs-pg-11-篇後的-priority-列表">Case：MySQL 18 篇 vs PG 11 篇後的 priority 列表&lt;/h2>
&lt;p>時間線：&lt;/p>
&lt;ol>
&lt;li>PG 11 篇先寫完（autovacuum-tuning / declarative-partitioning / patroni-ha / pgbouncer-config / pitr-wal-archiving / logical-replication-debezium + 5 migration playbook）&lt;/li>
&lt;li>MySQL 從 0 開始、user 要求「第一個示範服務、儘量都寫」、寫到 17 篇 deep article + migration playbook + 既有 migrate-to-postgresql = 18 篇 / 5715 行&lt;/li>
&lt;li>推薦下一步 priority 時、列「DynamoDB / Aurora / SQLite / MongoDB / CockroachDB / Spanner / Cosmos DB」、PG &lt;strong>不在列表&lt;/strong>&lt;/li>
&lt;li>User 問：「為什麼這裡列的選項沒有 PG？我們做完了嗎？」&lt;/li>
&lt;/ol>
&lt;p>實際盤點：&lt;/p>
&lt;ul>
&lt;li>PG 11 篇 vs MySQL 18 篇、PG 缺 &lt;strong>7 個 MySQL sibling deep article&lt;/strong>（replication-topology / online-schema-change-tools / query-optimization / lock-contention / vitess-sharding 對應 Citus / group-replication 對應 BDR / modern-sql-features 反向視角）&lt;/li>
&lt;li>PG 還缺 &lt;strong>4 個 PG-only 議題&lt;/strong>（JSONB deep dive / Extension ecosystem / Full-text search / Replication slot management）&lt;/li>
&lt;/ul>
&lt;p>User 直覺 catch 到 &lt;em>coverage asymmetry&lt;/em>、但我 priority 列表沒提供這個視角。&lt;/p>
&lt;h2 id="機制為什麼會忽略">機制：為什麼會忽略&lt;/h2>
&lt;p>至少 5 個 priority bias 共同貢獻：&lt;/p>
&lt;h3 id="1-先存在就-mature隱性假設">1. 「先存在就 mature」隱性假設&lt;/h3>
&lt;p>PG 11 篇先存在 → 直覺映射「PG 已 mature」。沒做 &lt;em>cross-sectional 對比&lt;/em>：&lt;/p>
&lt;ul>
&lt;li>PG 11 篇 vs MySQL 18 篇、絕對量比較&lt;/li>
&lt;li>議題覆蓋對應：MySQL 有哪些 deep article、PG 對應的是否都有&lt;/li>
&lt;/ul>
&lt;p>「11 篇」這個絕對數字 &lt;em>看起來合理&lt;/em>、但跟 MySQL 18 篇對比後 &lt;em>結構性不足&lt;/em>。心智模型把「合理」當成「mature」、跳過了相對性 audit。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心priority-評估的-sibling-對稱性盲點">核心：Priority 評估的 sibling 對稱性盲點</h2>
<p>當批量 A 跟批量 B 是 <em>sibling</em>（同類 vendor / 同類角色 / 應有對等 coverage）、但 A 後寫卻超過 B、心智模型容易 collapse 到「A 是 reference template / B 是 baseline」的角色分配、忽略 <em>B 才該 ≥ A coverage 的對稱性 priority</em>。Priority 列表往往跳過 B、列其他「新領域擴張」選項。</p>
<p>問題不在 <em>推某個 vendor</em>、在 <em>priority 評估維度漏掉 sibling symmetry</em>。</p>
<h2 id="casemysql-18-篇-vs-pg-11-篇後的-priority-列表">Case：MySQL 18 篇 vs PG 11 篇後的 priority 列表</h2>
<p>時間線：</p>
<ol>
<li>PG 11 篇先寫完（autovacuum-tuning / declarative-partitioning / patroni-ha / pgbouncer-config / pitr-wal-archiving / logical-replication-debezium + 5 migration playbook）</li>
<li>MySQL 從 0 開始、user 要求「第一個示範服務、儘量都寫」、寫到 17 篇 deep article + migration playbook + 既有 migrate-to-postgresql = 18 篇 / 5715 行</li>
<li>推薦下一步 priority 時、列「DynamoDB / Aurora / SQLite / MongoDB / CockroachDB / Spanner / Cosmos DB」、PG <strong>不在列表</strong></li>
<li>User 問：「為什麼這裡列的選項沒有 PG？我們做完了嗎？」</li>
</ol>
<p>實際盤點：</p>
<ul>
<li>PG 11 篇 vs MySQL 18 篇、PG 缺 <strong>7 個 MySQL sibling deep article</strong>（replication-topology / online-schema-change-tools / query-optimization / lock-contention / vitess-sharding 對應 Citus / group-replication 對應 BDR / modern-sql-features 反向視角）</li>
<li>PG 還缺 <strong>4 個 PG-only 議題</strong>（JSONB deep dive / Extension ecosystem / Full-text search / Replication slot management）</li>
</ul>
<p>User 直覺 catch 到 <em>coverage asymmetry</em>、但我 priority 列表沒提供這個視角。</p>
<h2 id="機制為什麼會忽略">機制：為什麼會忽略</h2>
<p>至少 5 個 priority bias 共同貢獻：</p>
<h3 id="1-先存在就-mature隱性假設">1. 「先存在就 mature」隱性假設</h3>
<p>PG 11 篇先存在 → 直覺映射「PG 已 mature」。沒做 <em>cross-sectional 對比</em>：</p>
<ul>
<li>PG 11 篇 vs MySQL 18 篇、絕對量比較</li>
<li>議題覆蓋對應：MySQL 有哪些 deep article、PG 對應的是否都有</li>
</ul>
<p>「11 篇」這個絕對數字 <em>看起來合理</em>、但跟 MySQL 18 篇對比後 <em>結構性不足</em>。心智模型把「合理」當成「mature」、跳過了相對性 audit。</p>
<h3 id="2-新領域擴張優於既有領域對齊的-progress-bias">2. 「新領域擴張」優於「既有領域對齊」的 progress bias</h3>
<p>Priority 列表時、DynamoDB / Aurora / SQLite 等 vendor <em>看起來進度感強</em> — 從 0 推到 N、新領域擴張。PG 補齊看起來 <em>重複勞動</em> — 從 11 推到 18、改善舊領域。</p>
<p>實際上：</p>
<ul>
<li>新領域擴張 <em>增加 surface area</em>、但不改善既有結構</li>
<li>既有領域對齊 <em>修補 baseline</em>、是 reference template 成立的前提</li>
</ul>
<p>當 baseline 跟 reference template 不對稱時、後者作為 <em>示範服務</em> 的價值打折扣 — 「MySQL 怎麼寫 vendor article」沒法 fully 套到 PG、因為 PG 本身不對稱。</p>
<h3 id="3-priority-評估維度漏-sibling-symmetry">3. Priority 評估維度漏 sibling symmetry</h3>
<p>我用的 priority 評估維度：</p>
<ul>
<li>T1 vs T2 vendor 分類</li>
<li>領域重要度</li>
<li>已有量</li>
<li>新領域 vs 既有領域</li>
</ul>
<p><strong>漏掉的維度</strong>：</p>
<ul>
<li>Sibling vendor 對稱性（A 跟 B 同類、A 寫完後 B coverage 是否對齊）</li>
<li>Reference template 跟 baseline 的關係（後寫的 reference template 應 ≤ baseline）</li>
</ul>
<p>「Sibling 對稱性」這個維度不在預設 priority 評估清單、就被自動忽略。</p>
<h3 id="4-reference-template-vs-baseline-角色混淆">4. Reference template vs Baseline 角色混淆</h3>
<p>寫 vendor article 時、<em>哪個是 baseline、哪個是 reference template</em> 的心智模型可能反轉：</p>
<ul>
<li>直覺：「先寫的 = baseline、後寫的 = reference / extension」</li>
<li>真實：「baseline 應 ≥ reference template coverage、不該倒過來」</li>
</ul>
<p>MySQL 18 篇是 <em>user-driven 要求</em> — user 明說「第一個示範服務、儘量都寫」。所以 MySQL 寫得多不是錯。但 <em>PG 沒對齊到同水準</em> 才是漏掉的紀律。</p>
<p>當 MySQL 寫到 reference template 規模、PG 還在 11 篇、心智模型容易 collapse 到「MySQL 是新 baseline、PG 是 legacy partial」、其實是 <em>baseline 應該升級到 reference template 水準</em>。</p>
<h3 id="5-sequential-vs-cross-sectional-coverage-評估">5. Sequential vs cross-sectional coverage 評估</h3>
<p>寫作過程是 sequential —寫 MySQL 17 篇是一段時間、寫完看 git diff stat 確認進度、然後 priority 下一步。<strong>Coverage 評估是 point-in-time 的</strong>：</p>
<ul>
<li>Point-in-time（sequential）：「我這 batch 寫了多少」</li>
<li>Cross-sectional（symmetric）：「我寫的這個跟 sibling 是否對齊」</li>
</ul>
<p>寫 MySQL 第 17 篇時 self-cross-check：「PG 對應有沒有？」是 cross-sectional 行為、不是預設行為。</p>
<p>Priority 列表階段沒回頭跑 cross-sectional audit、就把 PG 排除。</p>
<h2 id="修法">修法</h2>
<h3 id="1-priority-candidate-list-必須跑-sibling-symmetry-audit">1. Priority candidate list 必須跑 sibling symmetry audit</h3>
<p>提 priority 列表時、強制 cross-check：</p>
<ul>
<li>列出該批量影響的 <em>sibling vendor / sibling role</em></li>
<li>對比每個 sibling 的 coverage（篇數 + 議題覆蓋 mapping）</li>
<li>若有 asymmetry、把「補齊 sibling」加進 priority 列表 <em>跟新領域並列</em></li>
</ul>
<h3 id="2-vendors_index內容覆蓋進度表加對稱性視角">2. Vendors/_index「內容覆蓋進度」表加對稱性視角</h3>
<p>當前內容覆蓋進度只列「已寫 / 未寫」、不列 <em>sibling 之間相對進度</em>。改善：</p>
<ul>
<li>加 <em>「跟 sibling 對應」欄</em>：每個 article 標 sibling vendor 是否有對應</li>
<li>加 <em>總計篇數 + sibling 對比</em> 欄：直觀看到 asymmetry</li>
</ul>
<h3 id="3-先-mature-baseline再擴張紀律">3. 「先 mature baseline、再擴張」紀律</h3>
<p>寫 vendor batch 時、紀律：</p>
<ul>
<li>確認 <em>baseline vendor 對齊到 reference template 水準</em>、再推下一個 vendor</li>
<li>例外：user 明確要求先擴張某 vendor 時、加註 <em>baseline 待對齊</em> 為 known limitation</li>
</ul>
<h3 id="4-audit-dimension-list-加-coverage-symmetry">4. Audit dimension list 加 <em>Coverage symmetry</em></h3>
<p>跟 <a href="../data-topology-as-audit-dimension/">Data Topology as Audit Dimension</a> 同型 —audit 維度可擴張。把 <em>sibling coverage symmetry</em> 加進 priority audit 維度：</p>
<ul>
<li>既有維度：T1 / 領域 / 已有量 / 新 vs 既有</li>
<li>新增維度：<strong>sibling 對稱性</strong>（A 跟 B 同類時、coverage 對齊度）</li>
</ul>
<h2 id="跟既有原則的關係">跟既有原則的關係</h2>
<ul>
<li><a href="../data-topology-as-audit-dimension/">Data Topology as Audit Dimension</a>：本卡是 <em>priority 評估維度漏一個</em>、同型但不同 axis</li>
<li><a href="../collapse-is-implicit-default/">Collapse is Implicit Default</a>：priority 評估 collapse 到「新領域擴張」維度、是其變體</li>
<li><a href="../multi-pass-review-frame-granularity-blindspot/">Multi-Pass Review Frame Granularity Blindspot</a>：multi-pass review 漏 catch 的同型、但本卡是 <em>priority assessment 漏 catch</em>、不是 <em>review 漏 catch</em></li>
</ul>
<h2 id="反向驗證">反向驗證</h2>
<p>不該誤用本卡：</p>
<ul>
<li><em>Sibling vendor 對稱性</em> 不等於 <em>每個 vendor 都該寫到同篇數</em>。MySQL 18 篇對 PG 合理（兩大 SQL OLTP baseline），但 SQLite / DynamoDB / Spanner 各 18 篇不合理（領域窄 / niche audience）</li>
<li>對稱性 audit 是 <em>對 baseline / reference template 雙方適用</em>、不是擴張到所有 sibling</li>
<li>真正 niche vendor（如 Spanner / Cosmos DB 對小團隊）可以 <em>明確 backlog 標記 minimum coverage</em>、不必對齊 baseline</li>
</ul>
<h2 id="觸發再評估">觸發再評估</h2>
<p>未來累積到以下情境、本卡應重新 review：</p>
<ul>
<li>寫第二個 baseline pair（02 cache Redis vs Memcached / 03 queue Kafka vs NATS 等）時、是否同樣踩 asymmetry blindspot</li>
<li>多 reviewer audit 是否能 catch coverage asymmetry（4-reviewer 沒設計這軸、之後 batch 可加 reviewer E <em>coverage symmetry</em>）</li>
<li>Sibling 對稱性 audit 進工具化（vendors/_index 自動產 asymmetry warning）後是否解決</li>
</ul>
]]></content:encoded></item><item><title>Sibling Vendor Cross-Link 雙向性 Audit：寫 Vendor Batch 結束必跑</title><link>https://tarrragon.github.io/blog/report/sibling-vendor-cross-link-bidirectionality-audit/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/sibling-vendor-cross-link-bidirectionality-audit/</guid><description>&lt;h2 id="核心sibling-vendor-batch-容易單向-cross-link">核心：Sibling vendor batch 容易單向 cross-link&lt;/h2>
&lt;p>當寫 sibling vendor batch（A 跟 B 是同類角色的 vendor）、cross-link 容易單向：&lt;/p>
&lt;ul>
&lt;li>A 是後寫 batch、提 B 多次（「跟 PG sibling 對比」「PG 的 X 行為跟 MySQL 不同」）&lt;/li>
&lt;li>B 是先寫 batch、預設沒提 A（寫的時候 A 還不存在）&lt;/li>
&lt;li>結果：A → B 有 9 條 link、B → A 有 0 條 link&lt;/li>
&lt;/ul>
&lt;p>讀者從 B 進入、看不到 A 的存在；只有從 A 進入才知道兩者並列。&lt;/p>
&lt;p>問題不在 &lt;em>單向 link 本身錯&lt;/em>、在 &lt;em>vendor batch 結束沒跑 bidirectional audit&lt;/em>、就以為「cross-link 已建立」。&lt;/p>
&lt;h2 id="casemysql--postgresql-cross-link-asymmetry">Case：MySQL ↔ PostgreSQL cross-link asymmetry&lt;/h2>
&lt;p>4-reviewer audit（Reviewer B）finding：&lt;/p>
&lt;ul>
&lt;li>MySQL 18 篇對 PG sibling 的 cross-link：9 條（vs PostgreSQL 對比段 / 連到 PG vendor page / 連到 PG sibling article）&lt;/li>
&lt;li>PG 11 篇對 MySQL 的 cross-link：0 條&lt;/li>
&lt;/ul>
&lt;p>讀者站 PG &lt;code>pgbouncer-config&lt;/code> 不會跳到 MySQL &lt;code>proxysql-config&lt;/code>；站 MySQL &lt;code>proxysql-config&lt;/code> 直接看到「跟 PG pgBouncer 對比」段。Navigation asymmetric。&lt;/p>
&lt;h2 id="機制為什麼會單向">機制：為什麼會單向&lt;/h2>
&lt;h3 id="1-寫第二個-batch-時-reference-第一個-batch-是自然行為">1. 寫第二個 batch 時 reference 第一個 batch 是自然行為&lt;/h3>
&lt;p>寫 MySQL &lt;code>replication-topology&lt;/code> 時、PG &lt;code>patroni-ha&lt;/code> 已存在、自然連去做對比。寫 PG &lt;code>patroni-ha&lt;/code> 時、MySQL &lt;code>replication-topology&lt;/code> 還不存在、不可能 link。&lt;/p>
&lt;p>這是 &lt;em>sequential 寫作的時間性結構性&lt;/em>、不是疏忽。&lt;/p>
&lt;h3 id="2-bidirectional-link-audit-不在預設寫作流程">2. Bidirectional link audit 不在預設寫作流程&lt;/h3>
&lt;p>寫完 batch B 後、預設 audit：&lt;/p>
&lt;ul>
&lt;li>lint / cards&lt;/li>
&lt;li>emoji / 裸 URL&lt;/li>
&lt;li>跨檔一致性&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>沒有&lt;/strong> &lt;em>向上回補 sibling A 的 cross-link&lt;/em> 這一步。&lt;/p>
&lt;h3 id="3-sibling-a-寫好後不會自動-trigger-a-的更新">3. Sibling A 寫好後、不會自動 trigger A 的更新&lt;/h3>
&lt;p>寫 vendor batch B 完成時、A 的內容不變、沒人 trigger「現在 sibling B 存在了、A 應該加 cross-link 回 B」。&lt;/p>
&lt;h2 id="修法bidirectional-cross-link-audit">修法：Bidirectional cross-link audit&lt;/h2>
&lt;h3 id="audit-步驟">Audit 步驟&lt;/h3>
&lt;p>寫完 vendor batch B（B 跟 sibling A 存在對應）後、跑：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. Count A → B link&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">rg -c &lt;span class="s2">&amp;#34;\]\(/path/to/B/&amp;#34;&lt;/span> content/path/to/A/*.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. Count B → A link&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">rg -c &lt;span class="s2">&amp;#34;\]\(/path/to/A/&amp;#34;&lt;/span> content/path/to/B/*.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 對比&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 若 A→B 顯著少於 B→A、補 A 端 cross-link&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="補-a-端-cross-link-的位置">補 A 端 cross-link 的位置&lt;/h3>
&lt;p>每個 A article 應該在：&lt;/p></description><content:encoded><![CDATA[<h2 id="核心sibling-vendor-batch-容易單向-cross-link">核心：Sibling vendor batch 容易單向 cross-link</h2>
<p>當寫 sibling vendor batch（A 跟 B 是同類角色的 vendor）、cross-link 容易單向：</p>
<ul>
<li>A 是後寫 batch、提 B 多次（「跟 PG sibling 對比」「PG 的 X 行為跟 MySQL 不同」）</li>
<li>B 是先寫 batch、預設沒提 A（寫的時候 A 還不存在）</li>
<li>結果：A → B 有 9 條 link、B → A 有 0 條 link</li>
</ul>
<p>讀者從 B 進入、看不到 A 的存在；只有從 A 進入才知道兩者並列。</p>
<p>問題不在 <em>單向 link 本身錯</em>、在 <em>vendor batch 結束沒跑 bidirectional audit</em>、就以為「cross-link 已建立」。</p>
<h2 id="casemysql--postgresql-cross-link-asymmetry">Case：MySQL ↔ PostgreSQL cross-link asymmetry</h2>
<p>4-reviewer audit（Reviewer B）finding：</p>
<ul>
<li>MySQL 18 篇對 PG sibling 的 cross-link：9 條（vs PostgreSQL 對比段 / 連到 PG vendor page / 連到 PG sibling article）</li>
<li>PG 11 篇對 MySQL 的 cross-link：0 條</li>
</ul>
<p>讀者站 PG <code>pgbouncer-config</code> 不會跳到 MySQL <code>proxysql-config</code>；站 MySQL <code>proxysql-config</code> 直接看到「跟 PG pgBouncer 對比」段。Navigation asymmetric。</p>
<h2 id="機制為什麼會單向">機制：為什麼會單向</h2>
<h3 id="1-寫第二個-batch-時-reference-第一個-batch-是自然行為">1. 寫第二個 batch 時 reference 第一個 batch 是自然行為</h3>
<p>寫 MySQL <code>replication-topology</code> 時、PG <code>patroni-ha</code> 已存在、自然連去做對比。寫 PG <code>patroni-ha</code> 時、MySQL <code>replication-topology</code> 還不存在、不可能 link。</p>
<p>這是 <em>sequential 寫作的時間性結構性</em>、不是疏忽。</p>
<h3 id="2-bidirectional-link-audit-不在預設寫作流程">2. Bidirectional link audit 不在預設寫作流程</h3>
<p>寫完 batch B 後、預設 audit：</p>
<ul>
<li>lint / cards</li>
<li>emoji / 裸 URL</li>
<li>跨檔一致性</li>
</ul>
<p><strong>沒有</strong> <em>向上回補 sibling A 的 cross-link</em> 這一步。</p>
<h3 id="3-sibling-a-寫好後不會自動-trigger-a-的更新">3. Sibling A 寫好後、不會自動 trigger A 的更新</h3>
<p>寫 vendor batch B 完成時、A 的內容不變、沒人 trigger「現在 sibling B 存在了、A 應該加 cross-link 回 B」。</p>
<h2 id="修法bidirectional-cross-link-audit">修法：Bidirectional cross-link audit</h2>
<h3 id="audit-步驟">Audit 步驟</h3>
<p>寫完 vendor batch B（B 跟 sibling A 存在對應）後、跑：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Count A → B link</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">rg -c <span class="s2">&#34;\]\(/path/to/B/&#34;</span> content/path/to/A/*.md
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. Count B → A link</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">rg -c <span class="s2">&#34;\]\(/path/to/A/&#34;</span> content/path/to/B/*.md
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 對比</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 若 A→B 顯著少於 B→A、補 A 端 cross-link</span></span></span></code></pre></div><h3 id="補-a-端-cross-link-的位置">補 A 端 cross-link 的位置</h3>
<p>每個 A article 應該在：</p>
<ol>
<li><strong>「相關連結」段</strong> — 列對應 sibling B article</li>
<li><strong>「跟其他 vendor 的取捨」段</strong>（若有） — 提到 sibling B 的對應</li>
<li><strong>「下一步路由」 / 「替代路徑」段</strong> — 列 B 作為 alternative</li>
</ol>
<h3 id="audit-cadence">Audit cadence</h3>
<ul>
<li>每個 sibling vendor batch 寫完、跑一次 bidirectional audit</li>
<li>不只寫完 <em>第二個</em> batch、寫完 <em>第三 / 第四個</em> 也跑（A↔B↔C 三方對稱）</li>
<li>vendors/_index 內容覆蓋進度表加 <code>link_density</code> 欄、揭露 asymmetry</li>
</ul>
<h2 id="跟既有原則的關係">跟既有原則的關係</h2>
<ul>
<li><a href="../sibling-coverage-asymmetry-blindspot-in-priority/">Sibling Coverage Asymmetry Blindspot in Priority</a>：本卡是 cross-link asymmetry、那卡是 coverage asymmetry、同型但不同 axis</li>
<li><a href="../cards-as-living-system-iteration/">Cards as Living System Iteration</a>：cross-link 維護是 living system 部分、不是 one-shot</li>
</ul>
<h2 id="反向驗證">反向驗證</h2>
<p>不該誤用：</p>
<ul>
<li><em>Sibling vendor</em> 限同類角色（PG / MySQL 都 SQL baseline）、不是任意兩個 vendor。MySQL 沒必要 link Spanner（不同類）</li>
<li>雙向不等於 <em>對稱數量</em> — A 18 篇可能有 9 條 link、B 11 篇有 6 條 link 是合理（不是 9 對 9）</li>
<li>Migration playbook 結構性單向（A → B 是遷移、不是 B → A）— 對 migration playbook 是 <em>單向結構</em>、不適用本 audit</li>
</ul>
]]></content:encoded></item><item><title>Vendor Feature 時間敏感性：Claim Verification 必跑、寫作日期必標</title><link>https://tarrragon.github.io/blog/report/vendor-feature-time-sensitivity-claim-verification/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/vendor-feature-time-sensitivity-claim-verification/</guid><description>&lt;h2 id="核心vendor-feature-limitation-claim-有時間敏感性">核心：Vendor feature limitation claim 有時間敏感性&lt;/h2>
&lt;p>寫 vendor article 時、常見以下 claim 形態：&lt;/p>
&lt;ul>
&lt;li>「Vendor X 不支援 Y」&lt;/li>
&lt;li>「Vendor X 最多 Z」&lt;/li>
&lt;li>「Vendor X 預設 W」&lt;/li>
&lt;/ul>
&lt;p>這些 claim 在寫作那刻是真的、但 vendor 持續演進。寫作後 &lt;em>N 個月&lt;/em> — 6 個月、12 個月、24 個月 — claim 可能反轉、整段 audit 邏輯 invalidates。&lt;/p>
&lt;p>問題不只是 &lt;em>claim 過時&lt;/em>、是 &lt;em>基於 claim 的整段流程被推翻&lt;/em>。Migration playbook Phase 1 audit 如果以「Vendor 不支援 X」為前提、X 後來變支援、Phase 1 整段重寫。&lt;/p>
&lt;h2 id="caseplanetscale-fk-claim-反轉">Case：PlanetScale FK claim 反轉&lt;/h2>
&lt;p>寫 migrate-to-planetscale.md 跟 migrate-vitess-to-planetscale.md 時：&lt;/p>
&lt;ul>
&lt;li>Claim：「PlanetScale 不支援 Foreign Key（Vitess 限制）」&lt;/li>
&lt;li>基於此 claim：Phase 1 audit 整段「FK audit + 全 drop FK + application enforcement 改寫」&lt;/li>
&lt;li>Phase 1 是 weeks-months 工作量、第一個 phase&lt;/li>
&lt;/ul>
&lt;p>實際狀態（4-reviewer C audit catch）：&lt;/p>
&lt;ul>
&lt;li>Vitess 18（2023 末）加 FK 支援&lt;/li>
&lt;li>PlanetScale 2024 起在合適 plan 內可啟用 FK&lt;/li>
&lt;li>「不支援」是 2022 年的事實、寫作時已過時&lt;/li>
&lt;/ul>
&lt;p>修法：整段 Phase 1 audit 從「FK audit + drop」改寫成「FK 行為驗證 + cross-shard cascade 處理」。&lt;/p>
&lt;p>這不是 &lt;em>微調文字&lt;/em>、是 &lt;em>整段 framing 重做&lt;/em>。&lt;/p>
&lt;h2 id="機制為什麼會發生">機制：為什麼會發生&lt;/h2>
&lt;h3 id="1-llm-training-cutoff-vs-vendor-changelog-速度差">1. LLM training cutoff vs vendor changelog 速度差&lt;/h3>
&lt;p>LLM training data 有 cutoff date（通常滯後 12-18 個月）。Vendor major feature release 在 cutoff 後、LLM 不知道。&lt;/p>
&lt;p>寫 vendor article 時、LLM 預設用 &lt;em>training 內的 latest fact&lt;/em> — 那個 fact 可能已過時。&lt;/p>
&lt;h3 id="2-llm-預設不標-claim-的時間性">2. LLM 預設不標 claim 的時間性&lt;/h3>
&lt;p>LLM 寫「PlanetScale 不支援 FK」、不會自動標「&lt;em>as of 2022&lt;/em>」、讀者看到 &lt;em>永久性 claim&lt;/em>。&lt;/p>
&lt;p>LLM 不會主動 verify「我寫的這個 claim 是 N 個月內仍 valid 的嗎」、除非寫作流程強制 verify step。&lt;/p>
&lt;h3 id="3-基於-claim-的整段流程是結構性-anchor">3. 基於 claim 的整段流程是「結構性 anchor」&lt;/h3>
&lt;p>Migration playbook 的 Phase 1 是 &lt;em>結構錨點&lt;/em> — 後續 Phase 2-4 都 reference Phase 1 結果。Phase 1 基於過時 claim 時、修法不只是 claim、是 &lt;em>整個 anchor 重做&lt;/em>。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心vendor-feature-limitation-claim-有時間敏感性">核心：Vendor feature limitation claim 有時間敏感性</h2>
<p>寫 vendor article 時、常見以下 claim 形態：</p>
<ul>
<li>「Vendor X 不支援 Y」</li>
<li>「Vendor X 最多 Z」</li>
<li>「Vendor X 預設 W」</li>
</ul>
<p>這些 claim 在寫作那刻是真的、但 vendor 持續演進。寫作後 <em>N 個月</em> — 6 個月、12 個月、24 個月 — claim 可能反轉、整段 audit 邏輯 invalidates。</p>
<p>問題不只是 <em>claim 過時</em>、是 <em>基於 claim 的整段流程被推翻</em>。Migration playbook Phase 1 audit 如果以「Vendor 不支援 X」為前提、X 後來變支援、Phase 1 整段重寫。</p>
<h2 id="caseplanetscale-fk-claim-反轉">Case：PlanetScale FK claim 反轉</h2>
<p>寫 migrate-to-planetscale.md 跟 migrate-vitess-to-planetscale.md 時：</p>
<ul>
<li>Claim：「PlanetScale 不支援 Foreign Key（Vitess 限制）」</li>
<li>基於此 claim：Phase 1 audit 整段「FK audit + 全 drop FK + application enforcement 改寫」</li>
<li>Phase 1 是 weeks-months 工作量、第一個 phase</li>
</ul>
<p>實際狀態（4-reviewer C audit catch）：</p>
<ul>
<li>Vitess 18（2023 末）加 FK 支援</li>
<li>PlanetScale 2024 起在合適 plan 內可啟用 FK</li>
<li>「不支援」是 2022 年的事實、寫作時已過時</li>
</ul>
<p>修法：整段 Phase 1 audit 從「FK audit + drop」改寫成「FK 行為驗證 + cross-shard cascade 處理」。</p>
<p>這不是 <em>微調文字</em>、是 <em>整段 framing 重做</em>。</p>
<h2 id="機制為什麼會發生">機制：為什麼會發生</h2>
<h3 id="1-llm-training-cutoff-vs-vendor-changelog-速度差">1. LLM training cutoff vs vendor changelog 速度差</h3>
<p>LLM training data 有 cutoff date（通常滯後 12-18 個月）。Vendor major feature release 在 cutoff 後、LLM 不知道。</p>
<p>寫 vendor article 時、LLM 預設用 <em>training 內的 latest fact</em> — 那個 fact 可能已過時。</p>
<h3 id="2-llm-預設不標-claim-的時間性">2. LLM 預設不標 claim 的時間性</h3>
<p>LLM 寫「PlanetScale 不支援 FK」、不會自動標「<em>as of 2022</em>」、讀者看到 <em>永久性 claim</em>。</p>
<p>LLM 不會主動 verify「我寫的這個 claim 是 N 個月內仍 valid 的嗎」、除非寫作流程強制 verify step。</p>
<h3 id="3-基於-claim-的整段流程是結構性-anchor">3. 基於 claim 的整段流程是「結構性 anchor」</h3>
<p>Migration playbook 的 Phase 1 是 <em>結構錨點</em> — 後續 Phase 2-4 都 reference Phase 1 結果。Phase 1 基於過時 claim 時、修法不只是 claim、是 <em>整個 anchor 重做</em>。</p>
<p>這比修 isolated fact 工作量大 10x — 是「invalidates premise」、不是「fix typo」。</p>
<h3 id="4-vendor-article-多用-永久性語氣-而非-時間性語氣">4. Vendor article 多用 <em>永久性語氣</em> 而非 <em>時間性語氣</em></h3>
<p>寫作習慣寫「PlanetScale 不支援 FK」（永久性）、不寫「PlanetScale 截至 2022 末不支援 FK」（時間性）。</p>
<p>讀者讀到的是 <em>當前永久狀態</em>、寫作者其實只能保證 <em>寫作那刻</em>。</p>
<h2 id="修法">修法</h2>
<h3 id="1-每篇-vendor-article-標-last-verified-date">1. 每篇 vendor article 標 <code>Last verified</code> date</h3>
<p>frontmatter 或開頭加：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="nt">last_verified</span><span class="p">:</span><span class="w"> </span><span class="ld">2026-05-19</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w"></span><span class="nt">verified_against</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">  </span>- <span class="l">PlanetScale docs（2026-05 access）</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">  </span>- <span class="l">Vitess 18.0 release notes</span></span></span></code></pre></div><p>讓讀者看到 <em>寫作時 verify 的 source / date</em>、不假設永久性。</p>
<h3 id="2-feature-limitation-claim-加時間註">2. Feature limitation claim 加時間註</h3>
<p>寫「Vendor X 不支援 Y」時、加 <em>as of N</em>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">PlanetScale 截至 2024 末有限支援 FK（Vitess 18+、需明確啟用）</span></span></code></pre></div><p>而非：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">PlanetScale 不支援 FK</span></span></code></pre></div><h3 id="3-claim-反轉--整段-audit-重寫不是-patch">3. Claim 反轉 → 整段 audit 重寫、不是 patch</h3>
<p>當 verify 發現 claim 已反轉（如 PlanetScale FK 從不支援變支援）、不要 <em>只改 claim 字句</em>。回頭看 <em>基於該 claim 的流程段落</em> —</p>
<ul>
<li>Migration Phase 1 audit</li>
<li>「何時不要遷」反向 recommendation</li>
<li>「跟 sibling vendor 對比」表</li>
</ul>
<p>每段都要 <em>重看是否還成立</em>、不成立的整段重寫。</p>
<h3 id="4-vendor-article-寫作前先-verify-主要-claim">4. Vendor article 寫作前先 verify 主要 claim</h3>
<p>寫作流程加 <em>verify checkpoint</em>：</p>
<ul>
<li>列出該 article 的「Vendor X 不支援 Y / 最多 Z / 預設 W」claim</li>
<li>對每個 claim、查 vendor official docs（最新 docs）/ recent release note（過去 12 個月）</li>
<li>不確定的標 <em>uncertain</em>、不要 confidence-fake</li>
</ul>
<h3 id="5-reviewer-c-必查-vendor-feature-time-sensitive-claim">5. Reviewer C 必查 vendor feature time-sensitive claim</h3>
<p>跑 4-reviewer audit 時、Reviewer C（技術準確性）必須：</p>
<ul>
<li>對每個 <em>feature limitation claim</em>、verify 是否仍 current</li>
<li>對每個 <em>vendor CLI command</em>、verify 是否真實存在（hallucinated CLI 是 sibling 問題）</li>
<li>對每個 <em>vendor default value</em>、verify 是否最新</li>
</ul>
<h2 id="hallucination-鄰近議題">Hallucination 鄰近議題</h2>
<p>LLM 寫 vendor CLI command 容易 hallucinate（例如 <code>pscale database promote-shadow</code>、<code>vtctldclient PartitionTablet</code>）— 命令不存在、是 LLM 編造。</p>
<p>跟本卡時間敏感性 <em>不完全相同</em> —</p>
<ul>
<li>時間敏感性：<em>claim 寫作時 valid、現在過時</em></li>
<li>Hallucination：<em>claim 寫作時也 invalid、是編造</em></li>
</ul>
<p>兩者修法部分重疊：</p>
<ul>
<li>寫前 verify（claim + CLI）</li>
<li>Reviewer C audit</li>
<li>不確定標 uncertain</li>
</ul>
<p>但 hallucination 是 <em>更基本的 verify failure</em>、本卡聚焦時間敏感性。</p>
<h2 id="跟既有原則的關係">跟既有原則的關係</h2>
<ul>
<li><a href="../sibling-coverage-asymmetry-blindspot-in-priority/">Sibling Coverage Asymmetry Blindspot in Priority</a>：本卡是 <em>claim 時間敏感性</em>、那卡是 <em>coverage 對稱性</em>、不同 axis</li>
<li><a href="../data-topology-as-audit-dimension/">Data Topology as Audit Dimension</a>：本卡是 <em>寫作 audit 應加時間維度</em>、那卡是 <em>content audit 應加 topology 維度</em></li>
</ul>
<h2 id="反向驗證">反向驗證</h2>
<p>不該誤用本卡：</p>
<ul>
<li><em>穩定 fact</em>（SQL syntax / RFC standard / industry-wide convention）不必標時間性、只有 <em>vendor-specific evolving feature</em> 才需要</li>
<li>不是每個 claim 都要 verify — 「MySQL replication 用 binlog」是穩定 fact、不必加 <em>as of N</em></li>
<li>過度標 <em>as of N</em> 會讓 article 變 verbose、只對 <em>limitation claim</em> 跟 <em>vendor-specific behavior</em> 套用</li>
</ul>
<h2 id="觸發再評估">觸發再評估</h2>
<p>未來累積到以下情境、本卡應 review：</p>
<ul>
<li>連續 2 個 batch 都踩 hallucinated CLI（trigger 升級到強制 <em>寫前 CLI verify</em>）</li>
<li>Feature claim 反轉 invalidates 整段流程的 case 超過 3 次（trigger 把 vendor article 改成 <em>每 N 個月 re-verify</em> 紀律）</li>
<li>LLM training cutoff 跟 vendor changelog 速度差變更大（trigger 升級 verify cadence）</li>
</ul>
]]></content:encoded></item><item><title>字句層 review：keyword bank 命中是候選、不是判決</title><link>https://tarrragon.github.io/blog/report/keyword-bank-hit-is-candidate-not-verdict/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/keyword-bank-hit-is-candidate-not-verdict/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>字句層 review 有兩個獨立步驟：偵測（這句有沒有命中可疑訊號）跟判定（這個命中是不是違規）。keyword bank 解的是偵測、判定仍是一個獨立的語意認知步驟。&lt;/strong> reviewer 拿到 grep 命中後、傾向把它合理化成「這個 case 可以接受」而放行 — 偵測成功、判定失敗、違規一樣留在稿件裡。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>grep keyword bank（#114）&lt;/td>
 &lt;td>關鍵詞不在 bank 裡 → 漏命中（coverage gap）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>判定&lt;/td>
 &lt;td>reviewer 語意判斷&lt;/td>
 &lt;td>命中了、但被合理化成「可接受對照」→ 放行（judgment gap）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>#114 把字句層 review 的失敗歸到偵測層（沒 keyword bank、靠記憶 sweep）。本卡補它沒覆蓋的另一層：&lt;strong>就算 grep 命中、reviewer 仍可能判錯&lt;/strong>。命中只是候選、不是判決。&lt;/p>
&lt;hr>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>寫作規範「正向陳述優先」（主要敘述用正向句建立概念、反例只做對照）的 review、跑 grep &lt;code>不[行可是要能]|無法|沒[做有]|而非|而不是&lt;/code>。這個 bank 會命中兩類完全不同的句子：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>建立概念的否定&lt;/strong>：「高階函式&lt;strong>不是&lt;/strong>『用了比較高級』、&lt;strong>而是&lt;/strong>特定場景的自然解」 — 用否定當核心概念的開場、違反正向陳述。&lt;/li>
&lt;li>&lt;strong>反例對照的否定&lt;/strong>：「對照反例：假設一個只有單一布林設定的 controller…既&lt;strong>沒有&lt;/strong>共用流程、也&lt;strong>沒有&lt;/strong>開放的變化點」 — 在明示的反例段落裡、否定是對照本身、規範允許。&lt;/li>
&lt;/ul>
&lt;p>兩者 grep 命中長得一樣、語意角色相反。reviewer 掃命中清單時、若用「這裡有對照意味、應該算反例」的寬鬆預設、會把第一類也放行 —— 這正是本卡的 case：grep 命中了「不是…而是」、被判成「正向對照修辭、OK」、由讀者再次 feedback 才 catch。&lt;/p>
&lt;p>另有一類問題連命中都沒有：&lt;strong>訴諸群體的安撫贅語&lt;/strong>（「很多人卡在…」「大家都會搞混…」）。這類句子沒有固定關鍵詞（「很多人 / 大家 / 不少開發者 / 初學時」表面形式發散）、keyword bank 結構上抓不到、只能靠語意 pass。&lt;/p>
&lt;hr>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="否定句構命中後用概念位置判定不用有沒有對照意味判定">否定句構命中後、用「概念位置」判定、不用「有沒有對照意味」判定&lt;/h3>
&lt;p>判別問題從「這句有對照意味嗎」（太寬、幾乎都 yes）換成 &lt;strong>「這個否定在建立核心概念、還是在明示的反例段落裡做對照」&lt;/strong>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>直接陳述「B 是什麼」、把對 A 的否定整個拿掉&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>明示的「反例 / 對照 / 不適合場景」段落內&lt;/td>
 &lt;td>保留 — 否定是對照本體&lt;/td>
 &lt;td>不動（規範允許、見 #94）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>用對比定義術語（「裸寫 = 略過取名」）&lt;/td>
 &lt;td>保留 — 否定是定義的本質&lt;/td>
 &lt;td>不動&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵修法是&lt;strong>正向直述 B&lt;/strong>：「X 不是 A、而是 B」→「X 是 B」、把 A 的排除留給上下文或反例段。把「不是 A」翻成「而非 A」只是換個負向詞、仍違規。&lt;/p>
&lt;p>這條判定準則剛好夾在兩張既有卡之間：#94 警告「別過度刪對照（刪掉承擔 reasoning 的 Y 會讓結論空降）」、正向陳述優先要求「別保留建立概念的否定」。判別線就是上表的「概念位置」—— 概念開場的否定該刪、反例段落的對照該留。&lt;/p>
&lt;h3 id="沒有關鍵詞的贅語靠-reader-simulation-補">沒有關鍵詞的贅語、靠 reader-simulation 補&lt;/h3>
&lt;p>訴諸群體的安撫贅語抓不到固定關鍵詞、改用「換視角」pass：假裝讀者、問每一句「這句給了新資訊、還是只在安撫我（讓我覺得不是只有自己不會）」。教學文的責任是把概念講清楚、不是安撫讀者情緒 —— 安撫句一律刪、保留有教學價值的聚焦（「要分清什麼」）。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="規範掃描器顯示乾淨違規仍在">規範掃描器顯示「乾淨」、違規仍在&lt;/h3>
&lt;p>跑完 grep、把命中逐條判成「可接受」、回報「字句層 clean」 —— 這個 clean 是 judgment 放水的結果、不是真的沒違規。比「沒跑 grep」更危險：沒跑還知道沒查、跑完誤判會產生「已經查過」的虛假信心。&lt;/p>
&lt;h3 id="違規類型有系統性偏移">違規類型有系統性偏移&lt;/h3>
&lt;p>被合理化放行的是&lt;strong>特定一類&lt;/strong>（建立概念的否定句構），有系統性偏移。同一個寬鬆預設會在每篇文章放行同一類違規 —— 跨稿件累積成 systematic miss、跟 #114 的偵測層 systematic miss 同構、只是發生在判定層。&lt;/p>
&lt;h3 id="keyword-bank-越長judgment-放水越隱形">keyword bank 越長、judgment 放水越隱形&lt;/h3>
&lt;p>bank 補得越完整、命中越多、reviewer 越依賴「快速掃過命中清單」、每條停留判定的時間越短、越容易用寬鬆預設批次放行。偵測能力提升反而稀釋判定品質 —— 兩層要分開要求、不能假設「有 bank 就會判對」。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../multi-pass-review-frame-granularity-blindspot/">#114 Multi-pass review 的 frame 顆粒度盲點&lt;/a>&lt;/strong>：#114 解偵測層（把規則展開成 keyword bank、不靠記憶 sweep）。本卡是它的下一層 —— &lt;strong>就算 bank 命中、判定仍可能放水&lt;/strong>。#114 的 keyword bank 範例已收「不是 A 而是 B」、但收進 bank 只保證命中、不保證判對；本卡補「命中後怎麼判」。訴諸群體贅語則是 #114 bank 該補的新 coverage（無固定關鍵詞、靠 reader-simulation）。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據、不能空降結論&lt;/a>&lt;/strong>：#94 跟本卡是同一判定軸的兩極。#94 防「過度刪 —— 刪掉承擔 reasoning 的對照 Y、結論變空降」；本卡防「過度留 —— 保留建立概念的否定、用『這是對照』當藉口」。兩卡合起來才是完整判定準則：以「概念位置」區分該刪（概念開場）還是該留（反例段落 / reasoning 對照）。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../rule-codification-vs-self-audit/">#147 規範化跟自審是兩種認知任務&lt;/a>&lt;/strong>：#147 講「立了規範 ≠ 能在自己稿件辨識實例」。本卡是更細一層 —— &lt;strong>連 grep 命中（自審的最強形式、已經指到具體句子）都可能因判定放水而失效&lt;/strong>。#147 的三層機制（grep / checklist / reviewer in-stream）裡、本卡聚焦 grep 那層的「命中之後」缺口。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精修&lt;/a>&lt;/strong>：grep 命中是字面層攔截、看不到那個否定承擔的是「建立概念」還是「反例對照」 —— 需要 behavioral pass（讀者讀到這句、是拿到正向概念還是被否定句卡住）才能判。本卡是 #82 在「字句層 review 判定」的具體實例。&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>grep 命中清單掃過、大半判「可接受對照」&lt;/td>
 &lt;td>停 —— 寬鬆預設正在放水、逐條改用「概念位置」判定&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>命中的否定句在段首 / 小節開場 / 核心議題句&lt;/td>
 &lt;td>違規 —— 改正向直述、別翻成「而非」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>把「不是 A 而是 B」改成「而非 A」就收工&lt;/td>
 &lt;td>沒修 —— 只是換個負向詞、仍是否定建立概念&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>回報「字句層 clean」但只跑了 grep、沒做語意 pass&lt;/td>
 &lt;td>clean 可能是判定放水 —— 補 reader-simulation 一輪&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>句子在安撫讀者（「很多人 / 大家都會」）卻無關鍵詞命中&lt;/td>
 &lt;td>keyword bank 抓不到 —— 靠「這句給新資訊還是安撫」語意問句刪&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="適用範圍與邊界">適用範圍與邊界&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>適用&lt;/strong>：正向陳述優先這類「同一訊號命中、語意角色相反」的字句層規範 review；AI 輔助寫作的 self-review（最容易在判定層放水）；keyword bank 已建立、但 review 回報品質仍不穩的情境。&lt;/li>
&lt;li>&lt;strong>不適用&lt;/strong>：偵測本身就漏（關鍵詞不在 bank）的問題 —— 那是 #114 的偵測層、先補 bank 再談判定。&lt;/li>
&lt;li>&lt;strong>邊界&lt;/strong>：判定收緊 ≠ 一律刪否定。明示反例段落的對照（#94 的 reasoning Y）該留；判別線是「概念位置」、不是「有沒有否定詞」。收太緊會退回 #94 警告的「空降斷言」。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源&lt;/h2>
&lt;p>本卡觸發於 review &lt;a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式&lt;/a> 時。流程是先跑 3 個 frame 的 multi-round review + 字句層 grep keyword bank：&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>字句層 review 有兩個獨立步驟：偵測（這句有沒有命中可疑訊號）跟判定（這個命中是不是違規）。keyword bank 解的是偵測、判定仍是一個獨立的語意認知步驟。</strong> reviewer 拿到 grep 命中後、傾向把它合理化成「這個 case 可以接受」而放行 — 偵測成功、判定失敗、違規一樣留在稿件裡。</p>
<table>
  <thead>
      <tr>
          <th>步驟</th>
          <th>工具</th>
          <th>失敗模式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>偵測</td>
          <td>grep keyword bank（#114）</td>
          <td>關鍵詞不在 bank 裡 → 漏命中（coverage gap）</td>
      </tr>
      <tr>
          <td>判定</td>
          <td>reviewer 語意判斷</td>
          <td>命中了、但被合理化成「可接受對照」→ 放行（judgment gap）</td>
      </tr>
  </tbody>
</table>
<p>#114 把字句層 review 的失敗歸到偵測層（沒 keyword bank、靠記憶 sweep）。本卡補它沒覆蓋的另一層：<strong>就算 grep 命中、reviewer 仍可能判錯</strong>。命中只是候選、不是判決。</p>
<hr>
<h2 id="情境">情境</h2>
<p>寫作規範「正向陳述優先」（主要敘述用正向句建立概念、反例只做對照）的 review、跑 grep <code>不[行可是要能]|無法|沒[做有]|而非|而不是</code>。這個 bank 會命中兩類完全不同的句子：</p>
<ul>
<li><strong>建立概念的否定</strong>：「高階函式<strong>不是</strong>『用了比較高級』、<strong>而是</strong>特定場景的自然解」 — 用否定當核心概念的開場、違反正向陳述。</li>
<li><strong>反例對照的否定</strong>：「對照反例：假設一個只有單一布林設定的 controller…既<strong>沒有</strong>共用流程、也<strong>沒有</strong>開放的變化點」 — 在明示的反例段落裡、否定是對照本身、規範允許。</li>
</ul>
<p>兩者 grep 命中長得一樣、語意角色相反。reviewer 掃命中清單時、若用「這裡有對照意味、應該算反例」的寬鬆預設、會把第一類也放行 —— 這正是本卡的 case：grep 命中了「不是…而是」、被判成「正向對照修辭、OK」、由讀者再次 feedback 才 catch。</p>
<p>另有一類問題連命中都沒有：<strong>訴諸群體的安撫贅語</strong>（「很多人卡在…」「大家都會搞混…」）。這類句子沒有固定關鍵詞（「很多人 / 大家 / 不少開發者 / 初學時」表面形式發散）、keyword bank 結構上抓不到、只能靠語意 pass。</p>
<hr>
<h2 id="理想做法">理想做法</h2>
<h3 id="否定句構命中後用概念位置判定不用有沒有對照意味判定">否定句構命中後、用「概念位置」判定、不用「有沒有對照意味」判定</h3>
<p>判別問題從「這句有對照意味嗎」（太寬、幾乎都 yes）換成 <strong>「這個否定在建立核心概念、還是在明示的反例段落裡做對照」</strong>：</p>
<table>
  <thead>
      <tr>
          <th>命中位置</th>
          <th>判定</th>
          <th>修法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>段首 / 小節開場 / 核心議題句</td>
          <td>違規 — 用否定建立概念</td>
          <td>直接陳述「B 是什麼」、把對 A 的否定整個拿掉</td>
      </tr>
      <tr>
          <td>明示的「反例 / 對照 / 不適合場景」段落內</td>
          <td>保留 — 否定是對照本體</td>
          <td>不動（規範允許、見 #94）</td>
      </tr>
      <tr>
          <td>用對比定義術語（「裸寫 = 略過取名」）</td>
          <td>保留 — 否定是定義的本質</td>
          <td>不動</td>
      </tr>
  </tbody>
</table>
<p>關鍵修法是<strong>正向直述 B</strong>：「X 不是 A、而是 B」→「X 是 B」、把 A 的排除留給上下文或反例段。把「不是 A」翻成「而非 A」只是換個負向詞、仍違規。</p>
<p>這條判定準則剛好夾在兩張既有卡之間：#94 警告「別過度刪對照（刪掉承擔 reasoning 的 Y 會讓結論空降）」、正向陳述優先要求「別保留建立概念的否定」。判別線就是上表的「概念位置」—— 概念開場的否定該刪、反例段落的對照該留。</p>
<h3 id="沒有關鍵詞的贅語靠-reader-simulation-補">沒有關鍵詞的贅語、靠 reader-simulation 補</h3>
<p>訴諸群體的安撫贅語抓不到固定關鍵詞、改用「換視角」pass：假裝讀者、問每一句「這句給了新資訊、還是只在安撫我（讓我覺得不是只有自己不會）」。教學文的責任是把概念講清楚、不是安撫讀者情緒 —— 安撫句一律刪、保留有教學價值的聚焦（「要分清什麼」）。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="規範掃描器顯示乾淨違規仍在">規範掃描器顯示「乾淨」、違規仍在</h3>
<p>跑完 grep、把命中逐條判成「可接受」、回報「字句層 clean」 —— 這個 clean 是 judgment 放水的結果、不是真的沒違規。比「沒跑 grep」更危險：沒跑還知道沒查、跑完誤判會產生「已經查過」的虛假信心。</p>
<h3 id="違規類型有系統性偏移">違規類型有系統性偏移</h3>
<p>被合理化放行的是<strong>特定一類</strong>（建立概念的否定句構），有系統性偏移。同一個寬鬆預設會在每篇文章放行同一類違規 —— 跨稿件累積成 systematic miss、跟 #114 的偵測層 systematic miss 同構、只是發生在判定層。</p>
<h3 id="keyword-bank-越長judgment-放水越隱形">keyword bank 越長、judgment 放水越隱形</h3>
<p>bank 補得越完整、命中越多、reviewer 越依賴「快速掃過命中清單」、每條停留判定的時間越短、越容易用寬鬆預設批次放行。偵測能力提升反而稀釋判定品質 —— 兩層要分開要求、不能假設「有 bank 就會判對」。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../multi-pass-review-frame-granularity-blindspot/">#114 Multi-pass review 的 frame 顆粒度盲點</a></strong>：#114 解偵測層（把規則展開成 keyword bank、不靠記憶 sweep）。本卡是它的下一層 —— <strong>就算 bank 命中、判定仍可能放水</strong>。#114 的 keyword bank 範例已收「不是 A 而是 B」、但收進 bank 只保證命中、不保證判對；本卡補「命中後怎麼判」。訴諸群體贅語則是 #114 bank 該補的新 coverage（無固定關鍵詞、靠 reader-simulation）。</li>
<li><strong><a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據、不能空降結論</a></strong>：#94 跟本卡是同一判定軸的兩極。#94 防「過度刪 —— 刪掉承擔 reasoning 的對照 Y、結論變空降」；本卡防「過度留 —— 保留建立概念的否定、用『這是對照』當藉口」。兩卡合起來才是完整判定準則：以「概念位置」區分該刪（概念開場）還是該留（反例段落 / reasoning 對照）。</li>
<li><strong><a href="../rule-codification-vs-self-audit/">#147 規範化跟自審是兩種認知任務</a></strong>：#147 講「立了規範 ≠ 能在自己稿件辨識實例」。本卡是更細一層 —— <strong>連 grep 命中（自審的最強形式、已經指到具體句子）都可能因判定放水而失效</strong>。#147 的三層機制（grep / checklist / reviewer in-stream）裡、本卡聚焦 grep 那層的「命中之後」缺口。</li>
<li><strong><a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精修</a></strong>：grep 命中是字面層攔截、看不到那個否定承擔的是「建立概念」還是「反例對照」 —— 需要 behavioral pass（讀者讀到這句、是拿到正向概念還是被否定句卡住）才能判。本卡是 #82 在「字句層 review 判定」的具體實例。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>grep 命中清單掃過、大半判「可接受對照」</td>
          <td>停 —— 寬鬆預設正在放水、逐條改用「概念位置」判定</td>
      </tr>
      <tr>
          <td>命中的否定句在段首 / 小節開場 / 核心議題句</td>
          <td>違規 —— 改正向直述、別翻成「而非」</td>
      </tr>
      <tr>
          <td>把「不是 A 而是 B」改成「而非 A」就收工</td>
          <td>沒修 —— 只是換個負向詞、仍是否定建立概念</td>
      </tr>
      <tr>
          <td>回報「字句層 clean」但只跑了 grep、沒做語意 pass</td>
          <td>clean 可能是判定放水 —— 補 reader-simulation 一輪</td>
      </tr>
      <tr>
          <td>句子在安撫讀者（「很多人 / 大家都會」）卻無關鍵詞命中</td>
          <td>keyword bank 抓不到 —— 靠「這句給新資訊還是安撫」語意問句刪</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：正向陳述優先這類「同一訊號命中、語意角色相反」的字句層規範 review；AI 輔助寫作的 self-review（最容易在判定層放水）；keyword bank 已建立、但 review 回報品質仍不穩的情境。</li>
<li><strong>不適用</strong>：偵測本身就漏（關鍵詞不在 bank）的問題 —— 那是 #114 的偵測層、先補 bank 再談判定。</li>
<li><strong>邊界</strong>：判定收緊 ≠ 一律刪否定。明示反例段落的對照（#94 的 reasoning Y）該留；判別線是「概念位置」、不是「有沒有否定詞」。收太緊會退回 #94 警告的「空降斷言」。</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於 review <a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式</a> 時。流程是先跑 3 個 frame 的 multi-round review + 字句層 grep keyword bank：</p>
<ol>
<li>grep <strong>命中</strong>了核心議題句「高階函式<strong>不是</strong>『用了比較高級』、<strong>而是</strong>特定場景的自然解」跟小節開場「<strong>不是</strong>『能用就用』、<strong>而是</strong>…三個特徵」。</li>
<li>我把這些命中判成「正向對照修辭、OK」、回報「字句層大致乾淨」。</li>
<li>讀者 feedback 指出這仍違反正向陳述 —— 偵測成功、判定失敗。</li>
<li>修正後讀者再指出「很多人卡在…」是訴諸群體的安撫贅語 —— 這類連 grep 都沒命中（無固定關鍵詞）。</li>
</ol>
<p>對應本卡：<strong>keyword bank 命中是候選、不是判決</strong>。第一類（命中誤判）揭露判定層盲點、第二類（無命中）揭露 coverage 仍需 reader-simulation 補。兩者共同說明：字句層 review 的偵測（grep）跟判定（語意）是兩個步驟、不能假設「跑了 bank 就會判對、就會抓全」。</p>
]]></content:encoded></item><item><title>教材用中性陳述、不對讀者喊話</title><link>https://tarrragon.github.io/blog/report/teaching-register-states-not-addresses-reader/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/teaching-register-states-not-addresses-reader/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>1 個 case&lt;/strong>（&lt;a href="../../work-log/dart_hof_typedef_readability/">HOF / typedef 可讀性文章&lt;/a>的 review、一次抓到 3 種對讀者喊話的形式）抽出來的觀察。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>三 sub-case 是 starting set、不是窮舉&lt;/strong>：安撫 / 第二人稱 / 祈使是這次出現過的、不代表「對讀者喊話的完整形式庫」。新形式（反問句「想想看為什麼？」、預告「接下來你會看到」）出現時要持續擴充。&lt;/li>
&lt;li>&lt;strong>「中性 vs 親近」是情境化取捨、不是 zero-sum&lt;/strong>：本卡聚焦「判斷工具型 / 概念建立段」的喊話；hook / 引言 / narrative 段落的輕度第二人稱反而幫讀者進入論述、不適用本卡。&lt;/li>
&lt;li>&lt;strong>修補有效性未獨立驗證&lt;/strong>：改成中性陳述後讀起來更聚焦、但「register 跟讀者實際理解之間的相關性」沒做使用者測試。&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、先判斷段落是否屬於「概念建立 / 判斷工具型」——是 → 套用；否（hook / narrative）→ 評估親近感跟中性的取捨。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>教材的責任是把概念講清楚、不是管理讀者的情緒或閱讀節奏。&lt;/strong> 對讀者喊話的句子讀起來親近、但承載的是「對話 stance」而非概念內容 —— 把讀者當成要被安撫、被代入、被指揮的對象，多出來的是資訊負擔、拖慢進入正題。&lt;/p>
&lt;p>下面三種形式是觀察到的 pattern —— 不是窮舉、實際形式可能更多：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>對讀者喊話的形式&lt;/th>
 &lt;th>具體案例&lt;/th>
 &lt;th>喊話的 stance&lt;/th>
 &lt;th>中性改法&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>安撫情緒 / 訴諸群體&lt;/td>
 &lt;td>「很多人卡在…」「大家都會搞混…」&lt;/td>
 &lt;td>讓讀者覺得「不是只有自己不會」&lt;/td>
 &lt;td>直接講概念：「這個簽章的關鍵是分清 X」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>第二人稱代入&lt;/td>
 &lt;td>「你天天寫的 &lt;code>int count&lt;/code>」「你天天在用 map」&lt;/td>
 &lt;td>把讀者拉進句子當主詞&lt;/td>
 &lt;td>中性指稱：「常見的 &lt;code>int count&lt;/code>」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>祈使控制閱讀&lt;/td>
 &lt;td>「先讀懂這個簽章」「先釐清 X」「別搞混」&lt;/td>
 &lt;td>指揮讀者的閱讀順序 / 動作&lt;/td>
 &lt;td>描述性名詞標題：「簽章的型別與名字拆解」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵是這三種&lt;strong>精度都沒問題&lt;/strong> —— 「你天天寫的 &lt;code>int count&lt;/code>」指涉完全正確、「先讀懂這個簽章」語意清楚。違反不在用詞精度、在 &lt;strong>register/stance&lt;/strong>：教材該是「陳述概念」、喊話是「對讀者說話」。&lt;/p>
&lt;hr>
&lt;h2 id="三種形式的具體-case">三種形式的具體 case&lt;/h2>
&lt;h3 id="形式-1安撫情緒--訴諸群體">形式 1：安撫情緒 / 訴諸群體&lt;/h3>
&lt;p>&lt;strong>喊話版&lt;/strong>：「很多人卡在『這串到底哪裡是型別、哪裡是名字』。」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：「很多人」沒有資訊量 —— 讀者不會因為「別人也卡」而更懂型別跟名字怎麼分。它的功能是情緒安撫（你不孤單）、不是概念傳遞。教材的價值在講清楚概念、讀者的情緒不是它的責任。&lt;/p>
&lt;p>&lt;strong>中性版&lt;/strong>：「這個簽章的關鍵是分清『哪裡是型別、哪裡是名字』。」&lt;/p>
&lt;p>差別：中性版第一句就是概念聚焦（要分清什麼）、喊話版前半句純安撫、讀者要跳過它才到正題。&lt;/p>
&lt;h3 id="形式-2第二人稱代入">形式 2：第二人稱代入&lt;/h3>
&lt;p>&lt;strong>喊話版&lt;/strong>：「順序跟&lt;strong>你天天寫的&lt;/strong> &lt;code>int count&lt;/code>、&lt;code>Color color&lt;/code> 一樣」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：「你天天寫的」把讀者拉進句子當主詞、預設讀者的日常（萬一讀者沒天天寫 Dart？）。它想營造親近感、但概念（&lt;code>int count&lt;/code> 是 &lt;code>型別 名字&lt;/code> 順序）不依賴「誰寫的」。&lt;/p>
&lt;p>&lt;strong>中性版&lt;/strong>：「順序跟&lt;strong>常見的&lt;/strong> &lt;code>int count&lt;/code>、&lt;code>Color color&lt;/code> 一樣」&lt;/p>
&lt;p>差別：中性版用「常見的」指涉同一組例子、不預設讀者身分、概念一樣到位。&lt;/p>
&lt;h3 id="形式-3祈使控制閱讀">形式 3：祈使控制閱讀&lt;/h3>
&lt;p>&lt;strong>喊話版&lt;/strong>：小節標題「&lt;strong>先讀懂&lt;/strong>這個簽章的每個部分」、「&lt;strong>先釐清&lt;/strong>：什麼是 X」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：「先讀懂 / 先釐清」是對讀者下閱讀指令、控制節奏。標題的責任是標示這段在講什麼（讓讀者自己決定讀不讀）、不是指揮讀者「先做什麼」。&lt;/p>
&lt;p>&lt;strong>中性版&lt;/strong>：描述性名詞標題「簽章的型別與名字拆解」、「什麼是『函式型別裸寫在簽章』」&lt;/p>
&lt;p>差別：名詞標題讓讀者掃目錄就知道內容、祈使標題把目錄變成指令清單。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="資訊負擔累積稀釋概念密度">資訊負擔累積、稀釋概念密度&lt;/h3>
&lt;p>每句喊話都是「非概念」的字 —— 安撫、代入、指令本身不傳遞知識。教材裡散佈喊話、讀者要持續過濾「這句給資訊還是在跟我說話」、概念密度被稀釋。&lt;/p>
&lt;h3 id="預設讀者身分對不上就失效">預設讀者身分、對不上就失效&lt;/h3>
&lt;p>「你天天寫的」「很多人卡在」都預設了讀者的背景 / 經驗 / 困難。對不上的讀者（沒天天寫、第一次就懂）會感到突兀、甚至被排除 —— 跟 AGENTS 原則六「讀者定位用內容體現、不貼標籤」同源的失效。&lt;/p>
&lt;h3 id="keyword-bank-抓不到靠語意-pass">Keyword bank 抓不到、靠語意 pass&lt;/h3>
&lt;p>第二人稱（&lt;code>你&lt;/code> 會誤命中 code 註解）跟祈使（句式發散、無固定詞）沒有穩定關鍵詞、grep keyword bank 結構上抓不到 —— 這類問題只能靠 reader-simulation 語意 pass（「這句在給資訊、還是在指揮 / 安撫讀者？」）。正是 #149 講的 coverage gap。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度&lt;/a>&lt;/strong>：兩卡是字句層的 sibling、但軸不同。#111 是「&lt;strong>精度&lt;/strong>」軸（用詞能不能反推機制 / 條件 / 契約）；本卡是「&lt;strong>register/stance&lt;/strong>」軸（陳述概念 vs 對讀者說話）。「你天天寫的 &lt;code>int count&lt;/code>」精度完全正確、卻是錯 register —— #111 抓不到、要本卡。兩卡共享同一個情境邊界：hook / narrative 段落都放寬。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../keyword-bank-hit-is-candidate-not-verdict/">#149 keyword bank 命中是候選、不是判決&lt;/a>&lt;/strong>：本卡是 #149 的 content 對偶。#149 是 &lt;strong>review-process&lt;/strong>（偵測≠判定、怎麼審）、本卡是 &lt;strong>content 原則&lt;/strong>（prose 該怎麼寫）。#149 把「安撫贅語」當 coverage-gap 的&lt;strong>舉例&lt;/strong>、本卡把它&lt;strong>確立成 content 原則&lt;/strong>。產生情境不同：#149 源於 reviewer 誤判 grep 命中、本卡源於寫作當下 prose 對讀者喊話。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../multi-pass-review-frame-granularity-blindspot/">#114 Multi-pass review 的 frame 顆粒度盲點&lt;/a>&lt;/strong>：本卡的三形式裡、第二人稱跟祈使&lt;strong>沒有固定關鍵詞&lt;/strong>、是 #114 keyword bank 機制的已知盲區 —— 補強的是 #114 的 reader-simulation 機制（換視角）、不是 keyword bank（換工具）。&lt;/li>
&lt;li>&lt;strong>AGENTS 原則六（讀者定位用內容體現）&lt;/strong>：兩者相鄰但機制不同。原則六禁「&lt;strong>貼標籤&lt;/strong>」（叫讀者『新手 / 新人』）、本卡禁「&lt;strong>稱呼 / 指揮&lt;/strong>」（你 / 先讀懂）。可以不貼標籤卻仍在喊話（「你天天寫的」沒叫讀者新手、仍是第二人稱代入）—— 本卡補原則六沒覆蓋的 stance 維度。&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>第二人稱代入 —— 改中性指稱（常見的 / 一般而言）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>標題或開場是「先讀懂 / 先釐清 / 別搞混 / 記住」&lt;/td>
 &lt;td>祈使控制閱讀 —— 改描述性名詞標題&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>grep &lt;code>你&lt;/code> 命中、但分不清正文還是 code 註解&lt;/td>
 &lt;td>keyword bank 抓不準 —— 改 reader-simulation 語意問句&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>自問「這句給新概念、還是在跟讀者說話」答後者&lt;/td>
 &lt;td>對讀者喊話 —— 刪 stance、留概念&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="適用範圍與邊界">適用範圍與邊界&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>適用&lt;/strong>：概念建立段、判斷工具型段落、小節標題 —— 這些地方的責任是傳遞概念 / 標示內容、喊話純屬負擔。&lt;/li>
&lt;li>&lt;strong>不適用&lt;/strong>：hook / 引言 / narrative 開場 —— 輕度第二人稱（「假設你在維護一個…」）能幫讀者進入情境、跟 #111 的 hook 例外同理。&lt;/li>
&lt;li>&lt;strong>邊界&lt;/strong>：中性化 ≠ 消滅所有「你」。判別線是「這句在&lt;strong>傳遞概念 / 標示內容&lt;/strong>、還是在&lt;strong>管理讀者&lt;/strong>（安撫情緒 / 代入身分 / 指揮閱讀）」—— 後者才刪。protocol 型文件（操作步驟、checklist）的祈使是合理 stance、不適用本卡。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源&lt;/h2>
&lt;p>本卡觸發於 review &lt;a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式&lt;/a> 時、由讀者連續指出三種對讀者喊話：&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>1 個 case</strong>（<a href="../../work-log/dart_hof_typedef_readability/">HOF / typedef 可讀性文章</a>的 review、一次抓到 3 種對讀者喊話的形式）抽出來的觀察。具體限制：</p>
<ul>
<li><strong>三 sub-case 是 starting set、不是窮舉</strong>：安撫 / 第二人稱 / 祈使是這次出現過的、不代表「對讀者喊話的完整形式庫」。新形式（反問句「想想看為什麼？」、預告「接下來你會看到」）出現時要持續擴充。</li>
<li><strong>「中性 vs 親近」是情境化取捨、不是 zero-sum</strong>：本卡聚焦「判斷工具型 / 概念建立段」的喊話；hook / 引言 / narrative 段落的輕度第二人稱反而幫讀者進入論述、不適用本卡。</li>
<li><strong>修補有效性未獨立驗證</strong>：改成中性陳述後讀起來更聚焦、但「register 跟讀者實際理解之間的相關性」沒做使用者測試。</li>
</ul>
<p>讀者使用本卡時、先判斷段落是否屬於「概念建立 / 判斷工具型」——是 → 套用；否（hook / narrative）→ 評估親近感跟中性的取捨。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p><strong>教材的責任是把概念講清楚、不是管理讀者的情緒或閱讀節奏。</strong> 對讀者喊話的句子讀起來親近、但承載的是「對話 stance」而非概念內容 —— 把讀者當成要被安撫、被代入、被指揮的對象，多出來的是資訊負擔、拖慢進入正題。</p>
<p>下面三種形式是觀察到的 pattern —— 不是窮舉、實際形式可能更多：</p>
<table>
  <thead>
      <tr>
          <th>對讀者喊話的形式</th>
          <th>具體案例</th>
          <th>喊話的 stance</th>
          <th>中性改法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>安撫情緒 / 訴諸群體</td>
          <td>「很多人卡在…」「大家都會搞混…」</td>
          <td>讓讀者覺得「不是只有自己不會」</td>
          <td>直接講概念：「這個簽章的關鍵是分清 X」</td>
      </tr>
      <tr>
          <td>第二人稱代入</td>
          <td>「你天天寫的 <code>int count</code>」「你天天在用 map」</td>
          <td>把讀者拉進句子當主詞</td>
          <td>中性指稱：「常見的 <code>int count</code>」</td>
      </tr>
      <tr>
          <td>祈使控制閱讀</td>
          <td>「先讀懂這個簽章」「先釐清 X」「別搞混」</td>
          <td>指揮讀者的閱讀順序 / 動作</td>
          <td>描述性名詞標題：「簽章的型別與名字拆解」</td>
      </tr>
  </tbody>
</table>
<p>關鍵是這三種<strong>精度都沒問題</strong> —— 「你天天寫的 <code>int count</code>」指涉完全正確、「先讀懂這個簽章」語意清楚。違反不在用詞精度、在 <strong>register/stance</strong>：教材該是「陳述概念」、喊話是「對讀者說話」。</p>
<hr>
<h2 id="三種形式的具體-case">三種形式的具體 case</h2>
<h3 id="形式-1安撫情緒--訴諸群體">形式 1：安撫情緒 / 訴諸群體</h3>
<p><strong>喊話版</strong>：「很多人卡在『這串到底哪裡是型別、哪裡是名字』。」</p>
<p><strong>問題</strong>：「很多人」沒有資訊量 —— 讀者不會因為「別人也卡」而更懂型別跟名字怎麼分。它的功能是情緒安撫（你不孤單）、不是概念傳遞。教材的價值在講清楚概念、讀者的情緒不是它的責任。</p>
<p><strong>中性版</strong>：「這個簽章的關鍵是分清『哪裡是型別、哪裡是名字』。」</p>
<p>差別：中性版第一句就是概念聚焦（要分清什麼）、喊話版前半句純安撫、讀者要跳過它才到正題。</p>
<h3 id="形式-2第二人稱代入">形式 2：第二人稱代入</h3>
<p><strong>喊話版</strong>：「順序跟<strong>你天天寫的</strong> <code>int count</code>、<code>Color color</code> 一樣」</p>
<p><strong>問題</strong>：「你天天寫的」把讀者拉進句子當主詞、預設讀者的日常（萬一讀者沒天天寫 Dart？）。它想營造親近感、但概念（<code>int count</code> 是 <code>型別 名字</code> 順序）不依賴「誰寫的」。</p>
<p><strong>中性版</strong>：「順序跟<strong>常見的</strong> <code>int count</code>、<code>Color color</code> 一樣」</p>
<p>差別：中性版用「常見的」指涉同一組例子、不預設讀者身分、概念一樣到位。</p>
<h3 id="形式-3祈使控制閱讀">形式 3：祈使控制閱讀</h3>
<p><strong>喊話版</strong>：小節標題「<strong>先讀懂</strong>這個簽章的每個部分」、「<strong>先釐清</strong>：什麼是 X」</p>
<p><strong>問題</strong>：「先讀懂 / 先釐清」是對讀者下閱讀指令、控制節奏。標題的責任是標示這段在講什麼（讓讀者自己決定讀不讀）、不是指揮讀者「先做什麼」。</p>
<p><strong>中性版</strong>：描述性名詞標題「簽章的型別與名字拆解」、「什麼是『函式型別裸寫在簽章』」</p>
<p>差別：名詞標題讓讀者掃目錄就知道內容、祈使標題把目錄變成指令清單。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="資訊負擔累積稀釋概念密度">資訊負擔累積、稀釋概念密度</h3>
<p>每句喊話都是「非概念」的字 —— 安撫、代入、指令本身不傳遞知識。教材裡散佈喊話、讀者要持續過濾「這句給資訊還是在跟我說話」、概念密度被稀釋。</p>
<h3 id="預設讀者身分對不上就失效">預設讀者身分、對不上就失效</h3>
<p>「你天天寫的」「很多人卡在」都預設了讀者的背景 / 經驗 / 困難。對不上的讀者（沒天天寫、第一次就懂）會感到突兀、甚至被排除 —— 跟 AGENTS 原則六「讀者定位用內容體現、不貼標籤」同源的失效。</p>
<h3 id="keyword-bank-抓不到靠語意-pass">Keyword bank 抓不到、靠語意 pass</h3>
<p>第二人稱（<code>你</code> 會誤命中 code 註解）跟祈使（句式發散、無固定詞）沒有穩定關鍵詞、grep keyword bank 結構上抓不到 —— 這類問題只能靠 reader-simulation 語意 pass（「這句在給資訊、還是在指揮 / 安撫讀者？」）。正是 #149 講的 coverage gap。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度</a></strong>：兩卡是字句層的 sibling、但軸不同。#111 是「<strong>精度</strong>」軸（用詞能不能反推機制 / 條件 / 契約）；本卡是「<strong>register/stance</strong>」軸（陳述概念 vs 對讀者說話）。「你天天寫的 <code>int count</code>」精度完全正確、卻是錯 register —— #111 抓不到、要本卡。兩卡共享同一個情境邊界：hook / narrative 段落都放寬。</li>
<li><strong><a href="../keyword-bank-hit-is-candidate-not-verdict/">#149 keyword bank 命中是候選、不是判決</a></strong>：本卡是 #149 的 content 對偶。#149 是 <strong>review-process</strong>（偵測≠判定、怎麼審）、本卡是 <strong>content 原則</strong>（prose 該怎麼寫）。#149 把「安撫贅語」當 coverage-gap 的<strong>舉例</strong>、本卡把它<strong>確立成 content 原則</strong>。產生情境不同：#149 源於 reviewer 誤判 grep 命中、本卡源於寫作當下 prose 對讀者喊話。</li>
<li><strong><a href="../multi-pass-review-frame-granularity-blindspot/">#114 Multi-pass review 的 frame 顆粒度盲點</a></strong>：本卡的三形式裡、第二人稱跟祈使<strong>沒有固定關鍵詞</strong>、是 #114 keyword bank 機制的已知盲區 —— 補強的是 #114 的 reader-simulation 機制（換視角）、不是 keyword bank（換工具）。</li>
<li><strong>AGENTS 原則六（讀者定位用內容體現）</strong>：兩者相鄰但機制不同。原則六禁「<strong>貼標籤</strong>」（叫讀者『新手 / 新人』）、本卡禁「<strong>稱呼 / 指揮</strong>」（你 / 先讀懂）。可以不貼標籤卻仍在喊話（「你天天寫的」沒叫讀者新手、仍是第二人稱代入）—— 本卡補原則六沒覆蓋的 stance 維度。</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>第二人稱代入 —— 改中性指稱（常見的 / 一般而言）</td>
      </tr>
      <tr>
          <td>標題或開場是「先讀懂 / 先釐清 / 別搞混 / 記住」</td>
          <td>祈使控制閱讀 —— 改描述性名詞標題</td>
      </tr>
      <tr>
          <td>grep <code>你</code> 命中、但分不清正文還是 code 註解</td>
          <td>keyword bank 抓不準 —— 改 reader-simulation 語意問句</td>
      </tr>
      <tr>
          <td>自問「這句給新概念、還是在跟讀者說話」答後者</td>
          <td>對讀者喊話 —— 刪 stance、留概念</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：概念建立段、判斷工具型段落、小節標題 —— 這些地方的責任是傳遞概念 / 標示內容、喊話純屬負擔。</li>
<li><strong>不適用</strong>：hook / 引言 / narrative 開場 —— 輕度第二人稱（「假設你在維護一個…」）能幫讀者進入情境、跟 #111 的 hook 例外同理。</li>
<li><strong>邊界</strong>：中性化 ≠ 消滅所有「你」。判別線是「這句在<strong>傳遞概念 / 標示內容</strong>、還是在<strong>管理讀者</strong>（安撫情緒 / 代入身分 / 指揮閱讀）」—— 後者才刪。protocol 型文件（操作步驟、checklist）的祈使是合理 stance、不適用本卡。</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於 review <a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式</a> 時、由讀者連續指出三種對讀者喊話：</p>
<ol>
<li><strong>安撫</strong>：「很多人卡在『哪裡是型別、哪裡是名字』」—— 訴諸群體、讓讀者覺得不孤單。</li>
<li><strong>第二人稱</strong>：「順序跟你天天寫的 <code>int count</code> 一樣」「你天天在用 map」—— 把讀者拉進句子。</li>
<li><strong>祈使</strong>：小節標題「先讀懂這個簽章的每個部分」「先釐清：什麼是 X」—— 指揮閱讀順序。</li>
</ol>
<p>三者在 grep keyword bank 的表現不一（安撫有部分關鍵詞「很多人」、第二人稱跟祈使幾乎無固定詞）、但共享同一個違反 —— <strong>教材在對讀者喊話、而非中性陳述概念</strong>。修法統一：安撫句刪、第二人稱改中性指稱、祈使標題改描述性名詞標題。</p>
<p>對應本卡：對讀者喊話是獨立於精度（#111）跟 review-process（#149）的 content register 議題 —— 一個句子可以精度完全正確、grep 完全乾淨、卻因為 stance 錯（在跟讀者說話）而不該留在教材裡。</p>
]]></content:encoded></item><item><title>教材給技術理由、不替方案下品質評價</title><link>https://tarrragon.github.io/blog/report/teaching-gives-reasons-not-quality-verdicts/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/teaching-gives-reasons-not-quality-verdicts/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的建卡判準是&lt;strong>教學需求、不是出現頻率&lt;/strong>（對應 AGENTS 知識卡片規範段：建卡看「讀者缺這個知識會不會難以理解教材」、出現頻率只是補充訊號）。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>觸發 case 只有 1 個實例&lt;/strong>：這次 review 的 HOF 文章只出現一處「教科書級」。建卡的正當性來自「自評誇飾在技術寫作裡是常見 pattern」這個教學需求、不是這篇的頻率。單篇頻率低不影響值得建卡。&lt;/li>
&lt;li>&lt;strong>誇飾詞是 starting set、不是窮舉&lt;/strong>：列出的（教科書級 / 堪稱 / 完美 / 漂亮地）是觀察到的、不代表完整詞庫。新誇飾（神級 / 教科書式 / 無懈可擊）出現時持續擴充。&lt;/li>
&lt;li>&lt;strong>跟 #111 誇張家族部分重疊&lt;/strong>：本卡跟 #111 同屬「誇飾」大類、靠「評價對象」區分（見關係段）。邊界可能在某些句子模糊、需個案判斷。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>教材的責任是給出「為什麼這樣設計 / 為什麼適配」的技術理由，不對方案下品質評價。&lt;/strong> 自評誇飾（「X 是教科書級的適配」「堪稱經典」「完美契合」）讀起來像作者在替自己的方案打分數 —— 它傳遞的是作者的滿意度、不是讀者能用的概念。&lt;/p>
&lt;p>更深的問題是&lt;strong>品質評價會頂替技術理由&lt;/strong>：寫了「X 是教科書級的適配」、就佔掉了本該寫「X 為什麼適配」的位置。讀者拿到一個 verdict（這方案很好）、但拿不到 reasoning（好在哪、適配條件是什麼、邊界在哪）。誇飾是「&lt;strong>評價空降&lt;/strong>」—— 給結論不給依據。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>自評誇飾&lt;/th>
 &lt;th>讀者拿到的&lt;/th>
 &lt;th>該換成的技術理由&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>「X 是教科書級的適配」&lt;/td>
 &lt;td>作者覺得很適配&lt;/td>
 &lt;td>X 對上的具體結構（固定流程寫死、變化點抽參數）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「堪稱經典的設計」&lt;/td>
 &lt;td>作者覺得很經典&lt;/td>
 &lt;td>這設計解決的具體問題 + 成立條件&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「完美契合不可變模型」&lt;/td>
 &lt;td>作者覺得很契合&lt;/td>
 &lt;td>契合的機制（更新本質是 current → next、函式參數正好表達）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「漂亮地解決了 X」&lt;/td>
 &lt;td>作者覺得很漂亮&lt;/td>
 &lt;td>解法的步驟 + 為什麼這樣最省&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="具體-case">具體 case&lt;/h2>
&lt;p>&lt;strong>誇飾版&lt;/strong>：「當『共用流程』與『變化點』能這樣切乾淨時，HOF 是&lt;strong>教科書級的適配&lt;/strong>：把固定流程寫死在 &lt;code>update&lt;/code> 裡，把變化點抽成函式參數 &lt;code>transform&lt;/code> 由呼叫端帶入。」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>「教科書級」是品質評價、不是技術內容 —— 讀者無法反推「適配到什麼程度、什麼條件下成立、邊界在哪」。&lt;/li>
&lt;li>它頂替了理由的位置：冒號後面的「把固定流程寫死、把變化點抽成參數」其實才是真正的適配理由、但被「教科書級」這個 verdict 搶了焦點。&lt;/li>
&lt;li>沒有教學會說某寫法是「教科書寫法」—— 這句話的語氣是個人檢討在誇方案、不是教材在講概念。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>修法版&lt;/strong>：「當『共用流程』與『變化點』能這樣切乾淨時，HOF &lt;strong>正好對上這個結構&lt;/strong>：把固定流程寫死在 &lt;code>update&lt;/code> 裡，把變化點抽成函式參數 &lt;code>transform&lt;/code> 由呼叫端帶入。」&lt;/p>
&lt;p>差別：「正好對上這個結構」是中性的適配陳述、把焦點交給冒號後面的具體機制；「教科書級」是 verdict、把焦點留在作者的評價上。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="讀者拿到-verdict拿不到可遷移的判準">讀者拿到 verdict、拿不到可遷移的判準&lt;/h3>
&lt;p>「教科書級的適配」讀完、讀者只知道「作者覺得這很適配」、無法判斷自己的 case 適不適配。教學的目的是讓讀者拿到能套用到新情境的 reasoning —— 品質評價給不了這個。這違反 AGENTS 原則七（每段要有可操作判準、不能只做評價）。&lt;/p>
&lt;h3 id="評價會掩蓋理由其實沒寫">評價會掩蓋「理由其實沒寫」&lt;/h3>
&lt;p>誇飾讀起來很有說服力、容易讓作者跟 reviewer 都以為「這段講清楚了」。實際上 verdict 佔了版面、理由可能根本沒展開 —— 跟 #94 的空降斷言同構：包裝成肯定句、但依據是空的。&lt;/p>
&lt;h3 id="語氣從教材滑向個人檢討">語氣從教材滑向個人檢討&lt;/h3>
&lt;p>「教科書級 / 堪稱經典」是回顧視角的自我評價（我這方案選得好）。教材是面向讀者講概念、不是面向自己總結成果 —— 語氣一滑、整段的 register 就從「教學」變成「炫耀 / 自評」。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度&lt;/a>&lt;/strong>：兩卡同屬「誇飾」大類、靠&lt;strong>評價對象&lt;/strong>區分。#111 的誇飾誇張的是&lt;strong>技術屬性&lt;/strong>（「一輩子」誇張時間、「整個炸了」誇張嚴重度）—— 是對技術事實的不精確描述。本卡的誇飾評價的是&lt;strong>方案品質&lt;/strong>（「教科書級」評價設計好壞）—— 根本不在描述技術事實、是 verdict 頂替 reasoning。#111 修法是「翻譯回技術屬性」、本卡修法是「換成技術理由」。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../teaching-register-states-not-addresses-reader/">#150 教材用中性陳述、不對讀者喊話&lt;/a>&lt;/strong>：兩卡是 register/stance 議題的 sibling。#150 的違反是「&lt;strong>管理讀者&lt;/strong>」（安撫 / 代入 / 指揮）、本卡的違反是「&lt;strong>評價方案&lt;/strong>」（替自己的設計打分數）。兩者都背離「教材中性陳述概念」這個上層 stance、但對象不同（讀者 vs 方案）。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據、不能空降結論&lt;/a>&lt;/strong>：本卡是 #94「空降斷言」在「品質評價」維度的變體。#94 處理「刪掉對照 Y → 結論 X 變空降」、本卡處理「誇飾 verdict 頂替理由 → 評價變空降」。兩者共享同一個失敗：給結論不給依據、讀者只能選擇相信或腦補。&lt;/li>
&lt;li>&lt;strong>AGENTS 原則七（每段要有可操作判準）&lt;/strong>：誇飾直接違反原則七 —— verdict 不是判準。本卡是原則七在「自評誇飾」這個具體違反形式上的展開。&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>verdict 頂替 reasoning —— 補回理由&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>刪掉誇飾詞後、該段的適配理由仍完整&lt;/td>
 &lt;td>誇飾是純贅字 —— 直接刪&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>刪掉誇飾詞後、該段只剩 verdict、沒有理由&lt;/td>
 &lt;td>理由根本沒寫 —— 補機制 / 條件、不是補誇飾&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>語氣像在總結「我選得好」而非對讀者講概念&lt;/td>
 &lt;td>register 滑向個人檢討 —— 改回中性陳述&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="適用範圍與邊界">適用範圍與邊界&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>適用&lt;/strong>：概念建立段、設計理由段、適配性論述 —— 這些地方該給機制 / 條件、不該給品質評價。&lt;/li>
&lt;li>&lt;strong>不適用&lt;/strong>：純 narrative / 復盤型內容（work-log 的事件回顧、retrospective）—— 這類內容本就含作者視角的評價、誇飾是合理 register。&lt;/li>
&lt;li>&lt;strong>邊界&lt;/strong>：中性化 ≠ 禁止一切「適配 / 適合」字眼。判別線是「這句給的是&lt;strong>可遷移的判讀條件&lt;/strong>（三條件齊備時 HOF 比列舉更省）還是&lt;strong>品質 verdict&lt;/strong>（教科書級）」—— 前者是判準該留、後者是評價該換。帶條件的適配陳述不是誇飾。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源&lt;/h2>
&lt;p>本卡觸發於 review &lt;a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式&lt;/a> 時、讀者指出「HOF 是教科書級的適配」這句 —— 「這比較像個人檢討、沒有教學會說這是教科書寫法」。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的建卡判準是<strong>教學需求、不是出現頻率</strong>（對應 AGENTS 知識卡片規範段：建卡看「讀者缺這個知識會不會難以理解教材」、出現頻率只是補充訊號）。具體限制：</p>
<ul>
<li><strong>觸發 case 只有 1 個實例</strong>：這次 review 的 HOF 文章只出現一處「教科書級」。建卡的正當性來自「自評誇飾在技術寫作裡是常見 pattern」這個教學需求、不是這篇的頻率。單篇頻率低不影響值得建卡。</li>
<li><strong>誇飾詞是 starting set、不是窮舉</strong>：列出的（教科書級 / 堪稱 / 完美 / 漂亮地）是觀察到的、不代表完整詞庫。新誇飾（神級 / 教科書式 / 無懈可擊）出現時持續擴充。</li>
<li><strong>跟 #111 誇張家族部分重疊</strong>：本卡跟 #111 同屬「誇飾」大類、靠「評價對象」區分（見關係段）。邊界可能在某些句子模糊、需個案判斷。</li>
</ul>
<hr>
<h2 id="核心原則">核心原則</h2>
<p><strong>教材的責任是給出「為什麼這樣設計 / 為什麼適配」的技術理由，不對方案下品質評價。</strong> 自評誇飾（「X 是教科書級的適配」「堪稱經典」「完美契合」）讀起來像作者在替自己的方案打分數 —— 它傳遞的是作者的滿意度、不是讀者能用的概念。</p>
<p>更深的問題是<strong>品質評價會頂替技術理由</strong>：寫了「X 是教科書級的適配」、就佔掉了本該寫「X 為什麼適配」的位置。讀者拿到一個 verdict（這方案很好）、但拿不到 reasoning（好在哪、適配條件是什麼、邊界在哪）。誇飾是「<strong>評價空降</strong>」—— 給結論不給依據。</p>
<table>
  <thead>
      <tr>
          <th>自評誇飾</th>
          <th>讀者拿到的</th>
          <th>該換成的技術理由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「X 是教科書級的適配」</td>
          <td>作者覺得很適配</td>
          <td>X 對上的具體結構（固定流程寫死、變化點抽參數）</td>
      </tr>
      <tr>
          <td>「堪稱經典的設計」</td>
          <td>作者覺得很經典</td>
          <td>這設計解決的具體問題 + 成立條件</td>
      </tr>
      <tr>
          <td>「完美契合不可變模型」</td>
          <td>作者覺得很契合</td>
          <td>契合的機制（更新本質是 current → next、函式參數正好表達）</td>
      </tr>
      <tr>
          <td>「漂亮地解決了 X」</td>
          <td>作者覺得很漂亮</td>
          <td>解法的步驟 + 為什麼這樣最省</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="具體-case">具體 case</h2>
<p><strong>誇飾版</strong>：「當『共用流程』與『變化點』能這樣切乾淨時，HOF 是<strong>教科書級的適配</strong>：把固定流程寫死在 <code>update</code> 裡，把變化點抽成函式參數 <code>transform</code> 由呼叫端帶入。」</p>
<p><strong>問題</strong>：</p>
<ul>
<li>「教科書級」是品質評價、不是技術內容 —— 讀者無法反推「適配到什麼程度、什麼條件下成立、邊界在哪」。</li>
<li>它頂替了理由的位置：冒號後面的「把固定流程寫死、把變化點抽成參數」其實才是真正的適配理由、但被「教科書級」這個 verdict 搶了焦點。</li>
<li>沒有教學會說某寫法是「教科書寫法」—— 這句話的語氣是個人檢討在誇方案、不是教材在講概念。</li>
</ul>
<p><strong>修法版</strong>：「當『共用流程』與『變化點』能這樣切乾淨時，HOF <strong>正好對上這個結構</strong>：把固定流程寫死在 <code>update</code> 裡，把變化點抽成函式參數 <code>transform</code> 由呼叫端帶入。」</p>
<p>差別：「正好對上這個結構」是中性的適配陳述、把焦點交給冒號後面的具體機制；「教科書級」是 verdict、把焦點留在作者的評價上。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="讀者拿到-verdict拿不到可遷移的判準">讀者拿到 verdict、拿不到可遷移的判準</h3>
<p>「教科書級的適配」讀完、讀者只知道「作者覺得這很適配」、無法判斷自己的 case 適不適配。教學的目的是讓讀者拿到能套用到新情境的 reasoning —— 品質評價給不了這個。這違反 AGENTS 原則七（每段要有可操作判準、不能只做評價）。</p>
<h3 id="評價會掩蓋理由其實沒寫">評價會掩蓋「理由其實沒寫」</h3>
<p>誇飾讀起來很有說服力、容易讓作者跟 reviewer 都以為「這段講清楚了」。實際上 verdict 佔了版面、理由可能根本沒展開 —— 跟 #94 的空降斷言同構：包裝成肯定句、但依據是空的。</p>
<h3 id="語氣從教材滑向個人檢討">語氣從教材滑向個人檢討</h3>
<p>「教科書級 / 堪稱經典」是回顧視角的自我評價（我這方案選得好）。教材是面向讀者講概念、不是面向自己總結成果 —— 語氣一滑、整段的 register 就從「教學」變成「炫耀 / 自評」。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度</a></strong>：兩卡同屬「誇飾」大類、靠<strong>評價對象</strong>區分。#111 的誇飾誇張的是<strong>技術屬性</strong>（「一輩子」誇張時間、「整個炸了」誇張嚴重度）—— 是對技術事實的不精確描述。本卡的誇飾評價的是<strong>方案品質</strong>（「教科書級」評價設計好壞）—— 根本不在描述技術事實、是 verdict 頂替 reasoning。#111 修法是「翻譯回技術屬性」、本卡修法是「換成技術理由」。</li>
<li><strong><a href="../teaching-register-states-not-addresses-reader/">#150 教材用中性陳述、不對讀者喊話</a></strong>：兩卡是 register/stance 議題的 sibling。#150 的違反是「<strong>管理讀者</strong>」（安撫 / 代入 / 指揮）、本卡的違反是「<strong>評價方案</strong>」（替自己的設計打分數）。兩者都背離「教材中性陳述概念」這個上層 stance、但對象不同（讀者 vs 方案）。</li>
<li><strong><a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據、不能空降結論</a></strong>：本卡是 #94「空降斷言」在「品質評價」維度的變體。#94 處理「刪掉對照 Y → 結論 X 變空降」、本卡處理「誇飾 verdict 頂替理由 → 評價變空降」。兩者共享同一個失敗：給結論不給依據、讀者只能選擇相信或腦補。</li>
<li><strong>AGENTS 原則七（每段要有可操作判準）</strong>：誇飾直接違反原則七 —— verdict 不是判準。本卡是原則七在「自評誇飾」這個具體違反形式上的展開。</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>verdict 頂替 reasoning —— 補回理由</td>
      </tr>
      <tr>
          <td>刪掉誇飾詞後、該段的適配理由仍完整</td>
          <td>誇飾是純贅字 —— 直接刪</td>
      </tr>
      <tr>
          <td>刪掉誇飾詞後、該段只剩 verdict、沒有理由</td>
          <td>理由根本沒寫 —— 補機制 / 條件、不是補誇飾</td>
      </tr>
      <tr>
          <td>語氣像在總結「我選得好」而非對讀者講概念</td>
          <td>register 滑向個人檢討 —— 改回中性陳述</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：概念建立段、設計理由段、適配性論述 —— 這些地方該給機制 / 條件、不該給品質評價。</li>
<li><strong>不適用</strong>：純 narrative / 復盤型內容（work-log 的事件回顧、retrospective）—— 這類內容本就含作者視角的評價、誇飾是合理 register。</li>
<li><strong>邊界</strong>：中性化 ≠ 禁止一切「適配 / 適合」字眼。判別線是「這句給的是<strong>可遷移的判讀條件</strong>（三條件齊備時 HOF 比列舉更省）還是<strong>品質 verdict</strong>（教科書級）」—— 前者是判準該留、後者是評價該換。帶條件的適配陳述不是誇飾。</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於 review <a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式</a> 時、讀者指出「HOF 是教科書級的適配」這句 —— 「這比較像個人檢討、沒有教學會說這是教科書寫法」。</p>
<p>關鍵判讀：這句<strong>精度沒問題</strong>（HOF 確實適配這個結構）、<strong>grep 也不一定命中</strong>（「教科書級」不在口語修辭 keyword bank）、但 register 錯了 —— 它在評價方案品質、不在陳述技術理由。修法是把「教科書級的適配」換成「正好對上這個結構」、讓焦點回到冒號後面的具體機制。</p>
<p>建卡的正當性來自<strong>教學需求</strong>、不是這篇的頻率：自評誇飾在技術寫作裡是常見 pattern、讀者 / 作者都容易把「verdict 讀起來有說服力」誤當「理由講清楚了」。這篇只有 1 個實例、但 pattern 普遍 —— 對應 AGENTS 知識卡片規範段「建卡看教學需求、出現頻率只是補充訊號」。</p>
]]></content:encoded></item><item><title>教材把設計選擇講成選擇、不講成必然或天性</title><link>https://tarrragon.github.io/blog/report/design-choices-framed-as-choices-not-necessity/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/design-choices-framed-as-choices-not-necessity/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>1 個 case&lt;/strong>（&lt;a href="../../work-log/dart_hof_typedef_readability/">HOF / typedef 文章&lt;/a>的「更新的本質天生就是一個函式」）抽出來的觀察、建卡判準是教學需求（本質主義框架在技術寫作、尤其 LLM 生成內容裡是高發 pattern）。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>必然性詞是 starting set&lt;/strong>：天生 / 本質就是 / 必然 / 唯一 / 註定 是觀察到的、不窮舉。新形式（生來 / 理所當然 / 不可能不）持續擴充。&lt;/li>
&lt;li>&lt;strong>跟 compositional-writing 原則三（機會成本語氣）部分重疊&lt;/strong>：本卡是原則三的一個 subtype、靠「絕對的形式」區分（命令式 vs 必然式、見關係段）。原則三未獨立成 report 卡、本卡補這個缺口的必然性維度。&lt;/li>
&lt;li>&lt;strong>「設計 vs 必然」的界線本身是判斷&lt;/strong>：某些陳述介於「被上游選擇逼出來的後果」跟「真正的自然必然」之間（見邊界段）、需個案判讀。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>設計選擇要講成選擇 —— 說明它在什麼條件下成立、為什麼比替代方案好，而不是用「天生 / 本質就是 / 必然」把它講成自然法則。&lt;/strong> 必然性框架抹掉設計能動性：讀者拿到「這本來就這樣」、卻不知道「這是一個選擇、有前提、有替代」。&lt;/p>
&lt;p>這是「機會成本語氣 vs 絕對主義」違反的一個 subtype，但比命令式絕對更隱形：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>「應該用 X」「正確做法是 X」&lt;/td>
 &lt;td>讀者聽得出這是主張、會質疑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>必然式（本卡）&lt;/strong>&lt;/td>
 &lt;td>「X 天生就是 Y」「本質就是 Y」「必然是 Y」&lt;/td>
 &lt;td>偽裝成事實陳述、讀者不會質疑「天性」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>必然式更該防 —— 它不說「你該怎麼做」（讀者會審），而說「事情本來就這樣」（讀者直接接受）、把一個 trade-off 藏進「自然」的外衣。&lt;/p>
&lt;hr>
&lt;h2 id="具體-case">具體 case&lt;/h2>
&lt;p>&lt;strong>必然版&lt;/strong>：「更新的本質&lt;strong>天生就是&lt;/strong>一個 &lt;code>(current) =&amp;gt; next&lt;/code> 的函式 — 拿舊值算出新值。」&lt;/p>
&lt;p>&lt;strong>問題&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>update 是設計出來的方法、不是與生俱來的東西、「天生」語義場（生物性 / 本能）對不上設計產物（表層症狀）。&lt;/li>
&lt;li>更深：update 以 &lt;code>(current) =&amp;gt; next&lt;/code> 形式呈現、&lt;strong>只在「選了不可變模型」之後才成立&lt;/strong>。不可變本身是設計選擇（&lt;code>@immutable&lt;/code> + &lt;code>copyWith&lt;/code>）—— 「天生」把這個前提條件跳過、讓條件性結論變成無條件真理。&lt;/li>
&lt;li>最深：&lt;strong>牴觸文章自己的論點&lt;/strong>。這篇通篇論證 HOF 是&lt;strong>條件性&lt;/strong>適配（「三條件齊備才划算」「場景不對時硬用是過度設計」）—— 唯獨這句用「天生」把它講成必然、局部破壞了文章自己的條件性紀律。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>修法版&lt;/strong>：「&lt;strong>不可變模型下的&lt;/strong>更新，在語意上&lt;strong>就是&lt;/strong>一個 &lt;code>(current) =&amp;gt; next&lt;/code> 的函式 — 拿舊值算出新值。」&lt;/p>
&lt;p>差別：修法版用「不可變模型下的」把前提條件講出來、用「就是」取代「天生」—— 結論還在、但還原成「在某前提下成立」、不再偽裝成自然法則。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="讀者學到規則而非思考方式">讀者學到「規則」而非「思考方式」&lt;/h3>
&lt;p>必然框架告訴讀者「事情本來就這樣」、讀者拿到一條沒有條件的規則。換個情境（可變模型、需要 persist 的場景）規則就不適用、但讀者不知道邊界在哪 —— 因為「天生」沒給條件。機會成本語氣的核心就是「教思考方式（能遷移）而非規則（壓力下會忘）」、必然框架直接違反。&lt;/p>
&lt;h3 id="局部牴觸自身論點瓦解可信度">局部牴觸自身論點、瓦解可信度&lt;/h3>
&lt;p>一篇講「看條件、不是必然」的文章、出現一句「天生 / 必然」、細心的讀者會發現矛盾 —— 到底是條件性還是必然？這比單純用詞不當更傷：它瓦解文章整體論證的一致性。本質主義框架的高發處正是「作者其實知道是條件性、但順手用了必然語氣」。&lt;/p>
&lt;h3 id="偽裝成事實躲過-review">偽裝成事實、躲過 review&lt;/h3>
&lt;p>「應該用 X」這種命令式主張、reviewer 會審「憑什麼應該」。「X 天生就是 Y」偽裝成事實陳述、reviewer 容易直接接受 —— 跟 #151 誇飾、#94 空降斷言同構：把需要依據的東西包裝成不需要依據的形式、躲過檢查。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>compositional-writing 原則三（機會成本語氣優先）&lt;/strong>：本卡是原則三的 subtype。原則三主要談命令式絕對（「應該 / 正確做法是 / 替代方案不足」）、本卡補&lt;strong>必然式絕對&lt;/strong>（天生 / 本質就是 / 必然）這個更隱形的維度。原則三未獨立成 report 卡 —— 本卡是它在「必然性框架」這個具體形式上的 report 化。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../teaching-gives-reasons-not-quality-verdicts/">#151 教材給技術理由、不替方案下品質評價&lt;/a>&lt;/strong>：兩卡是「空降家族」的 sibling、都把需要依據的東西包裝成不需要依據。#151 是&lt;strong>品質 verdict 空降&lt;/strong>（教科書級頂替理由）、本卡是&lt;strong>必然框架空降&lt;/strong>（天生頂替條件）。差別在頂替的東西：#151 頂替「為什麼好」、本卡頂替「在什麼條件下成立」。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據、不能空降結論&lt;/a>&lt;/strong>：#94 是空降家族的源頭（刪掉對照 Y → 結論 X 空降）。本卡跟 #151 都是 #94 在不同維度的變體 —— 三者共享「給結論不給依據、讀者只能相信或腦補」的失敗。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度&lt;/a>&lt;/strong>：「天生」在表層也是一種用詞精度問題（語義場對不上指涉對象）—— 但本卡聚焦的是它的&lt;strong>框架效果&lt;/strong>（把設計絕對化）、不是精度。#111 抓表層用詞、本卡抓深層框架、可疊加。&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>句子說「X 本來就是 Y」、但 X 是設計出來的&lt;/td>
 &lt;td>必然框架 —— 補前提條件（「在選了 Z 之後、X 以 Y 形式成立」）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>同一篇別處強調「看條件 / 看場景 / trade-off」&lt;/td>
 &lt;td>檢查必然句是否牴觸自身條件性論點 —— 是 → 對齊&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>必然陳述讀起來像事實、但其實是設計決策&lt;/td>
 &lt;td>偽裝成事實的主張 —— 還原成「選擇 + 理由 + 條件」&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>：設計理由段、概念建立段、適配性論述 —— 凡是在講「某設計 / 某結構為什麼成立」的地方。&lt;/li>
&lt;li>&lt;strong>不適用&lt;/strong>：物理 / 法律 / 合規 / 數學事實（per 原則三的例外）—— 「雜湊碰撞必然存在」「GDPR 規定必須 X」這類是真必然、可用必然語氣。&lt;/li>
&lt;li>&lt;strong>邊界&lt;/strong>：條件性後果 vs 真必然的判別線是「&lt;strong>這個必然有沒有上游的設計選擇當前提&lt;/strong>」。「不可變模型下、更新是 current → next」是條件性（前提=選了不可變）、要講出前提；「任何雜湊函式都有碰撞」是真必然（不依賴任何設計選擇）、可直接斷言。被上游選擇逼出來的後果、不是天性。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源&lt;/h2>
&lt;p>本卡觸發於 review &lt;a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式&lt;/a> 時、讀者指出「更新的本質&lt;strong>天生&lt;/strong>就是一個函式」—— 「不會有天生這件事、update 也是設計出來的、中文語義上不可能說這叫天生」。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>1 個 case</strong>（<a href="../../work-log/dart_hof_typedef_readability/">HOF / typedef 文章</a>的「更新的本質天生就是一個函式」）抽出來的觀察、建卡判準是教學需求（本質主義框架在技術寫作、尤其 LLM 生成內容裡是高發 pattern）。具體限制：</p>
<ul>
<li><strong>必然性詞是 starting set</strong>：天生 / 本質就是 / 必然 / 唯一 / 註定 是觀察到的、不窮舉。新形式（生來 / 理所當然 / 不可能不）持續擴充。</li>
<li><strong>跟 compositional-writing 原則三（機會成本語氣）部分重疊</strong>：本卡是原則三的一個 subtype、靠「絕對的形式」區分（命令式 vs 必然式、見關係段）。原則三未獨立成 report 卡、本卡補這個缺口的必然性維度。</li>
<li><strong>「設計 vs 必然」的界線本身是判斷</strong>：某些陳述介於「被上游選擇逼出來的後果」跟「真正的自然必然」之間（見邊界段）、需個案判讀。</li>
</ul>
<hr>
<h2 id="核心原則">核心原則</h2>
<p><strong>設計選擇要講成選擇 —— 說明它在什麼條件下成立、為什麼比替代方案好，而不是用「天生 / 本質就是 / 必然」把它講成自然法則。</strong> 必然性框架抹掉設計能動性：讀者拿到「這本來就這樣」、卻不知道「這是一個選擇、有前提、有替代」。</p>
<p>這是「機會成本語氣 vs 絕對主義」違反的一個 subtype，但比命令式絕對更隱形：</p>
<table>
  <thead>
      <tr>
          <th>絕對主義形式</th>
          <th>句型</th>
          <th>為什麼隱形</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>命令式（原則三主要談的）</td>
          <td>「應該用 X」「正確做法是 X」</td>
          <td>讀者聽得出這是主張、會質疑</td>
      </tr>
      <tr>
          <td><strong>必然式（本卡）</strong></td>
          <td>「X 天生就是 Y」「本質就是 Y」「必然是 Y」</td>
          <td>偽裝成事實陳述、讀者不會質疑「天性」</td>
      </tr>
  </tbody>
</table>
<p>必然式更該防 —— 它不說「你該怎麼做」（讀者會審），而說「事情本來就這樣」（讀者直接接受）、把一個 trade-off 藏進「自然」的外衣。</p>
<hr>
<h2 id="具體-case">具體 case</h2>
<p><strong>必然版</strong>：「更新的本質<strong>天生就是</strong>一個 <code>(current) =&gt; next</code> 的函式 — 拿舊值算出新值。」</p>
<p><strong>問題</strong>：</p>
<ul>
<li>update 是設計出來的方法、不是與生俱來的東西、「天生」語義場（生物性 / 本能）對不上設計產物（表層症狀）。</li>
<li>更深：update 以 <code>(current) =&gt; next</code> 形式呈現、<strong>只在「選了不可變模型」之後才成立</strong>。不可變本身是設計選擇（<code>@immutable</code> + <code>copyWith</code>）—— 「天生」把這個前提條件跳過、讓條件性結論變成無條件真理。</li>
<li>最深：<strong>牴觸文章自己的論點</strong>。這篇通篇論證 HOF 是<strong>條件性</strong>適配（「三條件齊備才划算」「場景不對時硬用是過度設計」）—— 唯獨這句用「天生」把它講成必然、局部破壞了文章自己的條件性紀律。</li>
</ul>
<p><strong>修法版</strong>：「<strong>不可變模型下的</strong>更新，在語意上<strong>就是</strong>一個 <code>(current) =&gt; next</code> 的函式 — 拿舊值算出新值。」</p>
<p>差別：修法版用「不可變模型下的」把前提條件講出來、用「就是」取代「天生」—— 結論還在、但還原成「在某前提下成立」、不再偽裝成自然法則。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="讀者學到規則而非思考方式">讀者學到「規則」而非「思考方式」</h3>
<p>必然框架告訴讀者「事情本來就這樣」、讀者拿到一條沒有條件的規則。換個情境（可變模型、需要 persist 的場景）規則就不適用、但讀者不知道邊界在哪 —— 因為「天生」沒給條件。機會成本語氣的核心就是「教思考方式（能遷移）而非規則（壓力下會忘）」、必然框架直接違反。</p>
<h3 id="局部牴觸自身論點瓦解可信度">局部牴觸自身論點、瓦解可信度</h3>
<p>一篇講「看條件、不是必然」的文章、出現一句「天生 / 必然」、細心的讀者會發現矛盾 —— 到底是條件性還是必然？這比單純用詞不當更傷：它瓦解文章整體論證的一致性。本質主義框架的高發處正是「作者其實知道是條件性、但順手用了必然語氣」。</p>
<h3 id="偽裝成事實躲過-review">偽裝成事實、躲過 review</h3>
<p>「應該用 X」這種命令式主張、reviewer 會審「憑什麼應該」。「X 天生就是 Y」偽裝成事實陳述、reviewer 容易直接接受 —— 跟 #151 誇飾、#94 空降斷言同構：把需要依據的東西包裝成不需要依據的形式、躲過檢查。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong>compositional-writing 原則三（機會成本語氣優先）</strong>：本卡是原則三的 subtype。原則三主要談命令式絕對（「應該 / 正確做法是 / 替代方案不足」）、本卡補<strong>必然式絕對</strong>（天生 / 本質就是 / 必然）這個更隱形的維度。原則三未獨立成 report 卡 —— 本卡是它在「必然性框架」這個具體形式上的 report 化。</li>
<li><strong><a href="../teaching-gives-reasons-not-quality-verdicts/">#151 教材給技術理由、不替方案下品質評價</a></strong>：兩卡是「空降家族」的 sibling、都把需要依據的東西包裝成不需要依據。#151 是<strong>品質 verdict 空降</strong>（教科書級頂替理由）、本卡是<strong>必然框架空降</strong>（天生頂替條件）。差別在頂替的東西：#151 頂替「為什麼好」、本卡頂替「在什麼條件下成立」。</li>
<li><strong><a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據、不能空降結論</a></strong>：#94 是空降家族的源頭（刪掉對照 Y → 結論 X 空降）。本卡跟 #151 都是 #94 在不同維度的變體 —— 三者共享「給結論不給依據、讀者只能相信或腦補」的失敗。</li>
<li><strong><a href="../colloquial-rhetoric-erodes-technical-precision/">#111 口語化修辭會稀釋技術精度</a></strong>：「天生」在表層也是一種用詞精度問題（語義場對不上指涉對象）—— 但本卡聚焦的是它的<strong>框架效果</strong>（把設計絕對化）、不是精度。#111 抓表層用詞、本卡抓深層框架、可疊加。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>出現「天生 / 與生俱來 / 本質就是 / 必然 / 唯一 / 註定 / 理所當然」</td>
          <td>檢查指涉對象是不是設計產物 —— 是 → 還原成條件性</td>
      </tr>
      <tr>
          <td>句子說「X 本來就是 Y」、但 X 是設計出來的</td>
          <td>必然框架 —— 補前提條件（「在選了 Z 之後、X 以 Y 形式成立」）</td>
      </tr>
      <tr>
          <td>同一篇別處強調「看條件 / 看場景 / trade-off」</td>
          <td>檢查必然句是否牴觸自身條件性論點 —— 是 → 對齊</td>
      </tr>
      <tr>
          <td>必然陳述讀起來像事實、但其實是設計決策</td>
          <td>偽裝成事實的主張 —— 還原成「選擇 + 理由 + 條件」</td>
      </tr>
      <tr>
          <td>刪掉「天生 / 必然」後句子仍成立</td>
          <td>詞是純贅字 / 偽裝 —— 直接刪或還原條件</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：設計理由段、概念建立段、適配性論述 —— 凡是在講「某設計 / 某結構為什麼成立」的地方。</li>
<li><strong>不適用</strong>：物理 / 法律 / 合規 / 數學事實（per 原則三的例外）—— 「雜湊碰撞必然存在」「GDPR 規定必須 X」這類是真必然、可用必然語氣。</li>
<li><strong>邊界</strong>：條件性後果 vs 真必然的判別線是「<strong>這個必然有沒有上游的設計選擇當前提</strong>」。「不可變模型下、更新是 current → next」是條件性（前提=選了不可變）、要講出前提；「任何雜湊函式都有碰撞」是真必然（不依賴任何設計選擇）、可直接斷言。被上游選擇逼出來的後果、不是天性。</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於 review <a href="../../work-log/dart_hof_typedef_readability/">為什麼這個場景適合用高階函式</a> 時、讀者指出「更新的本質<strong>天生</strong>就是一個函式」—— 「不會有天生這件事、update 也是設計出來的、中文語義上不可能說這叫天生」。</p>
<p>第一輪我把它定性成單純的語義錯置（天生=生物性、對不上設計產物）、讀者要求用 WRAP 再想一次。WRAP 揭露三層遞進：(1) 表層語義場錯置；(2) 中層把設計選擇講成必然、抹掉設計能動性；(3) 深層<strong>牴觸文章自己的條件性論點</strong>（通篇論證 HOF 是條件性適配、唯獨這句講成天生）。</p>
<p>對應本卡：必然性框架不是用詞問題、是<strong>框架問題</strong> —— 把「設計」講成「天性」。它比命令式絕對（#151 / 原則三主談）更隱形、因為偽裝成事實陳述躲過讀者跟 reviewer 的審查；它的高發訊號是「局部牴觸作者自己在別處的條件性立場」。建卡正當性來自教學需求（LLM 寫作高發）、非本 case 頻率（1 實例）。</p>
]]></content:encoded></item><item><title>Review 漏抓先分 design gap 與 execution gap、再決定改框架還是改執行</title><link>https://tarrragon.github.io/blog/report/review-miss-diagnose-design-vs-execution-gap/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/review-miss-diagnose-design-vs-execution-gap/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡是一次 review 失誤的 self-retrospective（用 WRAP 的 Consider the Opposite 反向檢驗自己的 review 過程）抽出。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>樣本是 1 次 review、1 個 reviewer（我自己）&lt;/strong>：「design gap vs execution gap」這個二分基於單次自我檢討、不是跨多次 review 觀察到的 systematic pattern。&lt;/li>
&lt;li>&lt;strong>「自我歸因」有 self-serving 風險&lt;/strong>：reviewer 檢討自己漏抓時、可能傾向把責任推給「框架不足」（design gap）而非「我偷懶」（execution gap）—— 本卡的價值正是強迫拆開這兩者、但拆的人就是當事人、客觀性有限。&lt;/li>
&lt;li>&lt;strong>修法有效性未驗證&lt;/strong>：診斷後的修法（改框架 vs 改執行）是否真能讓下次 catch 到、未經後續 review 驗證。&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、把它當「review 失誤歸因的一個檢查步驟」、不當「驗證過的 review 流程」。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>Review 漏抓某類問題時，先分清是 &lt;strong>design gap&lt;/strong> 還是 &lt;strong>execution gap&lt;/strong>，再決定修法 —— 兩者修法相反。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Design gap&lt;/strong>：框架根本沒有對應的 frame / keyword 去 catch 這類問題。修法是&lt;strong>改框架&lt;/strong>（補 frame、補 keyword bank、補 lens）。&lt;/li>
&lt;li>&lt;strong>Execution gap&lt;/strong>：框架有對應 frame、但 reviewer 這次沒跑（跑了子集、跳過該跑的輪）。修法是&lt;strong>改執行&lt;/strong>（真的跑完該跑的輪），改框架沒用。&lt;/li>
&lt;/ul>
&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>Design gap&lt;/td>
 &lt;td>框架缺 frame&lt;/td>
 &lt;td>補 frame / keyword / lens&lt;/td>
 &lt;td>誤判成 execution → 一直漏同類（以為「下次認真跑」就好、但根本沒對應 frame）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Execution gap&lt;/td>
 &lt;td>沒跑該跑的輪&lt;/td>
 &lt;td>跑完整框架&lt;/td>
 &lt;td>誤判成 design → framework bloat（一直加 frame、卻沒解決「偷跑子集」的習慣）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>同一次漏抓&lt;strong>常常兩者都有&lt;/strong> —— 要分別處理、不能只修一邊。&lt;/p>
&lt;hr>
&lt;h2 id="具體-case">具體 case&lt;/h2>
&lt;p>這次 review 一篇技術教材、跑了「3 個臨時擬的 agent frame + 一次字句層 grep」、回報「字句層大致 clean」。結果使用者分多輪 catch 出 register/stance 類問題（安撫讀者 / 第二人稱 / 自評誇飾 / 必然框架）。用 WRAP Consider the Opposite 反向檢驗，發現&lt;strong>兩種 gap 都有&lt;/strong>：&lt;/p>
&lt;h3 id="execution-gap我沒跑完整框架">Execution gap（我沒跑完整框架）&lt;/h3>
&lt;p>multi-pass review 框架定義了輪 9（reader simulation）、輪 10（self-criticism），但這次&lt;strong>我根本沒跑&lt;/strong> —— 只跑了我臨時擬的 3 個 agent frame + grep。如果跑了輪 9（用讀者視角讀「這段在跟我說話嗎」），喊話類當場會 catch。這部分&lt;strong>不能怪框架&lt;/strong>、是我跑了子集。&lt;/p>
&lt;h3 id="design-gap框架本身的-frame-不夠">Design gap（框架本身的 frame 不夠）&lt;/h3>
&lt;p>但即使跑了輪 9、現有定義是「拿掉 code block 看論述能不能 parse」（聚焦&lt;strong>自包含性&lt;/strong>）、&lt;strong>沒有 register lens&lt;/strong>（這段在管理 / 評價 / 絕對化讀者嗎）。而且 register 類有兩個結構特性讓 keyword bank（輪 8）抓不到：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>無穩定關鍵詞&lt;/strong>：第二人稱「你」誤命中 code 註解、祈使句式發散、訴諸群體形式多。&lt;/li>
&lt;li>&lt;strong>最依賴外部 cold-read&lt;/strong>：這次正是**使用者（外部讀者）**才抓到 —— 同一 reviewer 模擬讀者視角有限（per multi-pass 自承的 partial fix 限制）。&lt;/li>
&lt;/ul>
&lt;p>這部分&lt;strong>要改框架&lt;/strong>：輪 9 擴入 register lens、標明 register 類「reader-sim 主、keyword bank 輔」。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="只改框架framework-bloatexecution-習慣沒解">只改框架：framework bloat、execution 習慣沒解&lt;/h3>
&lt;p>漏抓後直覺反應是「加 keyword / 加 frame」—— 因為這看得見、像進步。但若真正成因是 execution gap（沒跑輪 9）、加再多 keyword 都沒用（那些輪還是沒跑）。框架越加越胖、reviewer 還是偷跑子集。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡是一次 review 失誤的 self-retrospective（用 WRAP 的 Consider the Opposite 反向檢驗自己的 review 過程）抽出。具體限制：</p>
<ul>
<li><strong>樣本是 1 次 review、1 個 reviewer（我自己）</strong>：「design gap vs execution gap」這個二分基於單次自我檢討、不是跨多次 review 觀察到的 systematic pattern。</li>
<li><strong>「自我歸因」有 self-serving 風險</strong>：reviewer 檢討自己漏抓時、可能傾向把責任推給「框架不足」（design gap）而非「我偷懶」（execution gap）—— 本卡的價值正是強迫拆開這兩者、但拆的人就是當事人、客觀性有限。</li>
<li><strong>修法有效性未驗證</strong>：診斷後的修法（改框架 vs 改執行）是否真能讓下次 catch 到、未經後續 review 驗證。</li>
</ul>
<p>讀者使用本卡時、把它當「review 失誤歸因的一個檢查步驟」、不當「驗證過的 review 流程」。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p>Review 漏抓某類問題時，先分清是 <strong>design gap</strong> 還是 <strong>execution gap</strong>，再決定修法 —— 兩者修法相反。</p>
<ul>
<li><strong>Design gap</strong>：框架根本沒有對應的 frame / keyword 去 catch 這類問題。修法是<strong>改框架</strong>（補 frame、補 keyword bank、補 lens）。</li>
<li><strong>Execution gap</strong>：框架有對應 frame、但 reviewer 這次沒跑（跑了子集、跳過該跑的輪）。修法是<strong>改執行</strong>（真的跑完該跑的輪），改框架沒用。</li>
</ul>
<table>
  <thead>
      <tr>
          <th>成因</th>
          <th>問題在哪</th>
          <th>修法</th>
          <th>誤判的後果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Design gap</td>
          <td>框架缺 frame</td>
          <td>補 frame / keyword / lens</td>
          <td>誤判成 execution → 一直漏同類（以為「下次認真跑」就好、但根本沒對應 frame）</td>
      </tr>
      <tr>
          <td>Execution gap</td>
          <td>沒跑該跑的輪</td>
          <td>跑完整框架</td>
          <td>誤判成 design → framework bloat（一直加 frame、卻沒解決「偷跑子集」的習慣）</td>
      </tr>
  </tbody>
</table>
<p>同一次漏抓<strong>常常兩者都有</strong> —— 要分別處理、不能只修一邊。</p>
<hr>
<h2 id="具體-case">具體 case</h2>
<p>這次 review 一篇技術教材、跑了「3 個臨時擬的 agent frame + 一次字句層 grep」、回報「字句層大致 clean」。結果使用者分多輪 catch 出 register/stance 類問題（安撫讀者 / 第二人稱 / 自評誇飾 / 必然框架）。用 WRAP Consider the Opposite 反向檢驗，發現<strong>兩種 gap 都有</strong>：</p>
<h3 id="execution-gap我沒跑完整框架">Execution gap（我沒跑完整框架）</h3>
<p>multi-pass review 框架定義了輪 9（reader simulation）、輪 10（self-criticism），但這次<strong>我根本沒跑</strong> —— 只跑了我臨時擬的 3 個 agent frame + grep。如果跑了輪 9（用讀者視角讀「這段在跟我說話嗎」），喊話類當場會 catch。這部分<strong>不能怪框架</strong>、是我跑了子集。</p>
<h3 id="design-gap框架本身的-frame-不夠">Design gap（框架本身的 frame 不夠）</h3>
<p>但即使跑了輪 9、現有定義是「拿掉 code block 看論述能不能 parse」（聚焦<strong>自包含性</strong>）、<strong>沒有 register lens</strong>（這段在管理 / 評價 / 絕對化讀者嗎）。而且 register 類有兩個結構特性讓 keyword bank（輪 8）抓不到：</p>
<ul>
<li><strong>無穩定關鍵詞</strong>：第二人稱「你」誤命中 code 註解、祈使句式發散、訴諸群體形式多。</li>
<li><strong>最依賴外部 cold-read</strong>：這次正是**使用者（外部讀者）**才抓到 —— 同一 reviewer 模擬讀者視角有限（per multi-pass 自承的 partial fix 限制）。</li>
</ul>
<p>這部分<strong>要改框架</strong>：輪 9 擴入 register lens、標明 register 類「reader-sim 主、keyword bank 輔」。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="只改框架framework-bloatexecution-習慣沒解">只改框架：framework bloat、execution 習慣沒解</h3>
<p>漏抓後直覺反應是「加 keyword / 加 frame」—— 因為這看得見、像進步。但若真正成因是 execution gap（沒跑輪 9）、加再多 keyword 都沒用（那些輪還是沒跑）。框架越加越胖、reviewer 還是偷跑子集。</p>
<h3 id="只改執行漏掉的整類永遠-catch-不到">只改執行：漏掉的整類永遠 catch 不到</h3>
<p>反過來、若把 design gap 誤判成「我下次認真跑就好」、但框架根本沒有對應 frame —— 認真跑現有的輪也 catch 不到、同類問題每次都漏。</p>
<h3 id="加-keyword是最誘人的假修法">「加 keyword」是最誘人的假修法</h3>
<p>加 keyword bank 條目成本低、立即有「補上了」的感覺。但它只解 design gap 的一個 sub-type（偵測層、且限有穩定關鍵詞的類）。對 execution gap（沒跑輪）、對 register 這種無關鍵詞的 design gap、它都無效 —— 容易讓人以為修好了、其實沒。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../multi-pass-review-frame-granularity-blindspot/">#114 Multi-pass review 的 frame 顆粒度盲點</a></strong>：#114 處理的是 <strong>design gap 的一個面向</strong>（frame 不夠細、抽象規則沒展開成具體訊號）。本卡是上位 —— 在「改 frame 顆粒度」之前、先問「這次漏抓到底是缺 frame（design）還是沒跑 frame（execution）」。#114 預設問題在框架、本卡先驗證這個預設。</li>
<li><strong><a href="../rule-codification-vs-self-audit/">#147 規範化跟自審是兩種認知任務</a></strong>：#147 是 execution 側的 sibling —— 「立了規範 ≠ 自己稿件能辨識」講的就是「有 frame 不等於有跑」。本卡把它一般化成「有 frame 不等於有跑（execution gap）」、並跟「根本沒 frame（design gap）」對立起來。</li>
<li><strong><a href="../keyword-bank-hit-is-candidate-not-verdict/">#149 keyword bank 命中是候選、不是判決</a></strong>：#149 是另一個「兩層別混」的 pattern（偵測 vs 判定）。本卡（design vs execution）跟 #149（偵測 vs 判定）都在拆「review 失效的成因層」—— 修法都依賴先分層、再對症。</li>
<li><strong><a href="../teaching-register-states-not-addresses-reader/">#150-152 教材 register / framing 卡</a></strong>：這三張是本卡的觸發 case（漏抓的具體內容）。本卡是它們揭露的 <strong>review 流程層</strong> 教訓 —— 內容卡講「該怎麼寫」、本卡講「review 為什麼沒抓到、該改框架還是改執行」。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Review 漏抓、直覺想「加 keyword / 加 frame」</td>
          <td>先停 —— 問「這次有跑完該跑的輪嗎」、是 execution gap 就別加 frame</td>
      </tr>
      <tr>
          <td>「我下次認真跑就好」</td>
          <td>檢查框架真有對應 frame 嗎 —— 沒有就是 design gap、認真跑也沒用</td>
      </tr>
      <tr>
          <td>跑的是「臨時擬的子集」而非完整框架</td>
          <td>execution gap 訊號 —— 先補跑完整輪、再判斷框架夠不夠</td>
      </tr>
      <tr>
          <td>漏抓的類別有「無穩定關鍵詞」特性</td>
          <td>keyword bank 解不了（design gap 的 reader-sim 類）—— 加 lens、不是加 keyword</td>
      </tr>
      <tr>
          <td>漏抓由外部讀者 / 使用者 catch、自己多輪沒抓到</td>
          <td>該類高度依賴 external cold-read —— 同 reviewer 模擬有限、標明依賴</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：review 流程的 retrospective（漏抓後檢討）、framework 演進決策（要不要加 frame / keyword）、self-review 品質檢討。</li>
<li><strong>不適用</strong>：一次性短文 review（沒有「框架」可言、談不上 design vs execution）。</li>
<li><strong>邊界</strong>：兩者不互斥、常同時存在 —— 本卡要的不是「二選一」、是「分別診斷、分別修」。誤把它當 either-or 會只修一半。</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於對 <a href="../../work-log/dart_hof_typedef_readability/">HOF / typedef 文章</a> 的 review 失誤做 WRAP 檢討。使用者問「多輪審查設定是否需要調整」，WRAP 的 Consider the Opposite 步驟揭露：失敗不全是框架缺陷 —— 一半是我<strong>只跑了臨時子集、跳過框架既有的輪 9/10</strong>（execution gap）、一半是<strong>輪 9 定義聚焦自包含性、缺 register lens、且 register 類無穩定關鍵詞</strong>（design gap）。</p>
<p>對應本卡：若沒做這個拆分、最可能的反應是「再加幾個 keyword」（只解 design gap 的偵測 sub-type）、既沒解 execution gap（下次還是偷跑子集）、也沒解 register 的 reader-sim design gap。拆開後修法清楚：execution gap 靠「review 時真的跑完該跑的輪」（紀律、不改框架）、design gap 靠「輪 9 擴 register lens + 標明 external-reader 依賴」（改框架、下一步執行）。</p>
]]></content:encoded></item><item><title>教材的『重點 / 總結』段是內容發散的訊號、該重組正文不該補丁</title><link>https://tarrragon.github.io/blog/report/summary-section-signals-scattered-prose/</link><pubDate>Fri, 05 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/summary-section-signals-scattered-prose/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述源於 &lt;strong>1 個觸發 case&lt;/strong>（&lt;a href="../../work-log/git_stash_untracked/">git stash &lt;code>-u&lt;/code> 筆記&lt;/a>的 review、使用者指出尾端「重點」段沒有必要）、再以 &lt;strong>1 次 &lt;code>content/&lt;/code> 全站掃描&lt;/strong>（309 個總結型段落、Go 模組 53 章樣本、見下方「blog 樣本掃描」段）驗證與擴充。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>「重點段」是這次出現的形式、不是唯一形式&lt;/strong>：同類補丁還有「一句話總結」「TL;DR」「小結」「劃重點」。判準不在標題名稱、在「這段是否只是重述前文已講過的內容」。&lt;/li>
&lt;li>&lt;strong>不是所有 summary 都是補丁&lt;/strong>：長篇 / 多章模組的導覽型 summary（串連各章、給路由）有獨立價值、不適用本卡。本卡針對的是「單篇短文尾端重述自己」這種發散善後。&lt;/li>
&lt;li>&lt;strong>修補有效性未獨立驗證&lt;/strong>：刪掉總結段後讀起來更聚焦、但「有沒有總結段」跟「讀者實際記憶留存」之間沒做使用者測試。&lt;/li>
&lt;/ul>
&lt;p>讀者使用本卡時、先判斷該 summary 段是「重述前文」還是「跨段路由 / 導覽」—— 前者套用、後者保留。&lt;/p>
&lt;hr>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>教材把概念講清楚的責任落在正文、不落在尾端的總結段。&lt;/strong> 若一篇文章要靠「重點」段重述才能讓讀者記住、那訊號不是「需要總結」、是正文發散 —— 概念沒在它該出現的位置一次講清、被攤散在各段、所以尾端要再收一次。正確的回應是重組正文、不是補一個總結段替發散善後。&lt;/p>
&lt;p>判準很簡單：&lt;strong>刪掉總結段、看正文站不站得住。&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>站得住 → 總結段本就冗餘、刪掉是淨減負擔。&lt;/li>
&lt;li>站不住 → 問題在正文組織、該重拆段落、不是靠總結救。&lt;/li>
&lt;/ul>
&lt;p>兩種結果都指向「不該留總結段」。總結段唯一看似合理的存在理由（怕讀者沒記住），恰好是正文設計不佳的徵兆 —— 用補丁掩蓋了該修的結構。&lt;/p>
&lt;hr>
&lt;h2 id="處理總結段內容先分提醒-vs-概念">處理總結段內容：先分「提醒 vs 概念」&lt;/h2>
&lt;p>刪總結段的第一步是辨識段內每一條的性質，決定併回正文還是直接刪：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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;code>-u&lt;/code> 的習慣」「記得回頭確認」&lt;/td>
 &lt;td>刪 —— 提醒不傳遞新概念、讀者需要時自己回前文&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>有概念價值&lt;/td>
 &lt;td>「為何 Git 預設不收 untracked：因為常是編譯產物、log」&lt;/td>
 &lt;td>併回正文 —— 移到它本該所屬的概念段、一次講清&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>純重述&lt;/td>
 &lt;td>把表格 / 流程再用文字講一遍&lt;/td>
 &lt;td>刪 —— 跟前文重複、是發散的直接證據&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵動作是「&lt;strong>併回&lt;/strong>」而非「丟棄」：總結段裡常混著真正屬於正文卻被擠到尾端的概念（例如某設計選擇的理由）。把它移回該概念出現的段落、既刪了補丁、又補強了正文的「核心原則先行」。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="補丁掩蓋結構問題發散持續累積">補丁掩蓋結構問題、發散持續累積&lt;/h3>
&lt;p>留著總結段、等於接受「正文可以發散、尾端再收」。下一篇繼續發散、繼續補總結、文章組織能力不會進步。總結段是止痛藥、不是治療 —— 它讓「正文沒講清」這個真問題不痛、於是沒人去修。&lt;/p>
&lt;h3 id="讀者付兩次成本讀同一概念">讀者付兩次成本讀同一概念&lt;/h3>
&lt;p>重述型總結讓讀者讀第二遍已經懂的內容。懂的人覺得冗、沒懂的人靠重述也補不上（重述不會比正文講得更清）。兩種讀者都沒得到淨價值、只多付了 token。&lt;/p>
&lt;h3 id="概念價值被埋在補丁裡正文反而缺角">概念價值被埋在補丁裡、正文反而缺角&lt;/h3>
&lt;p>總結段常混著本該在正文的概念（設計理由、邊界條件）。塞在尾端、正文對應位置反而缺了這塊 —— 讀者讀到正文時概念不完整、要讀到最後才補上。這違反「核心原則先行」、把該前置的概念後置成總結。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../compose-feature-at-source-layer/">#64 Feature 操作要跟 Source 同層合成&lt;/a>&lt;/strong>：本卡是該原則在寫作層的同構。#64 講「filter / 操作要在 source 同層或更上游做、不在下游補」、本卡講「概念要在正文（source）講清、不在尾端總結（下游）補」。兩者共享「修在源頭、不在下游打補丁」的骨架 —— 總結段就是寫作版的 post-source patch。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../teaching-register-states-not-addresses-reader/">#150 教材用中性陳述、不對讀者喊話&lt;/a>&lt;/strong>：兩卡常在同一段命中、但軸不同。#150 是&lt;strong>字句層 / stance&lt;/strong>（「養成習慣」是祈使喊話）、本卡是&lt;strong>結構層&lt;/strong>（整個總結段是組織補丁）。一個總結段可能同時是 #150 的喊話載體跟本卡的結構補丁 —— 修法也不同：#150 改句子 register、本卡刪整段並重組正文。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../teaching-gives-reasons-not-quality-verdicts/">#151 教材給技術理由、不替方案下品質評價&lt;/a>&lt;/strong>：兩卡都在問「這段內容該不該留在教材」。#151 砍的是「自評誇飾」（不傳遞概念的品質 verdict）、本卡砍的是「重述總結」（不傳遞新概念的結構補丁）。共同判準：不貢獻新概念的內容、不論它讀起來多像收尾、都是負擔。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../review-miss-diagnose-design-vs-execution-gap/">#153 Review 漏抓先分 design gap 與 execution gap&lt;/a>&lt;/strong>：本卡的「刪總結 vs 重組正文」是 diagnose 先於修法的同類動作。看到總結段別直接刪了事 —— 先用「刪掉正文站不站得住」診斷：站得住是冗餘（execution-side、刪即可）、站不住是正文發散（design-side、要重組）。診斷錯就會「刪了總結、發散的正文還在」。&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>文章尾端有「重點 / 小結 / 一句話總結 / TL;DR」段&lt;/td>
 &lt;td>先問「這段是重述前文、還是跨段路由」—— 重述就是補丁候選&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>總結段每一條都能在前文找到對應&lt;/td>
 &lt;td>純重述、刪 —— 讀者需要時回前文即可&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>刪掉總結段後正文仍完整&lt;/td>
 &lt;td>證明總結冗餘、刪是淨減負擔&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>刪掉總結段後正文「少了關鍵概念」&lt;/td>
 &lt;td>不是總結要保、是那個概念該併回正文對應段落&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>總結段混著「養成習慣 / 記得 / 別忘了」&lt;/td>
 &lt;td>純提醒、刪 —— 提醒不是教材的責任（連 &lt;a href="../teaching-register-states-not-addresses-reader/">#150&lt;/a>）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>自問「沒有這段、讀者會看不懂嗎」答不會&lt;/td>
 &lt;td>補丁確認 —— 刪&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>總結段是「一段重述 + 一句下一章路由」&lt;/td>
 &lt;td>混合型 —— 外科式切重述段、留路由句、別整段刪&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>：單篇文章 / 卡片尾端「重述自己」的總結段 —— 重點、小結、一句話總結、劃重點、TL;DR。這些地方若只是把前文再講一遍、就是發散善後。&lt;/li>
&lt;li>&lt;strong>不適用&lt;/strong>：跨章模組 / 長篇的&lt;strong>導覽型 summary&lt;/strong>（串連各章、給下一步路由、列模組地圖）—— 它傳遞「結構關係」這個正文沒有的新資訊、不是重述。&lt;code>report/&lt;/code> 的 &lt;code>_index.md&lt;/code> 路由段、教學模組的章節導覽都屬此類。&lt;/li>
&lt;li>&lt;strong>邊界&lt;/strong>：判別線是「這段傳遞&lt;strong>新資訊（含結構 / 路由關係）&lt;/strong>、還是&lt;strong>重述已講過的內容&lt;/strong>」。前者保留、後者刪。長度不是判準 —— 短文也可能有合理的路由段、長文也可能塞冗餘總結。&lt;/li>
&lt;li>&lt;strong>位置反轉的例外：前置摘要不是尾端重述&lt;/strong>：放在文首的摘要（frontmatter &lt;code>description&lt;/code>、開頭一段 abstract）跟尾端重述性質相反 —— 它服務「讀者決定要不要讀、先建立全局框架」、在讀者&lt;strong>還沒讀正文時&lt;/strong>提供導航價值。尾端重述則是在讀者&lt;strong>讀完之後&lt;/strong>把已知內容再講一次、無導航功能。同樣一句「本文講 X 的三個取捨」、放文首是合理摘要、放文尾就是重述補丁。判別不只看「是否重述」、還看「相對正文的位置決定它服務的是導航還是回顧」。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="blog-樣本掃描三種變體與外科式修法">blog 樣本掃描：三種變體與外科式修法&lt;/h2>
&lt;p>對 &lt;code>content/&lt;/code> 掃「小結 / 總結 / 結論」當標題的段落、309 個檔案命中。Go 教學模組是密度最高的樣本：53 章每章一個 &lt;code>## 小結&lt;/code>、但只有 10 個含「下一章」路由、其餘 43 個是純重述章節核心原則。這不是偶發、是模組層級的系統性習慣 —— 也讓「總結段=補丁」這個判讀有了規模證據。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述源於 <strong>1 個觸發 case</strong>（<a href="../../work-log/git_stash_untracked/">git stash <code>-u</code> 筆記</a>的 review、使用者指出尾端「重點」段沒有必要）、再以 <strong>1 次 <code>content/</code> 全站掃描</strong>（309 個總結型段落、Go 模組 53 章樣本、見下方「blog 樣本掃描」段）驗證與擴充。具體限制：</p>
<ul>
<li><strong>「重點段」是這次出現的形式、不是唯一形式</strong>：同類補丁還有「一句話總結」「TL;DR」「小結」「劃重點」。判準不在標題名稱、在「這段是否只是重述前文已講過的內容」。</li>
<li><strong>不是所有 summary 都是補丁</strong>：長篇 / 多章模組的導覽型 summary（串連各章、給路由）有獨立價值、不適用本卡。本卡針對的是「單篇短文尾端重述自己」這種發散善後。</li>
<li><strong>修補有效性未獨立驗證</strong>：刪掉總結段後讀起來更聚焦、但「有沒有總結段」跟「讀者實際記憶留存」之間沒做使用者測試。</li>
</ul>
<p>讀者使用本卡時、先判斷該 summary 段是「重述前文」還是「跨段路由 / 導覽」—— 前者套用、後者保留。</p>
<hr>
<h2 id="核心原則">核心原則</h2>
<p><strong>教材把概念講清楚的責任落在正文、不落在尾端的總結段。</strong> 若一篇文章要靠「重點」段重述才能讓讀者記住、那訊號不是「需要總結」、是正文發散 —— 概念沒在它該出現的位置一次講清、被攤散在各段、所以尾端要再收一次。正確的回應是重組正文、不是補一個總結段替發散善後。</p>
<p>判準很簡單：<strong>刪掉總結段、看正文站不站得住。</strong></p>
<ul>
<li>站得住 → 總結段本就冗餘、刪掉是淨減負擔。</li>
<li>站不住 → 問題在正文組織、該重拆段落、不是靠總結救。</li>
</ul>
<p>兩種結果都指向「不該留總結段」。總結段唯一看似合理的存在理由（怕讀者沒記住），恰好是正文設計不佳的徵兆 —— 用補丁掩蓋了該修的結構。</p>
<hr>
<h2 id="處理總結段內容先分提醒-vs-概念">處理總結段內容：先分「提醒 vs 概念」</h2>
<p>刪總結段的第一步是辨識段內每一條的性質，決定併回正文還是直接刪：</p>
<table>
  <thead>
      <tr>
          <th>內容性質</th>
          <th>具體例子</th>
          <th>處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純提醒 / 喊話</td>
          <td>「開新功能要養成順手加 <code>-u</code> 的習慣」「記得回頭確認」</td>
          <td>刪 —— 提醒不傳遞新概念、讀者需要時自己回前文</td>
      </tr>
      <tr>
          <td>有概念價值</td>
          <td>「為何 Git 預設不收 untracked：因為常是編譯產物、log」</td>
          <td>併回正文 —— 移到它本該所屬的概念段、一次講清</td>
      </tr>
      <tr>
          <td>純重述</td>
          <td>把表格 / 流程再用文字講一遍</td>
          <td>刪 —— 跟前文重複、是發散的直接證據</td>
      </tr>
  </tbody>
</table>
<p>關鍵動作是「<strong>併回</strong>」而非「丟棄」：總結段裡常混著真正屬於正文卻被擠到尾端的概念（例如某設計選擇的理由）。把它移回該概念出現的段落、既刪了補丁、又補強了正文的「核心原則先行」。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="補丁掩蓋結構問題發散持續累積">補丁掩蓋結構問題、發散持續累積</h3>
<p>留著總結段、等於接受「正文可以發散、尾端再收」。下一篇繼續發散、繼續補總結、文章組織能力不會進步。總結段是止痛藥、不是治療 —— 它讓「正文沒講清」這個真問題不痛、於是沒人去修。</p>
<h3 id="讀者付兩次成本讀同一概念">讀者付兩次成本讀同一概念</h3>
<p>重述型總結讓讀者讀第二遍已經懂的內容。懂的人覺得冗、沒懂的人靠重述也補不上（重述不會比正文講得更清）。兩種讀者都沒得到淨價值、只多付了 token。</p>
<h3 id="概念價值被埋在補丁裡正文反而缺角">概念價值被埋在補丁裡、正文反而缺角</h3>
<p>總結段常混著本該在正文的概念（設計理由、邊界條件）。塞在尾端、正文對應位置反而缺了這塊 —— 讀者讀到正文時概念不完整、要讀到最後才補上。這違反「核心原則先行」、把該前置的概念後置成總結。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../compose-feature-at-source-layer/">#64 Feature 操作要跟 Source 同層合成</a></strong>：本卡是該原則在寫作層的同構。#64 講「filter / 操作要在 source 同層或更上游做、不在下游補」、本卡講「概念要在正文（source）講清、不在尾端總結（下游）補」。兩者共享「修在源頭、不在下游打補丁」的骨架 —— 總結段就是寫作版的 post-source patch。</li>
<li><strong><a href="../teaching-register-states-not-addresses-reader/">#150 教材用中性陳述、不對讀者喊話</a></strong>：兩卡常在同一段命中、但軸不同。#150 是<strong>字句層 / stance</strong>（「養成習慣」是祈使喊話）、本卡是<strong>結構層</strong>（整個總結段是組織補丁）。一個總結段可能同時是 #150 的喊話載體跟本卡的結構補丁 —— 修法也不同：#150 改句子 register、本卡刪整段並重組正文。</li>
<li><strong><a href="../teaching-gives-reasons-not-quality-verdicts/">#151 教材給技術理由、不替方案下品質評價</a></strong>：兩卡都在問「這段內容該不該留在教材」。#151 砍的是「自評誇飾」（不傳遞概念的品質 verdict）、本卡砍的是「重述總結」（不傳遞新概念的結構補丁）。共同判準：不貢獻新概念的內容、不論它讀起來多像收尾、都是負擔。</li>
<li><strong><a href="../review-miss-diagnose-design-vs-execution-gap/">#153 Review 漏抓先分 design gap 與 execution gap</a></strong>：本卡的「刪總結 vs 重組正文」是 diagnose 先於修法的同類動作。看到總結段別直接刪了事 —— 先用「刪掉正文站不站得住」診斷：站得住是冗餘（execution-side、刪即可）、站不住是正文發散（design-side、要重組）。診斷錯就會「刪了總結、發散的正文還在」。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>文章尾端有「重點 / 小結 / 一句話總結 / TL;DR」段</td>
          <td>先問「這段是重述前文、還是跨段路由」—— 重述就是補丁候選</td>
      </tr>
      <tr>
          <td>總結段每一條都能在前文找到對應</td>
          <td>純重述、刪 —— 讀者需要時回前文即可</td>
      </tr>
      <tr>
          <td>刪掉總結段後正文仍完整</td>
          <td>證明總結冗餘、刪是淨減負擔</td>
      </tr>
      <tr>
          <td>刪掉總結段後正文「少了關鍵概念」</td>
          <td>不是總結要保、是那個概念該併回正文對應段落</td>
      </tr>
      <tr>
          <td>總結段混著「養成習慣 / 記得 / 別忘了」</td>
          <td>純提醒、刪 —— 提醒不是教材的責任（連 <a href="../teaching-register-states-not-addresses-reader/">#150</a>）</td>
      </tr>
      <tr>
          <td>自問「沒有這段、讀者會看不懂嗎」答不會</td>
          <td>補丁確認 —— 刪</td>
      </tr>
      <tr>
          <td>總結段是「一段重述 + 一句下一章路由」</td>
          <td>混合型 —— 外科式切重述段、留路由句、別整段刪</td>
      </tr>
      <tr>
          <td>同一模組每章都有結構雷同的小結</td>
          <td>系統性補丁 —— 在模組層級統一定義小結責任、別逐章判</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：單篇文章 / 卡片尾端「重述自己」的總結段 —— 重點、小結、一句話總結、劃重點、TL;DR。這些地方若只是把前文再講一遍、就是發散善後。</li>
<li><strong>不適用</strong>：跨章模組 / 長篇的<strong>導覽型 summary</strong>（串連各章、給下一步路由、列模組地圖）—— 它傳遞「結構關係」這個正文沒有的新資訊、不是重述。<code>report/</code> 的 <code>_index.md</code> 路由段、教學模組的章節導覽都屬此類。</li>
<li><strong>邊界</strong>：判別線是「這段傳遞<strong>新資訊（含結構 / 路由關係）</strong>、還是<strong>重述已講過的內容</strong>」。前者保留、後者刪。長度不是判準 —— 短文也可能有合理的路由段、長文也可能塞冗餘總結。</li>
<li><strong>位置反轉的例外：前置摘要不是尾端重述</strong>：放在文首的摘要（frontmatter <code>description</code>、開頭一段 abstract）跟尾端重述性質相反 —— 它服務「讀者決定要不要讀、先建立全局框架」、在讀者<strong>還沒讀正文時</strong>提供導航價值。尾端重述則是在讀者<strong>讀完之後</strong>把已知內容再講一次、無導航功能。同樣一句「本文講 X 的三個取捨」、放文首是合理摘要、放文尾就是重述補丁。判別不只看「是否重述」、還看「相對正文的位置決定它服務的是導航還是回顧」。</li>
</ul>
<hr>
<h2 id="blog-樣本掃描三種變體與外科式修法">blog 樣本掃描：三種變體與外科式修法</h2>
<p>對 <code>content/</code> 掃「小結 / 總結 / 結論」當標題的段落、309 個檔案命中。Go 教學模組是密度最高的樣本：53 章每章一個 <code>## 小結</code>、但只有 10 個含「下一章」路由、其餘 43 個是純重述章節核心原則。這不是偶發、是模組層級的系統性習慣 —— 也讓「總結段=補丁」這個判讀有了規模證據。</p>
<p>樣本分成三種變體、各自修法不同：</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>真實樣本</th>
          <th>性質</th>
          <th>修法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純重述型</td>
          <td><code>channel.md</code>「channel 的重點是資料流、同步點與所有權邊界」、<code>interfaces.md</code>「Go interface 的核心是用行為定義依賴」</td>
          <td>整段重述正文已建立的核心原則、無路由、無新資訊</td>
          <td>刪或重組正文（本卡典型對象）</td>
      </tr>
      <tr>
          <td>重述 + 路由混合型</td>
          <td><code>control-flow.md</code>：一段重述（控制流程刻意維持少量語法）+ 一句路由（下一章回到 package）</td>
          <td>一段補丁包著一句合理路由</td>
          <td>外科式：切重述段、留路由句</td>
      </tr>
      <tr>
          <td>綜合關係型</td>
          <td><code>llm/application-protocols.md</code>「Function calling 是模型能力、structured output 是 sampling 約束、MCP 是 server 協議 —— 三者層級不同、組合使用而非競爭」</td>
          <td>把正文分散講過的多個概念並置成一個關係 frame</td>
          <td>語意判定：正文若從未在一句並置這個關係、屬新結構資訊、保留</td>
      </tr>
  </tbody>
</table>
<p>兩個從樣本提煉的補充、修正了「整段刪」的過度簡化：</p>
<ul>
<li>
<p><strong>真實世界最常見的是混合型、不是純補丁</strong>：一段重述包著一句路由。對混合型套用本卡、修法是<strong>外科式</strong>（切重述、留路由 / 綜合關係）、不是整段刪。判別線下沉到「段內每一句」、不是「整段留或刪」。</p>
</li>
<li>
<p><strong>系統性出現時在模組層級統一決定、不逐章補丁</strong>：當整個模組每章都有小結（Go 53 章），逐章判斷會反覆做同一決定。該在模組層級先定義「小結的責任」（只放跨章路由 / 跨章綜合、不放單章重述）、再一次套到全模組 —— 否則就是本卡反對的「為發散補補丁」在模組尺度重演。</p>
<blockquote>
<p><strong>升格條件（候選獨立卡）</strong>：「smell 系統性出現 → 在模組 / 政策層級統一修、不逐實例補丁」這條、語意上正交於「總結=發散」、且可泛化到 cadence 同骨化（<a href="../cadence-homogenization-in-batch-writing/">#122</a>）、emoji、任何系統性寫作 smell —— 是 <a href="../compose-feature-at-source-layer/">#64</a>「修在 source」往「修法尺度要匹配問題尺度」的泛化。目前只有 <strong>1 個 instance</strong>（Go 小結）、按 <a href="../two-occurrence-threshold/">#42 兩次門檻</a>暫不抽卡（避免過早抽象 / framework bloat）。當第二個系統性寫作 smell 出現同樣「逐實例 vs 模組政策」張力時、即有 2 instance、抽成獨立卡。</p></blockquote>
</li>
<li>
<p><strong>綜合關係型是導覽型例外的近親、但要語意驗證</strong>：「三者層級不同」這種並置、若正文從未在同一處講過這個關係、就是新資訊（傳遞結構）、不是重述。判別問「這句陳述的關係、正文有沒有在某段一次講過」—— 沒有則保留、有則仍是重述。</p>
</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於 review <a href="../../work-log/git_stash_untracked/">git stash <code>-u</code> 筆記</a> 時、由使用者指出尾端「重點」段沒有必要：</p>
<blockquote>
<p>重點這一塊是沒有必要的、如果讀者需要他可以自己回頭確認、不用預設讀者需要重新提醒。如果我們的文章一定要寫重點才能讓讀者記住、表示我們的文章內容太過發散、這時候要考慮的是重新拆分組織文章內容、而不是為了自己文章的設計不佳又多補一個重點章節。</p></blockquote>
<p>該「重點」段有三條：</p>
<ol>
<li><strong>「開新功能幾乎一定有 untracked 檔案、要養成順手加 <code>-u</code> 的習慣」</strong> —— 純提醒（養成習慣）、且跟「問題情境」段已講的重複。刪。</li>
<li><strong>「為何 Git 預設不收 untracked」</strong> —— 有概念價值、解釋了 <code>-u</code> 為何要明確表態。併回「<code>-u</code> 是什麼」段、放在表格之後、讓設計意圖在概念位置一次講清。</li>
<li><strong>「記憶法：<code>-u</code> = untracked、<code>-a</code> = …」</strong> —— 跟表格重複的重述。刪、把 <code>-a</code> 的範圍差異併進前述設計意圖段。</li>
</ol>
<p>刪掉「重點」段後、正文（問題情境 → <code>-u</code> 是什麼含設計意圖 → 正確流程 → 替代做法取捨）仍完整、且因為概念併回正文反而更聚焦 —— 證明總結段本就是補丁、不是必要結構。</p>
<p>對應本卡：總結段的存在價值（怕讀者沒記住）恰好是正文發散的徵兆 —— 修法不是保留總結、是重組正文、把該前置的概念前置、該刪的提醒刪掉。</p>
]]></content:encoded></item><item><title>register 違規：偵測可機械化、判定要靠文體異源的眼睛</title><link>https://tarrragon.github.io/blog/report/register-violation-needs-cross-style-eyes/</link><pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/register-violation-needs-cross-style-eyes/</guid><description>&lt;h2 id="結論">結論&lt;/h2>
&lt;p>寫作規範的違規分兩類、判定性質根本不同。形式違規（emoji、編號、broken link、裸 URL、frontmatter 缺欄）可完全機械判定、命中即違規、該進工具鏈。register / 品味違規（核心概念前置、否定起手、喊話、誇飾、口語修辭）的判定有不可消除的品味核心、偵測可機械化但判定不可。&lt;/p>
&lt;p>「不是 X、而是 Y」是 register 違規裡最隱蔽的一種、因為它的偵測可機械化（句型明顯、grep 抓得到）、這個「偵測可機械化」偽裝成「判定也可機械化」。被這個偽裝誤導、就會無限投入更精緻的判定方法（補 grep → 概念位置判準 → 行為測試）、而判定（這個否定在建立概念還是做對照）本質是品味判斷、始終在品味側、始終放水。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>後續校正（見 &lt;a href="../lead-with-the-point-cross-language/">#166 重點優先陳述是跨語言的資訊結構原則&lt;/a>）&lt;/strong>：「不是 X、而是 Y」這個子集後來被釐清為資訊結構問題（重點後置）、不是純品味 —— 判定其實可操作（核心概念第一次正面出現在不在句首）、主解是強制執行重點位置判準、異源視角降為補充。本卡論的「品味核心 / 同源上限 / 異源為真防線」對喊話、誇飾這類無單一重點位置的 register 仍成立、但對「重點優先」這個可操作子集是過度推論。&lt;/p>&lt;/blockquote>
&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>emoji、編號、broken link、frontmatter&lt;/td>
 &lt;td>確定性、命中即違規&lt;/td>
 &lt;td>工具鏈 lint&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>register 違規&lt;/td>
 &lt;td>概念前置、否定起手、喊話、誇飾、口語&lt;/td>
 &lt;td>有不可消除的品味核心&lt;/td>
 &lt;td>文體異源視角 + 工具鏈曝光&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="為什麼-register-違規的判定不可機械化">為什麼 register 違規的判定不可機械化&lt;/h2>
&lt;p>判定要回答「這個句子讀起來對不對」、這是品味問題、品味需要一個會讀的主體去感受、沒有可機械化的判準能取代。「不是 X、而是 Y」的判定要區分兩種角色：&lt;/p>
&lt;ul>
&lt;li>建立核心概念的否定（違規）：「外包一塊能力&lt;strong>不是&lt;/strong>二元、&lt;strong>而是&lt;/strong>有深度的」—— 核心概念「有深度」被擠到「而是」之後、句首先丟一個被否定的錯誤理解。&lt;/li>
&lt;li>反例對照的否定（合規）：在明示反例段落裡、否定就是對照本體（見 &lt;a href="../positive-rewrite-preserves-contrast/">#94&lt;/a>）。&lt;/li>
&lt;/ul>
&lt;p>兩者 grep 命中長得一樣、語意角色相反。要判對、reviewer 得讀懂段落結構、感受核心概念的位置 —— 這是品味判斷。任何想把它機械化的嘗試都只是換個地方做品味判斷：「概念位置判準」要判斷哪句是概念句、「刪除測試」要判斷剩下的概念完不完整、終點都回到「這讀起來對不對」。偵測的可機械化掩蓋了這個事實。&lt;/p>
&lt;hr>
&lt;h2 id="同源自審的結構上限">同源自審的結構上限&lt;/h2>
&lt;p>更深一層的原因、解釋了為什麼再多輪 LLM 審查都跨不過：產出 register 違規的主體跟審查它的主體共享同一套文體直覺。「不是 X、而是 Y」是 LLM 高頻自產的定義句型、LLM reviewer 讀到它「讀起來自然、權威」、違規感不觸發 —— 作者的盲區跟 reviewer 的盲區是同一個。&lt;/p>
&lt;p>這讓 register 違規的同源自審有結構上限。加 reviewer 數量、加審查輪次、換 frame、都在同一套文體直覺內打轉、跨不過盲區。要看出 register 違規、需要一雙「不共享作者文體」的眼睛。&lt;/p>
&lt;p>這條上限是 &lt;a href="../keyword-bank-hit-is-candidate-not-verdict/">#149&lt;/a>（命中後判定會放水）跟 &lt;a href="../rule-codification-vs-self-audit/">#147&lt;/a>（立規範不等於自審執行）的共同根因：#147 的修法是「立規範當下轉 grep + sweep」、#149 的修法是「命中後用概念位置判定」、兩個修法都還在自動化側、對 register 違規都攔不住、因為判定的品味核心要異源的眼睛才感受得到。&lt;/p>
&lt;hr>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>把違規先分類、再配對應的防線。&lt;/p>
&lt;h3 id="第一步分類--這個違規在哪一側">第一步：分類 —— 這個違規在哪一側&lt;/h3>
&lt;p>問一個判別問題：「這條規則的判定、是命中即違規（確定性）、還是要讀懂句子讀起來對不對（品味）？」確定性的進工具鏈、品味的進異源審查。emoji、編號、broken link 在確定性側；概念前置、否定起手、喊話、誇飾在品味側。&lt;/p>
&lt;h3 id="第二步register-違規--偵測機械化判定靠異源">第二步：register 違規 —— 偵測機械化、判定靠異源&lt;/h3>
&lt;p>偵測仍用 grep、但定位是「曝光候選給異源視角抽查」、產出不是「自動判定違規」。判定交給文體異源的眼睛：&lt;/p>
&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>作者以外的人讀、register 違規對非作者最刺眼（本卡就是這樣抓到的）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>reader-simulation&lt;/td>
 &lt;td>刻意換一個讀者視角讀每句「這句給新資訊、還是文體慣性」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>對抗文體 reviewer&lt;/td>
 &lt;td>prompt 明確要求 reviewer 採「挑剔否定起手 / 概念後置」的對抗姿態、抵銷同源文體慣性&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="第三步接受-100-自動-catch-不可能">第三步：接受 100% 自動 catch 不可能&lt;/h3>
&lt;p>把 register 違規的審查目標設成「曝光候選 + 異源抽查」、而不是「自動判定 clean」。回報時誠實標「register 層靠異源抽查、未做窮舉自動判定」、不把同源自審的 clean 當成真 clean。&lt;/p>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="在錯的一側無限用力">在錯的一側無限用力&lt;/h3>
&lt;p>把 register 違規當成自動化側問題、就會持續投入「更好的檢查方法」（補 grep、寫判準、做測試）、每次都改進一點、每次都還是放水 —— 因為判定始終在品味側。投入的努力跟結果脫節、看起來在進步、實際在原地。&lt;/p>
&lt;h3 id="同源-clean-製造虛假信心">同源 clean 製造虛假信心&lt;/h3>
&lt;p>跑完多輪 LLM 審查、回報「字句層 clean」、這個 clean 是同源盲區的產物、不是真 clean。比沒審更危險：沒審還知道沒查、同源審完誤以為查過了、register 違規帶著「已審查」標籤留在稿件裡。&lt;/p>
&lt;h3 id="規範卡越多越以為夠了">規範卡越多、越以為夠了&lt;/h3>
&lt;p>blog 累積了 #94 / #147 / #149 一整套 register 審查原則、看起來防護很完整、反而讓人以為「照卡片做就夠」。這次的失敗證明：原則齊備、修法齊備、同源執行仍跨不過上限。原則的數量不等於防線的強度。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="../keyword-bank-hit-is-candidate-not-verdict/">#149 字句層 review：keyword bank 命中是候選、不是判決&lt;/a>&lt;/strong>：#149 揭露「命中後判定會放水」這個現象、本卡是它的上層 —— 揭露放水的根因（判定在品味側、同源自審有結構上限）跟結構解（異源視角、不是更好的判定準則）。#149 的「概念位置判準」是好的判準、但它仍要同源 reviewer 執行品味判斷、本卡指出這一步有上限。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../rule-codification-vs-self-audit/">#147 規範化跟自審是兩種認知任務&lt;/a>&lt;/strong>：#147 講「立規範不等於自審執行」、修法是轉 grep + sweep。本卡補它沒覆蓋的：對 register 違規、grep + sweep 命中了、判定仍跨不過同源盲區。#147 解「自審有沒有做」、本卡解「自審做了、為什麼對 register 仍失效」。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精修&lt;/a>&lt;/strong>：本卡把 #82 的「字面 vs 行為」推到極限 —— 對 register 違規、連「行為精修」（讀者能不能驗證）都還是品味判斷、需要異源的讀者才感受得到。形式違規停在字面層即可、register 違規連行為層都需要異源。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass review scope 要蓋同類風險區&lt;/a>&lt;/strong>：#95 解 scope 軸（同類違規要 corpus-wide grep）、本卡解 source 軸（同類違規的判定要文體異源）。兩個一起才完整：grep 把候選掃出來（#95）、異源的眼睛判它違不違規（本卡）。這次三個 surface 鏡像內容共享同一違規句型、grep 掃得到、但同源判定全放行 —— scope 對了、source 沒換。&lt;/li>
&lt;li>&lt;strong>&lt;a href="../multi-pass-review-frame-granularity-blindspot/">#114 Multi-pass review 的 frame 顆粒度盲點&lt;/a>&lt;/strong>：#114 解偵測層（展開成 keyword bank）、本卡指出對 register 違規、偵測層做好了、判定層仍需異源 —— frame 顆粒度再細、同源 reviewer 對品味違規仍有盲區。&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>對某個寫作違規、一直在「換更好的檢查方法」（補 grep / 寫判準 / 做測試）&lt;/td>
 &lt;td>停 —— 先問它在品味側還形式側、品味側的解是換 source、不是換 method&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>一個違規「偵測明顯（grep 抓得到）」但「判定要讀懂語意」&lt;/td>
 &lt;td>偵測可機械化、判定在品味側、別把偵測的容易誤當判定的容易&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>多輪 LLM 審查全 clean、但作者以外的人一眼看到違規&lt;/td>
 &lt;td>同源盲區的 retro signal、這類違規需要文體異源視角&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>reviewer 全是 LLM、prompt 全是「自然語言判準」&lt;/td>
 &lt;td>register 層缺異源防線、補人類冷讀或對抗文體 reviewer&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>回報「字句層 clean」、但只跑了同源 reviewer&lt;/td>
 &lt;td>這個 clean 可能是同源盲區產物、標「register 層未經異源抽查」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="適用範圍與邊界">適用範圍與邊界&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>適用&lt;/strong>：register / 品味類寫作規範（正向陳述、概念前置、喊話、誇飾、口語修辭、文體）的 review 流程設計；AI 輔助寫作的 self-review（最容易在 register 層同源放水）；multi-round-review 的 frame 與資源配置。&lt;/li>
&lt;li>&lt;strong>不適用&lt;/strong>：形式違規（emoji、編號、broken link、frontmatter）—— 這類確定性判定、進工具鏈即可、不需異源、本卡的「同源上限」不適用。&lt;/li>
&lt;li>&lt;strong>邊界&lt;/strong>：「同源自審有上限」不等於「同源自審無用」 —— 同源 reviewer 仍能抓形式違規、抓部分明顯的 register 違規；上限指的是「對 register 違規無法做到窮舉可靠」、所以要補異源、不是廢掉同源。也不等於「只能靠人」 —— 偵測機械化、對抗文體 reviewer、reader-simulation 都能降低對純人工的依賴、只是接受殘餘要異源抽查。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源&lt;/h2>
&lt;p>本卡觸發於一次 backend 章節 + skill 的四輪 multi-round-review。流程是 12 個 LLM reviewer、4 輪、frame 涵蓋規範遵循 / 技術 / 一致性 / cadence / reader-simulation / title / self-application / steelman / outbound / cold-read / misuse / regression。Round 1-A 與 Round 3-A 都跑了 &lt;code>compositional-writing&lt;/code> 的正向陳述 grep keyword bank、命中了三個 surface 的「不是 X、而是 Y」、全部判成「合規對照」放行、回報「字句層 clean」。&lt;/p></description><content:encoded><![CDATA[<h2 id="結論">結論</h2>
<p>寫作規範的違規分兩類、判定性質根本不同。形式違規（emoji、編號、broken link、裸 URL、frontmatter 缺欄）可完全機械判定、命中即違規、該進工具鏈。register / 品味違規（核心概念前置、否定起手、喊話、誇飾、口語修辭）的判定有不可消除的品味核心、偵測可機械化但判定不可。</p>
<p>「不是 X、而是 Y」是 register 違規裡最隱蔽的一種、因為它的偵測可機械化（句型明顯、grep 抓得到）、這個「偵測可機械化」偽裝成「判定也可機械化」。被這個偽裝誤導、就會無限投入更精緻的判定方法（補 grep → 概念位置判準 → 行為測試）、而判定（這個否定在建立概念還是做對照）本質是品味判斷、始終在品味側、始終放水。</p>
<blockquote>
<p><strong>後續校正（見 <a href="../lead-with-the-point-cross-language/">#166 重點優先陳述是跨語言的資訊結構原則</a>）</strong>：「不是 X、而是 Y」這個子集後來被釐清為資訊結構問題（重點後置）、不是純品味 —— 判定其實可操作（核心概念第一次正面出現在不在句首）、主解是強制執行重點位置判準、異源視角降為補充。本卡論的「品味核心 / 同源上限 / 異源為真防線」對喊話、誇飾這類無單一重點位置的 register 仍成立、但對「重點優先」這個可操作子集是過度推論。</p></blockquote>
<table>
  <thead>
      <tr>
          <th>違規類型</th>
          <th>例子</th>
          <th>判定性質</th>
          <th>防線</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>形式違規</td>
          <td>emoji、編號、broken link、frontmatter</td>
          <td>確定性、命中即違規</td>
          <td>工具鏈 lint</td>
      </tr>
      <tr>
          <td>register 違規</td>
          <td>概念前置、否定起手、喊話、誇飾、口語</td>
          <td>有不可消除的品味核心</td>
          <td>文體異源視角 + 工具鏈曝光</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="為什麼-register-違規的判定不可機械化">為什麼 register 違規的判定不可機械化</h2>
<p>判定要回答「這個句子讀起來對不對」、這是品味問題、品味需要一個會讀的主體去感受、沒有可機械化的判準能取代。「不是 X、而是 Y」的判定要區分兩種角色：</p>
<ul>
<li>建立核心概念的否定（違規）：「外包一塊能力<strong>不是</strong>二元、<strong>而是</strong>有深度的」—— 核心概念「有深度」被擠到「而是」之後、句首先丟一個被否定的錯誤理解。</li>
<li>反例對照的否定（合規）：在明示反例段落裡、否定就是對照本體（見 <a href="../positive-rewrite-preserves-contrast/">#94</a>）。</li>
</ul>
<p>兩者 grep 命中長得一樣、語意角色相反。要判對、reviewer 得讀懂段落結構、感受核心概念的位置 —— 這是品味判斷。任何想把它機械化的嘗試都只是換個地方做品味判斷：「概念位置判準」要判斷哪句是概念句、「刪除測試」要判斷剩下的概念完不完整、終點都回到「這讀起來對不對」。偵測的可機械化掩蓋了這個事實。</p>
<hr>
<h2 id="同源自審的結構上限">同源自審的結構上限</h2>
<p>更深一層的原因、解釋了為什麼再多輪 LLM 審查都跨不過：產出 register 違規的主體跟審查它的主體共享同一套文體直覺。「不是 X、而是 Y」是 LLM 高頻自產的定義句型、LLM reviewer 讀到它「讀起來自然、權威」、違規感不觸發 —— 作者的盲區跟 reviewer 的盲區是同一個。</p>
<p>這讓 register 違規的同源自審有結構上限。加 reviewer 數量、加審查輪次、換 frame、都在同一套文體直覺內打轉、跨不過盲區。要看出 register 違規、需要一雙「不共享作者文體」的眼睛。</p>
<p>這條上限是 <a href="../keyword-bank-hit-is-candidate-not-verdict/">#149</a>（命中後判定會放水）跟 <a href="../rule-codification-vs-self-audit/">#147</a>（立規範不等於自審執行）的共同根因：#147 的修法是「立規範當下轉 grep + sweep」、#149 的修法是「命中後用概念位置判定」、兩個修法都還在自動化側、對 register 違規都攔不住、因為判定的品味核心要異源的眼睛才感受得到。</p>
<hr>
<h2 id="理想做法">理想做法</h2>
<p>把違規先分類、再配對應的防線。</p>
<h3 id="第一步分類--這個違規在哪一側">第一步：分類 —— 這個違規在哪一側</h3>
<p>問一個判別問題：「這條規則的判定、是命中即違規（確定性）、還是要讀懂句子讀起來對不對（品味）？」確定性的進工具鏈、品味的進異源審查。emoji、編號、broken link 在確定性側；概念前置、否定起手、喊話、誇飾在品味側。</p>
<h3 id="第二步register-違規--偵測機械化判定靠異源">第二步：register 違規 —— 偵測機械化、判定靠異源</h3>
<p>偵測仍用 grep、但定位是「曝光候選給異源視角抽查」、產出不是「自動判定違規」。判定交給文體異源的眼睛：</p>
<table>
  <thead>
      <tr>
          <th>異源來源</th>
          <th>怎麼用</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>人類冷讀</td>
          <td>作者以外的人讀、register 違規對非作者最刺眼（本卡就是這樣抓到的）</td>
      </tr>
      <tr>
          <td>reader-simulation</td>
          <td>刻意換一個讀者視角讀每句「這句給新資訊、還是文體慣性」</td>
      </tr>
      <tr>
          <td>對抗文體 reviewer</td>
          <td>prompt 明確要求 reviewer 採「挑剔否定起手 / 概念後置」的對抗姿態、抵銷同源文體慣性</td>
      </tr>
  </tbody>
</table>
<h3 id="第三步接受-100-自動-catch-不可能">第三步：接受 100% 自動 catch 不可能</h3>
<p>把 register 違規的審查目標設成「曝光候選 + 異源抽查」、而不是「自動判定 clean」。回報時誠實標「register 層靠異源抽查、未做窮舉自動判定」、不把同源自審的 clean 當成真 clean。</p>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="在錯的一側無限用力">在錯的一側無限用力</h3>
<p>把 register 違規當成自動化側問題、就會持續投入「更好的檢查方法」（補 grep、寫判準、做測試）、每次都改進一點、每次都還是放水 —— 因為判定始終在品味側。投入的努力跟結果脫節、看起來在進步、實際在原地。</p>
<h3 id="同源-clean-製造虛假信心">同源 clean 製造虛假信心</h3>
<p>跑完多輪 LLM 審查、回報「字句層 clean」、這個 clean 是同源盲區的產物、不是真 clean。比沒審更危險：沒審還知道沒查、同源審完誤以為查過了、register 違規帶著「已審查」標籤留在稿件裡。</p>
<h3 id="規範卡越多越以為夠了">規範卡越多、越以為夠了</h3>
<p>blog 累積了 #94 / #147 / #149 一整套 register 審查原則、看起來防護很完整、反而讓人以為「照卡片做就夠」。這次的失敗證明：原則齊備、修法齊備、同源執行仍跨不過上限。原則的數量不等於防線的強度。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../keyword-bank-hit-is-candidate-not-verdict/">#149 字句層 review：keyword bank 命中是候選、不是判決</a></strong>：#149 揭露「命中後判定會放水」這個現象、本卡是它的上層 —— 揭露放水的根因（判定在品味側、同源自審有結構上限）跟結構解（異源視角、不是更好的判定準則）。#149 的「概念位置判準」是好的判準、但它仍要同源 reviewer 執行品味判斷、本卡指出這一步有上限。</li>
<li><strong><a href="../rule-codification-vs-self-audit/">#147 規範化跟自審是兩種認知任務</a></strong>：#147 講「立規範不等於自審執行」、修法是轉 grep + sweep。本卡補它沒覆蓋的：對 register 違規、grep + sweep 命中了、判定仍跨不過同源盲區。#147 解「自審有沒有做」、本卡解「自審做了、為什麼對 register 仍失效」。</li>
<li><strong><a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精修</a></strong>：本卡把 #82 的「字面 vs 行為」推到極限 —— 對 register 違規、連「行為精修」（讀者能不能驗證）都還是品味判斷、需要異源的讀者才感受得到。形式違規停在字面層即可、register 違規連行為層都需要異源。</li>
<li><strong><a href="../multi-pass-scope-must-cover-risk-zone/">#95 Multi-pass review scope 要蓋同類風險區</a></strong>：#95 解 scope 軸（同類違規要 corpus-wide grep）、本卡解 source 軸（同類違規的判定要文體異源）。兩個一起才完整：grep 把候選掃出來（#95）、異源的眼睛判它違不違規（本卡）。這次三個 surface 鏡像內容共享同一違規句型、grep 掃得到、但同源判定全放行 —— scope 對了、source 沒換。</li>
<li><strong><a href="../multi-pass-review-frame-granularity-blindspot/">#114 Multi-pass review 的 frame 顆粒度盲點</a></strong>：#114 解偵測層（展開成 keyword bank）、本卡指出對 register 違規、偵測層做好了、判定層仍需異源 —— frame 顆粒度再細、同源 reviewer 對品味違規仍有盲區。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>對某個寫作違規、一直在「換更好的檢查方法」（補 grep / 寫判準 / 做測試）</td>
          <td>停 —— 先問它在品味側還形式側、品味側的解是換 source、不是換 method</td>
      </tr>
      <tr>
          <td>一個違規「偵測明顯（grep 抓得到）」但「判定要讀懂語意」</td>
          <td>偵測可機械化、判定在品味側、別把偵測的容易誤當判定的容易</td>
      </tr>
      <tr>
          <td>多輪 LLM 審查全 clean、但作者以外的人一眼看到違規</td>
          <td>同源盲區的 retro signal、這類違規需要文體異源視角</td>
      </tr>
      <tr>
          <td>reviewer 全是 LLM、prompt 全是「自然語言判準」</td>
          <td>register 層缺異源防線、補人類冷讀或對抗文體 reviewer</td>
      </tr>
      <tr>
          <td>回報「字句層 clean」、但只跑了同源 reviewer</td>
          <td>這個 clean 可能是同源盲區產物、標「register 層未經異源抽查」</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：register / 品味類寫作規範（正向陳述、概念前置、喊話、誇飾、口語修辭、文體）的 review 流程設計；AI 輔助寫作的 self-review（最容易在 register 層同源放水）；multi-round-review 的 frame 與資源配置。</li>
<li><strong>不適用</strong>：形式違規（emoji、編號、broken link、frontmatter）—— 這類確定性判定、進工具鏈即可、不需異源、本卡的「同源上限」不適用。</li>
<li><strong>邊界</strong>：「同源自審有上限」不等於「同源自審無用」 —— 同源 reviewer 仍能抓形式違規、抓部分明顯的 register 違規；上限指的是「對 register 違規無法做到窮舉可靠」、所以要補異源、不是廢掉同源。也不等於「只能靠人」 —— 偵測機械化、對抗文體 reviewer、reader-simulation 都能降低對純人工的依賴、只是接受殘餘要異源抽查。</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於一次 backend 章節 + skill 的四輪 multi-round-review。流程是 12 個 LLM reviewer、4 輪、frame 涵蓋規範遵循 / 技術 / 一致性 / cadence / reader-simulation / title / self-application / steelman / outbound / cold-read / misuse / regression。Round 1-A 與 Round 3-A 都跑了 <code>compositional-writing</code> 的正向陳述 grep keyword bank、命中了三個 surface 的「不是 X、而是 Y」、全部判成「合規對照」放行、回報「字句層 clean」。</p>
<p>四輪結束、三個 PR 合併之後、使用者讀稿件、一眼指出「外包一塊能力<strong>不是</strong>二元、<strong>而是</strong>有深度的」是否定句型 + 概念後置違規。同一個違規在 0.22 章節、知識卡、skill principle 卡三個 surface 都存在、12 個 LLM reviewer 全漏、使用者一眼抓到。</p>
<p>對應本卡：register 違規的判定在品味側、12 個 LLM reviewer 共享文體直覺、同源自審跨不過盲區；使用者是文體異源的眼睛、所以一眼看到。這次失敗證明 #147 的「轉 grep + sweep」、#149 的「概念位置判定」、補 grep keyword bank —— 三個自動化側的修法疊起來、對 register 違規仍跨不過同源上限。結構解是把異源視角寫進流程、不是再疊第四個自動化側修法。</p>
]]></content:encoded></item><item><title>重點優先陳述是跨語言的資訊結構原則、不是中文句型問題</title><link>https://tarrragon.github.io/blog/report/lead-with-the-point-cross-language/</link><pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/lead-with-the-point-cross-language/</guid><description>&lt;h2 id="結論">結論&lt;/h2>
&lt;p>正向陳述優先的本質是資訊結構效率：讀者拿到核心概念的認知步驟越少越好。「不是 X、而是 Y」表達能力差、是因為它讓讀者先處理一個被否定的錯誤理解 X、才拿到正確的 Y —— 重點後置、多繞一步。問題的根本在資訊結構、不在中文特有的句型、也不在主觀品味。&lt;/p>
&lt;p>這個校正很重要、因為它決定了解法的方向：把問題定位成「中文句型」、會去抓句型變體或換語言；定位成「品味」、會去靠主觀判定或異源視角；定位成「資訊結構效率」、才會去檢查「核心概念在不在最前」這個跨語言、可操作的判準。&lt;/p>
&lt;hr>
&lt;h2 id="證偽過的反例假設換語言能打破">證偽過的反例假設：「換語言能打破」&lt;/h2>
&lt;p>一個自然的假設：如果「不是 X、而是 Y」是 LLM 中文訓練語料的高頻行為、那換英文或日文思考就能打破。這個假設值得驗、但證偽了。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>不是 X、而是 Y&lt;/td>
 &lt;td>高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>英文&lt;/td>
 &lt;td>not X but rather Y、it&amp;rsquo;s not that X but Y、rather than X&lt;/td>
 &lt;td>學術 / 技術修辭傳統的核心愛用句、可能更高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>日文&lt;/td>
 &lt;td>X ではなく Y、A というより、むしろ B&lt;/td>
 &lt;td>高&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>LLM 在三種語言都從語料學到對應的高頻版本、換語言不打破、英文甚至可能更嚴重。&lt;/p>
&lt;p>這個證偽的價值不在「結論是否定的」、在它把問題釘到正確的層：如果這個句型跨語言都在、那本質就不在「某種語言的句型」、而在所有語言共享的資訊結構偏好（重點後置讀起來「優雅」、但效率次優）。&lt;/p>
&lt;hr>
&lt;h2 id="判別線重點位置統一了對照句的判定">判別線：重點位置統一了對照句的判定&lt;/h2>
&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>「X、不是 Y」&lt;/td>
 &lt;td>重點 X 先行&lt;/td>
 &lt;td>合法&lt;/td>
 &lt;td>#94&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「不是 X、而是 Y」&lt;/td>
 &lt;td>重點 Y 後置&lt;/td>
 &lt;td>違規&lt;/td>
 &lt;td>#149 的違規例&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>判別是「核心概念在不在最前」、不是「否定的角色」（#149 的「概念位置」其實就是這個、本卡正名它為資訊結構的重點優先）、不是「對照刪不刪」（#94）、不是「句型」。一個資訊結構判準涵蓋全部對照句、且涵蓋所有重點後置變體（與其 X 不如 Y、不只 X 更 Y），而句型 grep 永遠枚舉不完。實證在這次的 POS lint pattern：連接詞清單擴了兩次（而是 → 加「— 是」→ 加「不在…而在」）、每次擴完就暴露下一個變體、仍漏第四個「不是 X、是 Y」頓號版；而「、是」頓號版誤判率高（「不是 A、是 B」多為正常列舉）、刻意不補進 pattern —— 正是判準（重點位置）優於窮舉（連接詞）的活證明。完整修法軌跡見 &lt;a href="../remediation-introduces-sibling-variants/">#167 修法是新違規的來源、且常引入同類變體&lt;/a>。&lt;/p>
&lt;p>這個判準可操作：對每個定義句、找核心概念第一次正面出現的位置、在句首就合規、被擠到「而是」之後就違規。它比「判斷這個否定是建立概念還是對照」客觀得多。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼-llm-系統性放水高頻偏置">為什麼 LLM 系統性放水：高頻偏置&lt;/h2>
&lt;p>LLM 從語料學到「不是 X、而是 Y」是高頻、讀起來優雅的表達、於是它的「表達能力評價」把這個句型評為好。問題在高頻不等於資訊結構優 —— 這個句型高頻、是因為它在修辭上有對照張力、好寫好讀；它效率次優、是因為重點後置。兩件事獨立、而 LLM 的評價把前者（高頻 / 優雅）誤當後者（資訊結構好）。&lt;/p>
&lt;p>這個偏置跨語言、且作者與 reviewer 共享（都是 LLM、學同一類語料）。所以 LLM reviewer 讀到這個句型覺得「自然、好」、跳過重點位置判準、走「讀起來優雅就放行」的捷徑。歸因是訓練語料的高頻偏置、比「文體盲區」這個說法更具體可檢驗。&lt;/p>
&lt;hr>
&lt;h2 id="主解強制執行重點位置判準異源為輔">主解：強制執行重點位置判準、異源為輔&lt;/h2>
&lt;p>本質可操作、所以主解是把重點位置判準變成不可跳過的機械步驟、不是靠品味、也不是只靠異源視角。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>主解&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>文體異源視角&lt;/td>
 &lt;td>human cold-read / 對抗文體 reviewer（&lt;a href="../register-violation-needs-cross-style-eyes/">#165&lt;/a>）&lt;/td>
 &lt;td>補充&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>異源視角是補充、不是唯一解。它補兩種殘餘：強制判準仍漏的、以及無單一重點位置的 register 類（喊話、誇飾 —— 這類回到 #165 的同源上限）。對「重點優先」這個可操作子集、強制執行判準就能抓大部分、不必先跳到「不可機械化、只能靠人」。&lt;/p>
&lt;hr>
&lt;h2 id="存量候選的漸進判讀">存量候選的漸進判讀&lt;/h2>
&lt;p>把重點位置判準升進工具鏈（&lt;code>mdtools lint&lt;/code> 的 POS-negation-lead 警告層、見 &lt;a href="https://tarrragon.github.io/blog/posts/blog-markdown-%E5%AF%AB%E4%BD%9C%E8%A6%8F%E7%AF%84%E8%88%87-mdtools-%E6%AA%A2%E6%9F%A5/" data-link-title="Blog Markdown 寫作規範與 mdtools 檢查" data-link-desc="本 blog 的 Markdown 排版規範權威契約。涵蓋 H1 禁用、MD024 siblings_only、反釣魚 TLD 校驗、卡片雙向完整性、front matter schema；改規則時要與 scripts/mdtools 實作同步。">markdown-writing-spec&lt;/a> 否定起手候選掃描段）之後、全 &lt;code>content/&lt;/code> 約 300 個重點後置候選一次曝光 —— 它們之前 silent、靠 review 記憶才偶爾 catch。曝光本身就是價值（候選在每次 lint 持續可見、不再靠記憶）、判讀則漸進進行：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>不一次清倉&lt;/strong>：300 裡多數是合法對照（核心概念已先行、「不是 X、而是 Y」只是補充）或 meta / 引用（講此句型的卡與規範），真違規只是子集 —— 一次性全判 ROI 遞減。&lt;/li>
&lt;li>&lt;strong>changed-set scoped 漸進&lt;/strong>：規則讓候選在每次 lint 持續可見、碰到含 POS 警告的檔時用上面三類判準順手判、真違規改重點先行。這是 markdown-writing-spec 位置引用掃描段與否定起手掃描段的存量處理原則。&lt;/li>
&lt;li>&lt;strong>本卡承擔這個漸進工作的 backlog&lt;/strong>：判讀協議（重點位置 + 三類處置）寫在這、未來遇到候選的人讀本卡就知道怎麼判、不需要另開記錄文件。report 卡比單純的記錄文件更有條理 —— 原則、判讀協議、落地狀態收在同一處。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;h3 id="在語言層找解治不了跨語言的問題">在語言層找解、治不了跨語言的問題&lt;/h3>
&lt;p>把問題定位成「中文句型」、就會去補 grep 抓句型變體、或想換語言打破。句型 grep 枚舉不完、換語言不打破（證偽過）—— 兩條都在語言層用力、而問題在跨語言的資訊結構層。&lt;/p></description><content:encoded><![CDATA[<h2 id="結論">結論</h2>
<p>正向陳述優先的本質是資訊結構效率：讀者拿到核心概念的認知步驟越少越好。「不是 X、而是 Y」表達能力差、是因為它讓讀者先處理一個被否定的錯誤理解 X、才拿到正確的 Y —— 重點後置、多繞一步。問題的根本在資訊結構、不在中文特有的句型、也不在主觀品味。</p>
<p>這個校正很重要、因為它決定了解法的方向：把問題定位成「中文句型」、會去抓句型變體或換語言；定位成「品味」、會去靠主觀判定或異源視角；定位成「資訊結構效率」、才會去檢查「核心概念在不在最前」這個跨語言、可操作的判準。</p>
<hr>
<h2 id="證偽過的反例假設換語言能打破">證偽過的反例假設：「換語言能打破」</h2>
<p>一個自然的假設：如果「不是 X、而是 Y」是 LLM 中文訓練語料的高頻行為、那換英文或日文思考就能打破。這個假設值得驗、但證偽了。</p>
<table>
  <thead>
      <tr>
          <th>語言</th>
          <th>對應句型</th>
          <th>密度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>中文</td>
          <td>不是 X、而是 Y</td>
          <td>高</td>
      </tr>
      <tr>
          <td>英文</td>
          <td>not X but rather Y、it&rsquo;s not that X but Y、rather than X</td>
          <td>學術 / 技術修辭傳統的核心愛用句、可能更高</td>
      </tr>
      <tr>
          <td>日文</td>
          <td>X ではなく Y、A というより、むしろ B</td>
          <td>高</td>
      </tr>
  </tbody>
</table>
<p>LLM 在三種語言都從語料學到對應的高頻版本、換語言不打破、英文甚至可能更嚴重。</p>
<p>這個證偽的價值不在「結論是否定的」、在它把問題釘到正確的層：如果這個句型跨語言都在、那本質就不在「某種語言的句型」、而在所有語言共享的資訊結構偏好（重點後置讀起來「優雅」、但效率次優）。</p>
<hr>
<h2 id="判別線重點位置統一了對照句的判定">判別線：重點位置統一了對照句的判定</h2>
<p>核心概念在不在句首、是判別對照句合不合規的單一判準：</p>
<table>
  <thead>
      <tr>
          <th>句型</th>
          <th>重點位置</th>
          <th>判定</th>
          <th>既有卡</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「X、不是 Y」</td>
          <td>重點 X 先行</td>
          <td>合法</td>
          <td>#94</td>
      </tr>
      <tr>
          <td>「不是 X、而是 Y」</td>
          <td>重點 Y 後置</td>
          <td>違規</td>
          <td>#149 的違規例</td>
      </tr>
  </tbody>
</table>
<p>判別是「核心概念在不在最前」、不是「否定的角色」（#149 的「概念位置」其實就是這個、本卡正名它為資訊結構的重點優先）、不是「對照刪不刪」（#94）、不是「句型」。一個資訊結構判準涵蓋全部對照句、且涵蓋所有重點後置變體（與其 X 不如 Y、不只 X 更 Y），而句型 grep 永遠枚舉不完。實證在這次的 POS lint pattern：連接詞清單擴了兩次（而是 → 加「— 是」→ 加「不在…而在」）、每次擴完就暴露下一個變體、仍漏第四個「不是 X、是 Y」頓號版；而「、是」頓號版誤判率高（「不是 A、是 B」多為正常列舉）、刻意不補進 pattern —— 正是判準（重點位置）優於窮舉（連接詞）的活證明。完整修法軌跡見 <a href="../remediation-introduces-sibling-variants/">#167 修法是新違規的來源、且常引入同類變體</a>。</p>
<p>這個判準可操作：對每個定義句、找核心概念第一次正面出現的位置、在句首就合規、被擠到「而是」之後就違規。它比「判斷這個否定是建立概念還是對照」客觀得多。</p>
<hr>
<h2 id="為什麼-llm-系統性放水高頻偏置">為什麼 LLM 系統性放水：高頻偏置</h2>
<p>LLM 從語料學到「不是 X、而是 Y」是高頻、讀起來優雅的表達、於是它的「表達能力評價」把這個句型評為好。問題在高頻不等於資訊結構優 —— 這個句型高頻、是因為它在修辭上有對照張力、好寫好讀；它效率次優、是因為重點後置。兩件事獨立、而 LLM 的評價把前者（高頻 / 優雅）誤當後者（資訊結構好）。</p>
<p>這個偏置跨語言、且作者與 reviewer 共享（都是 LLM、學同一類語料）。所以 LLM reviewer 讀到這個句型覺得「自然、好」、跳過重點位置判準、走「讀起來優雅就放行」的捷徑。歸因是訓練語料的高頻偏置、比「文體盲區」這個說法更具體可檢驗。</p>
<hr>
<h2 id="主解強制執行重點位置判準異源為輔">主解：強制執行重點位置判準、異源為輔</h2>
<p>本質可操作、所以主解是把重點位置判準變成不可跳過的機械步驟、不是靠品味、也不是只靠異源視角。</p>
<table>
  <thead>
      <tr>
          <th>防線層</th>
          <th>做法</th>
          <th>角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>強制重點位置判準</td>
          <td>對每個定義句逐句問「核心概念第一次正面出現在句首、還是被擠到『而是』之後」</td>
          <td>主解</td>
      </tr>
      <tr>
          <td>文體異源視角</td>
          <td>human cold-read / 對抗文體 reviewer（<a href="../register-violation-needs-cross-style-eyes/">#165</a>）</td>
          <td>補充</td>
      </tr>
  </tbody>
</table>
<p>異源視角是補充、不是唯一解。它補兩種殘餘：強制判準仍漏的、以及無單一重點位置的 register 類（喊話、誇飾 —— 這類回到 #165 的同源上限）。對「重點優先」這個可操作子集、強制執行判準就能抓大部分、不必先跳到「不可機械化、只能靠人」。</p>
<hr>
<h2 id="存量候選的漸進判讀">存量候選的漸進判讀</h2>
<p>把重點位置判準升進工具鏈（<code>mdtools lint</code> 的 POS-negation-lead 警告層、見 <a href="/blog/posts/blog-markdown-%E5%AF%AB%E4%BD%9C%E8%A6%8F%E7%AF%84%E8%88%87-mdtools-%E6%AA%A2%E6%9F%A5/" data-link-title="Blog Markdown 寫作規範與 mdtools 檢查" data-link-desc="本 blog 的 Markdown 排版規範權威契約。涵蓋 H1 禁用、MD024 siblings_only、反釣魚 TLD 校驗、卡片雙向完整性、front matter schema；改規則時要與 scripts/mdtools 實作同步。">markdown-writing-spec</a> 否定起手候選掃描段）之後、全 <code>content/</code> 約 300 個重點後置候選一次曝光 —— 它們之前 silent、靠 review 記憶才偶爾 catch。曝光本身就是價值（候選在每次 lint 持續可見、不再靠記憶）、判讀則漸進進行：</p>
<ul>
<li><strong>不一次清倉</strong>：300 裡多數是合法對照（核心概念已先行、「不是 X、而是 Y」只是補充）或 meta / 引用（講此句型的卡與規範），真違規只是子集 —— 一次性全判 ROI 遞減。</li>
<li><strong>changed-set scoped 漸進</strong>：規則讓候選在每次 lint 持續可見、碰到含 POS 警告的檔時用上面三類判準順手判、真違規改重點先行。這是 markdown-writing-spec 位置引用掃描段與否定起手掃描段的存量處理原則。</li>
<li><strong>本卡承擔這個漸進工作的 backlog</strong>：判讀協議（重點位置 + 三類處置）寫在這、未來遇到候選的人讀本卡就知道怎麼判、不需要另開記錄文件。report 卡比單純的記錄文件更有條理 —— 原則、判讀協議、落地狀態收在同一處。</li>
</ul>
<hr>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<h3 id="在語言層找解治不了跨語言的問題">在語言層找解、治不了跨語言的問題</h3>
<p>把問題定位成「中文句型」、就會去補 grep 抓句型變體、或想換語言打破。句型 grep 枚舉不完、換語言不打破（證偽過）—— 兩條都在語言層用力、而問題在跨語言的資訊結構層。</p>
<h3 id="把可操作問題誤診成品味上限">把可操作問題誤診成品味上限</h3>
<p>把「重點位置」這個可操作判準、誤診成「不可機械化的品味、只能靠異源」（<a href="../register-violation-needs-cross-style-eyes/">#165</a> 的過度推論）、就會放棄判準、過度依賴異源。實際上強制執行重點位置判準就能抓大部分 —— 這是把 execution gap（有判準沒執行）誤判成 design 上限（判準不存在）、正是 <a href="../review-miss-diagnose-design-vs-execution-gap/">#153</a> 警告的診斷錯誤。</p>
<h3 id="高頻偏置讓優雅變成放行藉口">高頻偏置讓「優雅」變成放行藉口</h3>
<p>reviewer 用「這句讀起來優雅 / 自然」當放行理由、等於用高頻偏置覆蓋資訊結構判準。優雅與效率是兩件事、要分開問。</p>
<hr>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li><strong><a href="../register-violation-needs-cross-style-eyes/">#165 register 違規：偵測可機械化、判定要靠文體異源</a></strong>：本卡是 #165 的上層、並校正它兩個過度推論。#165 揭露「同源 LLM 漏 register 違規」這個現象、有價值；但它把解過度歸到「判定不可機械化、異源是唯一結構解」。本卡指出「不是 X、而是 Y」這個子集的本質是可操作的資訊結構判準（重點位置）、主解是強制執行、異源降為補充。#165 對喊話 / 誇飾這類無單一重點位置的 register 仍成立、本卡聚焦「重點優先」這個可操作子集。</li>
<li><strong><a href="../keyword-bank-hit-is-candidate-not-verdict/">#149 keyword bank 命中是候選、不是判決</a></strong>：#149 的「概念位置判定」其實就是重點位置、本卡把它正名為「資訊結構的重點優先」、並指出它跨語言、可操作。#149 停在「用概念位置判定」、本卡補「為什麼判定會跳過（高頻偏置）」與「怎麼強制執行」。</li>
<li><strong><a href="../remediation-introduces-sibling-variants/">#167 修法是新違規的來源、且常引入同類變體</a></strong>：本卡是靜態原則（句型枚舉不完、判準是重點位置）、#167 是它的過程面 —— 修法 / 補 pattern 的動作反覆暴露同類變體（這次 POS pattern 連接詞清單擴兩次仍漏第四個的軌跡），收斂靠本卡的重點位置判準、不靠窮舉連接詞。</li>
<li><strong><a href="../positive-rewrite-preserves-contrast/">#94 正向改寫要保留對照論據</a></strong>：本卡統一 #94 與 #149 的判別線。#94 的「X、不是 Y」是重點先行（合法）、#149 的「不是 X、而是 Y」是重點後置（違規）—— 兩者的判別線是同一個「重點位置」、不是兩條獨立規則。</li>
<li><strong><a href="../review-miss-diagnose-design-vs-execution-gap/">#153 Review 漏抓先分 design gap 與 execution gap</a></strong>：本卡是 #153 的一個實證 —— #165 把「reviewer 有判準（概念位置）卻沒執行」（execution gap）誤診成「判定不可機械化」（design 上限）。本卡校正回 execution + 可操作判準。</li>
<li><strong><a href="../literal-interception-vs-behavioral-refinement/">#82 字面攔截 vs 行為精修</a></strong>：重點位置是行為層判準（讀者拿到核心要幾個認知步驟）、比字面層（grep「不是…而是」句型）更本質、且跨語言。grep 抓字面句型、重點位置判讀者的認知成本。</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>徵兆</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>對某寫作問題在「語言 / 句型」層找解（換語言、grep 句型變體）</td>
          <td>退一步問「本質是不是跨語言的資訊結構問題」、在語言層找不到根本解</td>
      </tr>
      <tr>
          <td>「不是 X、而是 Y / 與其 X 不如 Y / 不只 X 更 Y」</td>
          <td>找核心概念第一次正面出現的位置、後置就前置</td>
      </tr>
      <tr>
          <td>reviewer 覺得某句「讀起來優雅 / 自然」就放行</td>
          <td>警惕高頻偏置 —— 優雅與資訊結構效率是兩件事、用重點位置判準覆核</td>
      </tr>
      <tr>
          <td>把寫作問題歸到「不可機械化、只能靠人 / 異源」</td>
          <td>先確認是不是有可操作的結構判準被跳過（execution）、別太快宣告 design 上限</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="適用範圍與邊界">適用範圍與邊界</h2>
<ul>
<li><strong>適用</strong>：對照句 / 定義句的重點位置（不是…而是、與其…不如、不只…更）；跨語言寫作；技術 / 教學文（重點優先最該成立的 surface）。</li>
<li><strong>不適用</strong>：敘事 / 懸念類寫作（先鋪陳後揭重點是設計、不是缺陷）；無單一「重點」的純列舉。</li>
<li><strong>邊界</strong>：「重點優先」是可操作判準、但「哪個是重點」仍需理解內容 —— 可操作指「一旦識別重點、位置判定客觀」、不是「全自動無需理解」。對喊話 / 誇飾這類非重點位置的 register、回到 #165 的異源補充。</li>
</ul>
<hr>
<h2 id="self-case本卡的觸發來源">Self-case：本卡的觸發來源</h2>
<p>本卡觸發於 <a href="../register-violation-needs-cross-style-eyes/">#165</a> 寫完之後、使用者的追問：如果「不是 X、而是 Y」是 LLM 中文訓練出來的行為、換英文或日文思考能不能打破？這個假設的證偽（英 / 日文同樣高頻、英文修辭傳統尤甚）、把問題從「中文句型」釘到「跨語言資訊結構」。使用者並指出真需求是「正面語境描述 + 重點優先陳述」、本質是這個句型表達能力差（重點後置）、不是對抗特定句型。</p>
<p>這校正了 #165 的兩個過度推論：本質可操作（重點位置、跨語言）、不是不可機械化的品味；主解是強制執行重點位置判準、不是異源唯一。記錄這次「把可操作問題誤診成品味上限」的校正 —— 它跟同批 retrospective 第一輪「把問題過度工具化（補 grep）」對稱、兩次都偏離中道（一次過度工具化、一次過度玄學化）、由使用者連續追問拉回（見 memory <code>root-cause-over-toolification</code>）。</p>
]]></content:encoded></item><item><title>多輪審查要有冷讀者 frame：知情 reviewer 看不見行話洩漏</title><link>https://tarrragon.github.io/blog/report/cold-reader-frame-vs-informed-reviewer/</link><pubDate>Thu, 18 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/cold-reader-frame-vs-informed-reviewer/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡是一次 multi-round-review 漏抓的 self-retrospective 抽出。限制：樣本為 1 次 review（til/terms 14 卡），「知情 vs 冷讀」二分基於單次觀察；修法（補冷讀 frame）的有效性已由同批內容的後續冷讀驗證初步確認，但未跨多批驗證。讀者把它當「review 讀者模擬的一個必查維度」，不當已驗證流程。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>多輪審查模擬讀者時，要區分兩種讀者，分開跑：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>知情讀者（旅程 frame）&lt;/strong>：讀完全部、依學習路線走，看入口判讀與內容門檻。&lt;/li>
&lt;li>&lt;strong>冷讀者（零脈絡單卡落地 frame）&lt;/strong>：假裝經搜尋或他人貼連結，直接落在單一篇章，沒讀過其他篇與索引。&lt;/li>
&lt;/ul>
&lt;p>關鍵差別：&lt;strong>知情 reviewer 會自動腦補脈絡，因此結構性看不見「洩漏撰寫者預設前提的行話」&lt;/strong>——未定義就出現的「家族」「上述」「如前所述」「本文前面提到」。只有零脈絡冷讀者會立刻問「這裡突然冒出的 X 是什麼」。&lt;/p>
&lt;p>原子化 / Zettelkasten / glossary / 任何可被直連或搜尋單獨抵達的內容，冷讀 frame 為必備，不可只靠旅程 frame。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>til/terms 是一組 14 張互連的術語卡。經 3 輪多輪審查（含「讀者旅程」frame），三個 reviewer 全給 A、零必修。但每張卡都用「連到家族 / 概念家族」這個只有撰寫者懂的詞——讀者從搜尋落在單卡時，根本不知「家族」指什麼。知情 reviewer 讀完全部後腦補了「這是一組詞」，沒察覺這個洩漏。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>把 Reader simulation 拆成兩個子 frame：旅程（知情讀者走路線）與冷讀落地（單卡零脈絡）。冷讀 frame 逐篇問三件事：我知道為何讀這篇嗎？有沒有未在本篇定義的預設脈絡詞？我能不能從這篇找到回路？原子內容兩個 frame 都要跑。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;p>只跑旅程 frame，知情 reviewer 全 A 放行，行話會留到讀者冷讀單卡時才卡住——而那時內容已發佈，回報後得回頭改全部卡。把「讀完全部的 reviewer 覺得通順」當成「冷讀者也通順」，是把 informed 的腦補誤當成內容自包含。&lt;/p>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;ul>
&lt;li>內容是原子 / 可被搜尋或直連單篇落地（術語卡、glossary、知識卡）。&lt;/li>
&lt;li>reviewer 是「讀完全部」才判讀旅程，沒人模擬「只讀這一篇」。&lt;/li>
&lt;li>文中出現「家族 / 本盒 / 上述 / 如前所述 / 前面提到」這類需要前文才懂的詞。&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>本檢討已回饋到 multi-round-review skill（Round 2 新增 B′ 冷讀 frame）。寫作順序上 skill 修改先於本報告，屬例外；正序是報告（來源）→ skill 改進 → 下游。&lt;/p>&lt;/blockquote></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡是一次 multi-round-review 漏抓的 self-retrospective 抽出。限制：樣本為 1 次 review（til/terms 14 卡），「知情 vs 冷讀」二分基於單次觀察；修法（補冷讀 frame）的有效性已由同批內容的後續冷讀驗證初步確認，但未跨多批驗證。讀者把它當「review 讀者模擬的一個必查維度」，不當已驗證流程。</p>
<h2 id="核心原則">核心原則</h2>
<p>多輪審查模擬讀者時，要區分兩種讀者，分開跑：</p>
<ul>
<li><strong>知情讀者（旅程 frame）</strong>：讀完全部、依學習路線走，看入口判讀與內容門檻。</li>
<li><strong>冷讀者（零脈絡單卡落地 frame）</strong>：假裝經搜尋或他人貼連結，直接落在單一篇章，沒讀過其他篇與索引。</li>
</ul>
<p>關鍵差別：<strong>知情 reviewer 會自動腦補脈絡，因此結構性看不見「洩漏撰寫者預設前提的行話」</strong>——未定義就出現的「家族」「上述」「如前所述」「本文前面提到」。只有零脈絡冷讀者會立刻問「這裡突然冒出的 X 是什麼」。</p>
<p>原子化 / Zettelkasten / glossary / 任何可被直連或搜尋單獨抵達的內容，冷讀 frame 為必備，不可只靠旅程 frame。</p>
<h2 id="情境">情境</h2>
<p>til/terms 是一組 14 張互連的術語卡。經 3 輪多輪審查（含「讀者旅程」frame），三個 reviewer 全給 A、零必修。但每張卡都用「連到家族 / 概念家族」這個只有撰寫者懂的詞——讀者從搜尋落在單卡時，根本不知「家族」指什麼。知情 reviewer 讀完全部後腦補了「這是一組詞」，沒察覺這個洩漏。</p>
<h2 id="理想做法">理想做法</h2>
<p>把 Reader simulation 拆成兩個子 frame：旅程（知情讀者走路線）與冷讀落地（單卡零脈絡）。冷讀 frame 逐篇問三件事：我知道為何讀這篇嗎？有沒有未在本篇定義的預設脈絡詞？我能不能從這篇找到回路？原子內容兩個 frame 都要跑。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<p>只跑旅程 frame，知情 reviewer 全 A 放行，行話會留到讀者冷讀單卡時才卡住——而那時內容已發佈，回報後得回頭改全部卡。把「讀完全部的 reviewer 覺得通順」當成「冷讀者也通順」，是把 informed 的腦補誤當成內容自包含。</p>
<h2 id="判讀徵兆">判讀徵兆</h2>
<ul>
<li>內容是原子 / 可被搜尋或直連單篇落地（術語卡、glossary、知識卡）。</li>
<li>reviewer 是「讀完全部」才判讀旅程，沒人模擬「只讀這一篇」。</li>
<li>文中出現「家族 / 本盒 / 上述 / 如前所述 / 前面提到」這類需要前文才懂的詞。</li>
</ul>
<blockquote>
<p>本檢討已回饋到 multi-round-review skill（Round 2 新增 B′ 冷讀 frame）。寫作順序上 skill 修改先於本報告，屬例外；正序是報告（來源）→ skill 改進 → 下游。</p></blockquote>
]]></content:encoded></item><item><title>原子筆記要有向上的議題入口：讀者要知道為何讀這張、何時會撞到</title><link>https://tarrragon.github.io/blog/report/atomic-note-needs-situational-entry/</link><pubDate>Thu, 18 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/atomic-note-needs-situational-entry/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自一次術語卡撰寫的檢討（til/terms 14 卡）。限制：單一案例、單一內容類型（跨領域術語）；「議題 hub + 原子卡」兩層結構對其他內容類型的適用性未驗證。與既有 &lt;a href="../teaching-completeness-by-learner-journey/">教材完整性要用讀者旅程驗證&lt;/a> 區分——那談課程級的學習路線，本卡談單張原子筆記的進入動機與其上層議題。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>承載知識的原子筆記&lt;strong>不是字典條目&lt;/strong>。字典回答「這個詞是什麼」；承載知識的卡要回答「&lt;strong>你在討論什麼、撞到什麼問題，才需要這個知識&lt;/strong>」。&lt;/p>
&lt;p>撰寫者有預設的情境與前提，讀者沒有。所以每張原子卡（或它的上層）要提供進入動機：從情境進入，而非劈頭給定義。具體做法是建一層&lt;strong>議題 hub&lt;/strong>——以讀者會遇到的問題為標題（「測試紅燈不一定是真的壞」「告警太多反而沒人看」），討論議題、再分流到底下的術語卡；術語卡頂部回指它出自哪個議題，讓搜尋直接落地者也有回路。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>til/terms 的術語卡初版，每張都從定義開頭：「alert fatigue 指誤報太多、人對告警麻木……」。內容正確，但讀者不知道自己&lt;strong>為什麼&lt;/strong>會需要這個詞、&lt;strong>何時&lt;/strong>會撞到——卡片成了字典。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>為每個分支建議題 hub（情境入口），從「你遇到什麼問題」進入、再導向該讀的術語卡；術語卡頂部加一行回指議題（「這個詞出現在『X』這個問題裡」）。形成「議題 hub（情境）→ 原子卡（定義）」兩層，讀者由動機而非定義進入。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;p>卡淪為字典：讀者沒有觸發點，搜尋落地後讀完仍不知這對他有何用，知識無法在「對的時機」被取用。承載知識的內容若只有定義層、缺議題層，就退化成可被任何字典取代的條目，失去 blog 累積知識的價值。&lt;/p>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;ul>
&lt;li>卡片開頭是「X 指……」的定義句，沒有情境鋪陳。&lt;/li>
&lt;li>問「讀者為什麼要讀這張卡」答不出來，或答案是「為了知道定義」。&lt;/li>
&lt;li>一組原子卡彼此互連，卻沒有上層的議題導讀帶讀者進入。&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自一次術語卡撰寫的檢討（til/terms 14 卡）。限制：單一案例、單一內容類型（跨領域術語）；「議題 hub + 原子卡」兩層結構對其他內容類型的適用性未驗證。與既有 <a href="../teaching-completeness-by-learner-journey/">教材完整性要用讀者旅程驗證</a> 區分——那談課程級的學習路線，本卡談單張原子筆記的進入動機與其上層議題。</p>
<h2 id="核心原則">核心原則</h2>
<p>承載知識的原子筆記<strong>不是字典條目</strong>。字典回答「這個詞是什麼」；承載知識的卡要回答「<strong>你在討論什麼、撞到什麼問題，才需要這個知識</strong>」。</p>
<p>撰寫者有預設的情境與前提，讀者沒有。所以每張原子卡（或它的上層）要提供進入動機：從情境進入，而非劈頭給定義。具體做法是建一層<strong>議題 hub</strong>——以讀者會遇到的問題為標題（「測試紅燈不一定是真的壞」「告警太多反而沒人看」），討論議題、再分流到底下的術語卡；術語卡頂部回指它出自哪個議題，讓搜尋直接落地者也有回路。</p>
<h2 id="情境">情境</h2>
<p>til/terms 的術語卡初版，每張都從定義開頭：「alert fatigue 指誤報太多、人對告警麻木……」。內容正確，但讀者不知道自己<strong>為什麼</strong>會需要這個詞、<strong>何時</strong>會撞到——卡片成了字典。</p>
<h2 id="理想做法">理想做法</h2>
<p>為每個分支建議題 hub（情境入口），從「你遇到什麼問題」進入、再導向該讀的術語卡；術語卡頂部加一行回指議題（「這個詞出現在『X』這個問題裡」）。形成「議題 hub（情境）→ 原子卡（定義）」兩層，讀者由動機而非定義進入。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<p>卡淪為字典：讀者沒有觸發點，搜尋落地後讀完仍不知這對他有何用，知識無法在「對的時機」被取用。承載知識的內容若只有定義層、缺議題層，就退化成可被任何字典取代的條目，失去 blog 累積知識的價值。</p>
<h2 id="判讀徵兆">判讀徵兆</h2>
<ul>
<li>卡片開頭是「X 指……」的定義句，沒有情境鋪陳。</li>
<li>問「讀者為什麼要讀這張卡」答不出來，或答案是「為了知道定義」。</li>
<li>一組原子卡彼此互連，卻沒有上層的議題導讀帶讀者進入。</li>
</ul>
]]></content:encoded></item><item><title>Description 是未來自己的 recall trigger、不是文章摘要</title><link>https://tarrragon.github.io/blog/report/description-as-recall-trigger/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/description-as-recall-trigger/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自一次三篇 macOS 系統管理文章的多輪審查。審查修完 32 項 finding 後，作者發現 description 雖符合格式規範（30-150 字、非空），語意卻只是摘要——未來回顧列表時無法判斷「何時該重讀」。限制：單一案例（操作型文章），其他類型（教學模組、report 卡、知識卡）的 description 可能有不同的 recall 結構。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>文章的 &lt;code>description&lt;/code> 欄位是寫給&lt;strong>未來自己&lt;/strong>的 recall trigger，不是寫給搜尋引擎的摘要。它要回答的問題是：「我在什麼情境下、遇到什麼問題，會需要回來讀這篇？」&lt;/p>
&lt;p>類比：Claude Code skill 的 &lt;code>description&lt;/code> 讓系統在對話中自動判斷「要不要載入這個 skill」。文章的 description 讓未來的自己在掃列表時自動判斷「要不要進去讀」。兩者目的相同——降低 recall 的認知成本。&lt;/p>
&lt;p>摘要式 description 只回答「這篇&lt;strong>在講什麼&lt;/strong>」（內容索引）；recall trigger 回答「&lt;strong>你在什麼情境下需要這篇&lt;/strong>」（情境索引）。前者是被動的——搜尋命中後才看；後者是主動的——掃列表就能決定。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>三篇 macOS 文章（新機設定 / 磁碟診斷 / App 佔用報告）的 description 寫法：&lt;/p>
&lt;ul>
&lt;li>原本：「從一台 30G 餘裕在幾小時內歸零的 Mac，記錄一套先看快照、再用實際佔用排查的磁碟診斷順序……」&lt;/li>
&lt;li>問題：這是&lt;strong>內容摘要&lt;/strong>——讀者已經知道要找「磁碟診斷」才會搜到它，description 只重述他已預期的內容，沒有增量資訊。&lt;/li>
&lt;li>理想：description 應該告訴未來的自己「你什麼時候會需要回來」——例如「磁碟莫名滿載時的排查起手順序、避開 sparse 假大小陷阱、以及用 tmutil 判讀快照是否為元兇的方法」。&lt;/li>
&lt;/ul>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>description 撰寫時問自己三個問題：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>我未來會在什麼情境下需要這篇？&lt;/strong>（觸發條件）&lt;/li>
&lt;li>&lt;strong>這篇給我的關鍵判讀 / 操作是什麼？&lt;/strong>（帶走的能力）&lt;/li>
&lt;li>&lt;strong>不讀這篇我會踩什麼坑？&lt;/strong>（省下的試錯）&lt;/li>
&lt;/ol>
&lt;p>三者至少涵蓋一個。格式不重要，重要的是 description 讀完後能判斷「現在要不要進去」。&lt;/p>
&lt;p>反例——以下句型通常是摘要不是 trigger：&lt;/p>
&lt;ul>
&lt;li>「記錄了 X 的過程」（日記式）&lt;/li>
&lt;li>「介紹 X 的做法」（教科書式）&lt;/li>
&lt;li>「從 X 事件整理出 Y」（報告式）&lt;/li>
&lt;/ul>
&lt;p>這些句型把 description 當後設描述（meta-description of the article），而不是情境描述（description of when you need it）。&lt;/p>
&lt;h3 id="寫法準則精準無假設無修辭">寫法準則：精準、無假設、無修辭&lt;/h3>
&lt;p>description 給人判斷也給機器（AI）判斷，每個 token 都要有資訊量。三個不要：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>不要操作細節&lt;/strong>——指令、參數、具體步驟留在內文。description 幫人決定「要不要點進去」，不是把文章壓縮塞進來。&lt;/li>
&lt;li>&lt;strong>不要假設前提&lt;/strong>——「想不起來」「卻發現」「卻不確定」「不知從何下手」這些描述讀者的困境，不是資訊。直接說用途。&lt;/li>
&lt;li>&lt;strong>不要情緒修辭&lt;/strong>——「別被騙」「打架」「空轉」「踩坑」這些不精準。用事實陳述取代。&lt;/li>
&lt;li>&lt;strong>不要內嵌數字&lt;/strong>——「三項基礎建設」「6 段結構」「兩個陷阱」把成員數烤進 description，內文增刪就要同步改。description 描述文章的功能（解什麼問題），不描述文章的結構（幾段幾項）。理想的 description 無論內文怎麼調整都不用變動。同 &lt;a href="../name-collections-by-role-not-count/">#156 集合命名不內嵌數量&lt;/a>。&lt;/li>
&lt;/ol>
&lt;p>對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>有問題&lt;/th>
 &lt;th>精準&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>想不起 figure shortcode 還是 Markdown 時查這篇&lt;/td>
 &lt;td>Hugo 文章插圖的寫法與路徑規則&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>別被 fail 訊息指的 test 騙&lt;/td>
 &lt;td>fail 位置看 &lt;code>+N -1&lt;/code> 累計而非訊息標示的 test&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>套模板每篇結構都打架時回來&lt;/td>
 &lt;td>migration playbook 的結構選型流程&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>三項基礎建設的依賴順序&lt;/td>
 &lt;td>底層基礎建設的依賴順序（數字隨內容變會過時）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>150 字上限不是要塞滿的配額。短能到位就短。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;ul>
&lt;li>列表頁的 description 變成一片「記錄了…」「整理出…」的重複句型，掃不出差異，每篇都要點進去才知道需不需要&lt;/li>
&lt;li>日後同類情境再發生時，想不起來自己寫過、重新搜或重新踩坑&lt;/li>
&lt;li>blog 的知識累積效益被 recall 成本吃掉——寫了等於沒寫&lt;/li>
&lt;/ul>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;ul>
&lt;li>description 的主詞是「本文 / 這篇 / 記錄」→ 可能是摘要不是 trigger&lt;/li>
&lt;li>description 刪掉後，只看 title 就能猜出 description 的全部內容 → 沒有增量&lt;/li>
&lt;li>掃列表時無法在 3 秒內判斷「這篇跟我現在的問題有沒有關」→ trigger 失敗&lt;/li>
&lt;/ul>
&lt;h2 id="跟其他原則的關係">跟其他原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="../atomic-note-needs-situational-entry/">#169 原子筆記要有向上的議題入口&lt;/a>：同根因——讀者（含未來的自己）需要「情境入口」而非「定義入口」。#169 談卡片正文的進入動機，本卡談 frontmatter description 的進入動機，是同一原則在不同 surface 的體現。&lt;/li>
&lt;li>&lt;a href="../teaching-completeness-by-learner-journey/">#131 教材完整性要用讀者旅程驗證&lt;/a>：讀者旅程的第一站是列表頁的 description——旅程驗證如果從「已進入文章」開始，就跳過了「要不要進入」的判斷點。&lt;/li>
&lt;li>&lt;a href="../audience-fork-before-jargon-wall/">#159 入口分流要放在詞彙牆之前&lt;/a>：description 是文章的入口分流欄位，分流依據應是讀者的情境而非文章的內容結構。&lt;/li>
&lt;/ul>
&lt;hr></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自一次三篇 macOS 系統管理文章的多輪審查。審查修完 32 項 finding 後，作者發現 description 雖符合格式規範（30-150 字、非空），語意卻只是摘要——未來回顧列表時無法判斷「何時該重讀」。限制：單一案例（操作型文章），其他類型（教學模組、report 卡、知識卡）的 description 可能有不同的 recall 結構。</p>
<h2 id="核心原則">核心原則</h2>
<p>文章的 <code>description</code> 欄位是寫給<strong>未來自己</strong>的 recall trigger，不是寫給搜尋引擎的摘要。它要回答的問題是：「我在什麼情境下、遇到什麼問題，會需要回來讀這篇？」</p>
<p>類比：Claude Code skill 的 <code>description</code> 讓系統在對話中自動判斷「要不要載入這個 skill」。文章的 description 讓未來的自己在掃列表時自動判斷「要不要進去讀」。兩者目的相同——降低 recall 的認知成本。</p>
<p>摘要式 description 只回答「這篇<strong>在講什麼</strong>」（內容索引）；recall trigger 回答「<strong>你在什麼情境下需要這篇</strong>」（情境索引）。前者是被動的——搜尋命中後才看；後者是主動的——掃列表就能決定。</p>
<h2 id="情境">情境</h2>
<p>三篇 macOS 文章（新機設定 / 磁碟診斷 / App 佔用報告）的 description 寫法：</p>
<ul>
<li>原本：「從一台 30G 餘裕在幾小時內歸零的 Mac，記錄一套先看快照、再用實際佔用排查的磁碟診斷順序……」</li>
<li>問題：這是<strong>內容摘要</strong>——讀者已經知道要找「磁碟診斷」才會搜到它，description 只重述他已預期的內容，沒有增量資訊。</li>
<li>理想：description 應該告訴未來的自己「你什麼時候會需要回來」——例如「磁碟莫名滿載時的排查起手順序、避開 sparse 假大小陷阱、以及用 tmutil 判讀快照是否為元兇的方法」。</li>
</ul>
<h2 id="理想做法">理想做法</h2>
<p>description 撰寫時問自己三個問題：</p>
<ol>
<li><strong>我未來會在什麼情境下需要這篇？</strong>（觸發條件）</li>
<li><strong>這篇給我的關鍵判讀 / 操作是什麼？</strong>（帶走的能力）</li>
<li><strong>不讀這篇我會踩什麼坑？</strong>（省下的試錯）</li>
</ol>
<p>三者至少涵蓋一個。格式不重要，重要的是 description 讀完後能判斷「現在要不要進去」。</p>
<p>反例——以下句型通常是摘要不是 trigger：</p>
<ul>
<li>「記錄了 X 的過程」（日記式）</li>
<li>「介紹 X 的做法」（教科書式）</li>
<li>「從 X 事件整理出 Y」（報告式）</li>
</ul>
<p>這些句型把 description 當後設描述（meta-description of the article），而不是情境描述（description of when you need it）。</p>
<h3 id="寫法準則精準無假設無修辭">寫法準則：精準、無假設、無修辭</h3>
<p>description 給人判斷也給機器（AI）判斷，每個 token 都要有資訊量。三個不要：</p>
<ol>
<li><strong>不要操作細節</strong>——指令、參數、具體步驟留在內文。description 幫人決定「要不要點進去」，不是把文章壓縮塞進來。</li>
<li><strong>不要假設前提</strong>——「想不起來」「卻發現」「卻不確定」「不知從何下手」這些描述讀者的困境，不是資訊。直接說用途。</li>
<li><strong>不要情緒修辭</strong>——「別被騙」「打架」「空轉」「踩坑」這些不精準。用事實陳述取代。</li>
<li><strong>不要內嵌數字</strong>——「三項基礎建設」「6 段結構」「兩個陷阱」把成員數烤進 description，內文增刪就要同步改。description 描述文章的功能（解什麼問題），不描述文章的結構（幾段幾項）。理想的 description 無論內文怎麼調整都不用變動。同 <a href="../name-collections-by-role-not-count/">#156 集合命名不內嵌數量</a>。</li>
</ol>
<p>對比：</p>
<table>
  <thead>
      <tr>
          <th>有問題</th>
          <th>精準</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>想不起 figure shortcode 還是 Markdown 時查這篇</td>
          <td>Hugo 文章插圖的寫法與路徑規則</td>
      </tr>
      <tr>
          <td>別被 fail 訊息指的 test 騙</td>
          <td>fail 位置看 <code>+N -1</code> 累計而非訊息標示的 test</td>
      </tr>
      <tr>
          <td>套模板每篇結構都打架時回來</td>
          <td>migration playbook 的結構選型流程</td>
      </tr>
      <tr>
          <td>三項基礎建設的依賴順序</td>
          <td>底層基礎建設的依賴順序（數字隨內容變會過時）</td>
      </tr>
  </tbody>
</table>
<p>150 字上限不是要塞滿的配額。短能到位就短。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<ul>
<li>列表頁的 description 變成一片「記錄了…」「整理出…」的重複句型，掃不出差異，每篇都要點進去才知道需不需要</li>
<li>日後同類情境再發生時，想不起來自己寫過、重新搜或重新踩坑</li>
<li>blog 的知識累積效益被 recall 成本吃掉——寫了等於沒寫</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<ul>
<li>description 的主詞是「本文 / 這篇 / 記錄」→ 可能是摘要不是 trigger</li>
<li>description 刪掉後，只看 title 就能猜出 description 的全部內容 → 沒有增量</li>
<li>掃列表時無法在 3 秒內判斷「這篇跟我現在的問題有沒有關」→ trigger 失敗</li>
</ul>
<h2 id="跟其他原則的關係">跟其他原則的關係</h2>
<ul>
<li><a href="../atomic-note-needs-situational-entry/">#169 原子筆記要有向上的議題入口</a>：同根因——讀者（含未來的自己）需要「情境入口」而非「定義入口」。#169 談卡片正文的進入動機，本卡談 frontmatter description 的進入動機，是同一原則在不同 surface 的體現。</li>
<li><a href="../teaching-completeness-by-learner-journey/">#131 教材完整性要用讀者旅程驗證</a>：讀者旅程的第一站是列表頁的 description——旅程驗證如果從「已進入文章」開始，就跳過了「要不要進入」的判斷點。</li>
<li><a href="../audience-fork-before-jargon-wall/">#159 入口分流要放在詞彙牆之前</a>：description 是文章的入口分流欄位，分流依據應是讀者的情境而非文章的內容結構。</li>
</ul>
<hr>
]]></content:encoded></item><item><title>列舉與數字殘留在定義型文件會製造維護債務</title><link>https://tarrragon.github.io/blog/report/enumeration-creates-maintenance-debt/</link><pubDate>Thu, 25 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/enumeration-creates-maintenance-debt/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>定義型文件（規則、規格、常駐名單——陳述「什麼成立」的文件，相對於報告、日誌這類記錄「當時發生什麼」的文件）中的&lt;strong>冗餘列舉和描述性數字&lt;/strong>是撰寫過程中的推理殘留——作者需要先計算範圍和數量來確認定義正確，但這個計算過程不該留在最終文件裡。判斷標準：&lt;strong>如果拿掉列舉或數字，讀者對定義的理解不受影響 → 刪除&lt;/strong>。&lt;/p>
&lt;p>下面兩個層次的殘留是觀察到的 pattern：&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>「所有情境（A-G）無條件加入」&lt;/td>
 &lt;td>新增情境 H 時要回頭更新所有引用&lt;/td>
 &lt;td>零——「所有情境」已完整表達&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>描述性數字&lt;/td>
 &lt;td>「9 個函式、428 行可獨立抽出」&lt;/td>
 &lt;td>任何函式增減都要校準計數&lt;/td>
 &lt;td>低——讀者需要的是哪些函式、不是幾個&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>列舉在定義型文件中也有合理用途：當列舉本身就是定義（封閉 enum、有限狀態機的狀態集、HTTP 方法集），列舉本身就是被定義的對象。區分方式：列舉是在&lt;strong>重述&lt;/strong>已由其他機制決定的範圍（冗餘）、還是在&lt;strong>建立&lt;/strong>範圍（定義）。&lt;/p>
&lt;p>同理，數字分兩種：&lt;strong>描述性數字&lt;/strong>報告現狀（「目前有 9 個函式」），程式碼一變就過時；&lt;strong>規範性數字&lt;/strong>規定目標值（「P99 &amp;lt; 200ms」「委員固定 7 人」「MAX_DEPTH=3」），是被定義的對象，該保留。&lt;/p>
&lt;hr>
&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡的論述基於 &lt;strong>2 個 case&lt;/strong>（parallel-evaluation SKILL.md 常駐委員定義 + W3-008 分析報告）抽出來的觀察，每個子論點（列舉 / 數字）各只有 1 個 case 支撐。具體限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>「列舉」指的是定義型文件中的冗餘列舉&lt;/strong>（如「所有情境（A-G）」），不包含報告格式範本中的 placeholder（如「情境: [A-G]」）——後者是填空欄位、不是定義；也不包含本身就是定義的封閉列舉（如 enum 成員清單）&lt;/li>
&lt;li>&lt;strong>「數字」指的是描述性計數&lt;/strong>（如「9 個函式」「428 行」），不包含規範性數字（如「MAX_DEPTH=3」「P99 &amp;lt; 200ms」）——後者是設計決策或 SLA 目標、不是統計快照&lt;/li>
&lt;li>&lt;strong>推理殘留不限於 AI 寫作&lt;/strong>：兩個 case 都來自 AI 生成的文件、AI 的生成順序可能讓這類殘留更常出現（見下方觀察），但人類作者在撰寫定義時同樣會先列舉確認再寫結論、忘了刪除中間產物&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="觸發案例">觸發案例&lt;/h2>
&lt;h3 id="case-1常駐委員定義的冗餘列舉">Case 1：常駐委員定義的冗餘列舉&lt;/h3>
&lt;p>parallel-evaluation SKILL.md 常駐委員表格寫了「所有情境（A-G）無條件加入」。「所有情境」已是完整定義，「（A-G）」在語意上重複——拿掉後讀者理解不受影響。留在文件裡則變成維護債務：新增情境 H 時「（A-G）」過時，讀者可能誤判 H 不含。&lt;/p>
&lt;p>&lt;strong>修正&lt;/strong>：刪除「（A-G）」。「所有情境無條件加入」自動涵蓋未來新增的情境。&lt;/p>
&lt;h3 id="case-2分析報告的數字快照">Case 2：分析報告的數字快照&lt;/h3>
&lt;p>W3-008 分析報告寫了「duplicate_detection 群組 9 個函式、428 行」。這是分析時的統計快照、作為報告紀錄合理。但如果這些數字被寫進 ticket 驗收條件（「duplicate_detector.py 含 9 個函式」「create.py 行數減少約 428 行」），重構過程中任何函式增減都會讓驗收條件失效。&lt;/p>
&lt;p>&lt;strong>判讀&lt;/strong>：分析報告中的數字 → 保留（紀錄）。驗收條件中的描述性計數 → 改用結構性斷言（「所有 duplicate 相關函式已移至新模組」「既有測試通過」）。&lt;/p>
&lt;hr>
&lt;h2 id="ai-生成的順序觀察">AI 生成的順序觀察&lt;/h2>
&lt;p>兩個 case 都來自 AI 生成的文件。AI 的生成順序是&lt;strong>先推理 → 再生成文字&lt;/strong>——模型在寫「所有情境無條件加入」之前，內部已驗證了 A 到 G 都涵蓋，列舉是推理的副產物被寫進生成的文字裡。同理，AI 在寫函式列表時傾向先數數量再列內容（「9 個函式：_tokenize, &amp;hellip;」），數量是為了自我驗證完整性，但讀者只需要函式列表本身。&lt;/p>
&lt;p>人類作者在撰寫定義時也會先列舉確認涵蓋範圍、AI 是否讓此模式更頻繁出現仍待更多樣本驗證（見限制段）。無論成因，判準相同：拿掉後讀者理解不受影響 → 刪除。&lt;/p>
&lt;hr>
&lt;h2 id="判斷決策表">判斷決策表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &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>刪除——定義本身已完整&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>報告型（分析、日誌、檢討）&lt;/td>
 &lt;td>紀錄快照&lt;/td>
 &lt;td>保留——讀者需要知道當時的狀態&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>驗收條件&lt;/td>
 &lt;td>依被測屬性判斷&lt;/td>
 &lt;td>穩定屬性（函式名稱清單）→ 保留；易變屬性（行數、計數）→ 改結構性斷言&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>範本 placeholder&lt;/td>
 &lt;td>填空欄位&lt;/td>
 &lt;td>保留——提示使用者填入具體值&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>驗收條件的判斷依據是&lt;strong>被測屬性是否隨重構變動&lt;/strong>。函式名稱清單在重構後仍可驗證（名稱沒變、只是搬家），但行數和函式計數會因任何增減而失效——改用結構性斷言（「所有 X 相關函式已移至新模組」）讓驗收條件跟重構過程解耦。&lt;/p>
&lt;p>真實文件常混合定義段與分析段（如 SKILL.md 同時有規則定義和設計紀錄），分類單位是&lt;strong>段落&lt;/strong>而非整份文件——同一份文件內的定義段套用刪除判準、分析段保留數字。範本 placeholder 同理，它是填空欄位、不是定義。&lt;/p>
&lt;hr>
&lt;h2 id="跟其他原則的關係">跟其他原則的關係&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/report/reader-does-not-need-to-know/" data-link-title="讀者不需要知道 — 刪除比解釋更尊重讀者" data-link-desc="「整理目的」blockquote 告訴讀者這篇文章的寫作動機和邊界。但讀者不需要知道作者為什麼寫這篇文章——他們需要知道讀完能帶走什麼。meta 資訊（寫作動機、邊界聲明、脈絡解釋）服務的是作者的組織需求，不是讀者的閱讀需求。">讀者不需要知道的資訊不該出現在最終文件&lt;/a> — 同根原則的兩種表現：該卡處理 meta 動機殘留（「為什麼寫這篇」）、本卡處理推理過程殘留（列舉和數字）。兩者共用「拿掉後讀者體驗變不變差」的判準&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/report/applicability-scope-must-be-enumerated/" data-link-title="適用範圍要展開成 file enumeration、口語描述不夠" data-link-desc="原則的『適用範圍』寫成口語描述（『所有教學文件的論證段落』）時、執行 review 的人要當場推導『具體哪些檔屬於這個範圍』、推導步驟容易漏；改寫成 enumerated file list（具體列出 file paths）就能避免 enumeration 不完整。Enumerate 的合法形式是『可被 grep / find 重現的具體 file 集合』、不是『口語類型描述』。本卡是 #95 的下游具體化、跟 #82 互補：enumerate 是字面層、enumeration completeness 是行為層判準。">適用範圍要展開成 file enumeration&lt;/a> — 鏡像關係：該卡主張「適用範圍要 enumerate」、本卡主張「定義型文件的冗餘列舉要刪」。取決於文件型別——scope 文件需要 enumeration 確保執行時不遺漏、定義型文件的範圍已由定義本身表達&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/report/name-collections-by-role-not-count/" data-link-title="集合命名用角色、不內嵌數量：「核心七問」的七是成員數的 derivation、加一問就全面失真" data-link-desc="「核心七問」「成長六階段」「四大支柱」這類名稱把成員數量烤進名字裡 — 數量是集合當前成員的 derivation、不是集合的語意身分；成員增減時名稱失真、且名稱是被複製最多次的字串、缺陷隨每次引用繁殖。修法：命名只承載角色與層級（核心問題 / 次要問題 / 撞牆階段）、數量讓清單自己呈現。本卡是 #155 的命名端 sibling（#155 修引用端、本卡讓「語意標題是穩定錨」的前提真正成立）、#44 SSoT 在名稱內容的實例、#84 命名檢驗的數量維度。">集合命名用角色、不內嵌數量&lt;/a> — 同原則在不同層面：前者處理命名層（「六大原則」的數字是成員清單的衍生值）、本卡處理正文定義層（「9 個函式」的數字是程式碼的衍生值）。兩卡共享「外部凍結數字可留」的邊界（前者的 SOLID / OWASP 對應本卡的 SLA / 設計常數）&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/report/ease-of-writing-vs-intent-alignment/" data-link-title="寫作便利度跟意圖對齊反相關" data-link-desc="寫程式時最容易寫出的版本、通常是離意圖最遠的版本。便利度建立在「現有上下文 / 已 materialize 資料 / 已存在 API」上、而意圖對齊需要找到正確的層、處理上游、跨抽象層 — 兩者方向相反。識別這個反相關 = 識別自己掉進「容易寫的陷阱」。">便利驅動的寫法會偏離意圖&lt;/a> — 上位原則：列舉殘留是「寫的時候方便（先算再寫）、讀的時候多餘」的具體實例&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p>定義型文件（規則、規格、常駐名單——陳述「什麼成立」的文件，相對於報告、日誌這類記錄「當時發生什麼」的文件）中的<strong>冗餘列舉和描述性數字</strong>是撰寫過程中的推理殘留——作者需要先計算範圍和數量來確認定義正確，但這個計算過程不該留在最終文件裡。判斷標準：<strong>如果拿掉列舉或數字，讀者對定義的理解不受影響 → 刪除</strong>。</p>
<p>下面兩個層次的殘留是觀察到的 pattern：</p>
<table>
  <thead>
      <tr>
          <th>殘留類型</th>
          <th>文件中的樣子</th>
          <th>維護成本</th>
          <th>閱讀價值</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>冗餘列舉</td>
          <td>「所有情境（A-G）無條件加入」</td>
          <td>新增情境 H 時要回頭更新所有引用</td>
          <td>零——「所有情境」已完整表達</td>
      </tr>
      <tr>
          <td>描述性數字</td>
          <td>「9 個函式、428 行可獨立抽出」</td>
          <td>任何函式增減都要校準計數</td>
          <td>低——讀者需要的是哪些函式、不是幾個</td>
      </tr>
  </tbody>
</table>
<p>列舉在定義型文件中也有合理用途：當列舉本身就是定義（封閉 enum、有限狀態機的狀態集、HTTP 方法集），列舉本身就是被定義的對象。區分方式：列舉是在<strong>重述</strong>已由其他機制決定的範圍（冗餘）、還是在<strong>建立</strong>範圍（定義）。</p>
<p>同理，數字分兩種：<strong>描述性數字</strong>報告現狀（「目前有 9 個函式」），程式碼一變就過時；<strong>規範性數字</strong>規定目標值（「P99 &lt; 200ms」「委員固定 7 人」「MAX_DEPTH=3」），是被定義的對象，該保留。</p>
<hr>
<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡的論述基於 <strong>2 個 case</strong>（parallel-evaluation SKILL.md 常駐委員定義 + W3-008 分析報告）抽出來的觀察，每個子論點（列舉 / 數字）各只有 1 個 case 支撐。具體限制：</p>
<ul>
<li><strong>「列舉」指的是定義型文件中的冗餘列舉</strong>（如「所有情境（A-G）」），不包含報告格式範本中的 placeholder（如「情境: [A-G]」）——後者是填空欄位、不是定義；也不包含本身就是定義的封閉列舉（如 enum 成員清單）</li>
<li><strong>「數字」指的是描述性計數</strong>（如「9 個函式」「428 行」），不包含規範性數字（如「MAX_DEPTH=3」「P99 &lt; 200ms」）——後者是設計決策或 SLA 目標、不是統計快照</li>
<li><strong>推理殘留不限於 AI 寫作</strong>：兩個 case 都來自 AI 生成的文件、AI 的生成順序可能讓這類殘留更常出現（見下方觀察），但人類作者在撰寫定義時同樣會先列舉確認再寫結論、忘了刪除中間產物</li>
</ul>
<hr>
<h2 id="觸發案例">觸發案例</h2>
<h3 id="case-1常駐委員定義的冗餘列舉">Case 1：常駐委員定義的冗餘列舉</h3>
<p>parallel-evaluation SKILL.md 常駐委員表格寫了「所有情境（A-G）無條件加入」。「所有情境」已是完整定義，「（A-G）」在語意上重複——拿掉後讀者理解不受影響。留在文件裡則變成維護債務：新增情境 H 時「（A-G）」過時，讀者可能誤判 H 不含。</p>
<p><strong>修正</strong>：刪除「（A-G）」。「所有情境無條件加入」自動涵蓋未來新增的情境。</p>
<h3 id="case-2分析報告的數字快照">Case 2：分析報告的數字快照</h3>
<p>W3-008 分析報告寫了「duplicate_detection 群組 9 個函式、428 行」。這是分析時的統計快照、作為報告紀錄合理。但如果這些數字被寫進 ticket 驗收條件（「duplicate_detector.py 含 9 個函式」「create.py 行數減少約 428 行」），重構過程中任何函式增減都會讓驗收條件失效。</p>
<p><strong>判讀</strong>：分析報告中的數字 → 保留（紀錄）。驗收條件中的描述性計數 → 改用結構性斷言（「所有 duplicate 相關函式已移至新模組」「既有測試通過」）。</p>
<hr>
<h2 id="ai-生成的順序觀察">AI 生成的順序觀察</h2>
<p>兩個 case 都來自 AI 生成的文件。AI 的生成順序是<strong>先推理 → 再生成文字</strong>——模型在寫「所有情境無條件加入」之前，內部已驗證了 A 到 G 都涵蓋，列舉是推理的副產物被寫進生成的文字裡。同理，AI 在寫函式列表時傾向先數數量再列內容（「9 個函式：_tokenize, &hellip;」），數量是為了自我驗證完整性，但讀者只需要函式列表本身。</p>
<p>人類作者在撰寫定義時也會先列舉確認涵蓋範圍、AI 是否讓此模式更頻繁出現仍待更多樣本驗證（見限制段）。無論成因，判準相同：拿掉後讀者理解不受影響 → 刪除。</p>
<hr>
<h2 id="判斷決策表">判斷決策表</h2>
<table>
  <thead>
      <tr>
          <th>文件類型</th>
          <th>列舉/數字的角色</th>
          <th>行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>定義型（規則、規格、常駐名單）</td>
          <td>推理殘留</td>
          <td>刪除——定義本身已完整</td>
      </tr>
      <tr>
          <td>報告型（分析、日誌、檢討）</td>
          <td>紀錄快照</td>
          <td>保留——讀者需要知道當時的狀態</td>
      </tr>
      <tr>
          <td>驗收條件</td>
          <td>依被測屬性判斷</td>
          <td>穩定屬性（函式名稱清單）→ 保留；易變屬性（行數、計數）→ 改結構性斷言</td>
      </tr>
      <tr>
          <td>範本 placeholder</td>
          <td>填空欄位</td>
          <td>保留——提示使用者填入具體值</td>
      </tr>
  </tbody>
</table>
<p>驗收條件的判斷依據是<strong>被測屬性是否隨重構變動</strong>。函式名稱清單在重構後仍可驗證（名稱沒變、只是搬家），但行數和函式計數會因任何增減而失效——改用結構性斷言（「所有 X 相關函式已移至新模組」）讓驗收條件跟重構過程解耦。</p>
<p>真實文件常混合定義段與分析段（如 SKILL.md 同時有規則定義和設計紀錄），分類單位是<strong>段落</strong>而非整份文件——同一份文件內的定義段套用刪除判準、分析段保留數字。範本 placeholder 同理，它是填空欄位、不是定義。</p>
<hr>
<h2 id="跟其他原則的關係">跟其他原則的關係</h2>
<ul>
<li><a href="/blog/report/reader-does-not-need-to-know/" data-link-title="讀者不需要知道 — 刪除比解釋更尊重讀者" data-link-desc="「整理目的」blockquote 告訴讀者這篇文章的寫作動機和邊界。但讀者不需要知道作者為什麼寫這篇文章——他們需要知道讀完能帶走什麼。meta 資訊（寫作動機、邊界聲明、脈絡解釋）服務的是作者的組織需求，不是讀者的閱讀需求。">讀者不需要知道的資訊不該出現在最終文件</a> — 同根原則的兩種表現：該卡處理 meta 動機殘留（「為什麼寫這篇」）、本卡處理推理過程殘留（列舉和數字）。兩者共用「拿掉後讀者體驗變不變差」的判準</li>
<li><a href="/blog/report/applicability-scope-must-be-enumerated/" data-link-title="適用範圍要展開成 file enumeration、口語描述不夠" data-link-desc="原則的『適用範圍』寫成口語描述（『所有教學文件的論證段落』）時、執行 review 的人要當場推導『具體哪些檔屬於這個範圍』、推導步驟容易漏；改寫成 enumerated file list（具體列出 file paths）就能避免 enumeration 不完整。Enumerate 的合法形式是『可被 grep / find 重現的具體 file 集合』、不是『口語類型描述』。本卡是 #95 的下游具體化、跟 #82 互補：enumerate 是字面層、enumeration completeness 是行為層判準。">適用範圍要展開成 file enumeration</a> — 鏡像關係：該卡主張「適用範圍要 enumerate」、本卡主張「定義型文件的冗餘列舉要刪」。取決於文件型別——scope 文件需要 enumeration 確保執行時不遺漏、定義型文件的範圍已由定義本身表達</li>
<li><a href="/blog/report/name-collections-by-role-not-count/" data-link-title="集合命名用角色、不內嵌數量：「核心七問」的七是成員數的 derivation、加一問就全面失真" data-link-desc="「核心七問」「成長六階段」「四大支柱」這類名稱把成員數量烤進名字裡 — 數量是集合當前成員的 derivation、不是集合的語意身分；成員增減時名稱失真、且名稱是被複製最多次的字串、缺陷隨每次引用繁殖。修法：命名只承載角色與層級（核心問題 / 次要問題 / 撞牆階段）、數量讓清單自己呈現。本卡是 #155 的命名端 sibling（#155 修引用端、本卡讓「語意標題是穩定錨」的前提真正成立）、#44 SSoT 在名稱內容的實例、#84 命名檢驗的數量維度。">集合命名用角色、不內嵌數量</a> — 同原則在不同層面：前者處理命名層（「六大原則」的數字是成員清單的衍生值）、本卡處理正文定義層（「9 個函式」的數字是程式碼的衍生值）。兩卡共享「外部凍結數字可留」的邊界（前者的 SOLID / OWASP 對應本卡的 SLA / 設計常數）</li>
<li><a href="/blog/report/ease-of-writing-vs-intent-alignment/" data-link-title="寫作便利度跟意圖對齊反相關" data-link-desc="寫程式時最容易寫出的版本、通常是離意圖最遠的版本。便利度建立在「現有上下文 / 已 materialize 資料 / 已存在 API」上、而意圖對齊需要找到正確的層、處理上游、跨抽象層 — 兩者方向相反。識別這個反相關 = 識別自己掉進「容易寫的陷阱」。">便利驅動的寫法會偏離意圖</a> — 上位原則：列舉殘留是「寫的時候方便（先算再寫）、讀的時候多餘」的具體實例</li>
</ul>
]]></content:encoded></item><item><title>讀者是缺經驗的專業人士、不是外行人</title><link>https://tarrragon.github.io/blog/report/audience-is-professional-not-layperson/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/audience-is-professional-not-layperson/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自 infra 教學模組的寫作 retrospective。21 篇文章初稿完成後，入門層文章（「個人專案到團隊服務」「一台機器到三個環境」）和溝通層文章（「給非工程人員的 infra 說明」）採用了宣導式框架（故事線導入、辦公室比喻、「跑得好好的」語氣），經作者 review 判定不適合目標讀者，重寫為「補足專業人士經驗缺口」的框架。限制：evidence 來自單一教學模組的一次重寫週期，跨領域適用性未驗證。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>技術教材的讀者是在特定領域缺乏經驗的專業人士，不是完全不懂的外行人。他們有系統思考能力、理解風險與成本、能處理抽象概念，只是沒有經歷過這個領域的具體情境。&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;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>科普宣導&lt;/td>
 &lt;td>讀者不懂、需要被說服&lt;/td>
 &lt;td>降低可信度 — 專業人士感到被低估&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>經驗補足&lt;/td>
 &lt;td>讀者有能力判斷、缺的是情境&lt;/td>
 &lt;td>建立信任 — 讀者在熟悉的認知框架裡接收新資訊&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>infra 教學模組的入門層文章原本採用宣導式框架：&lt;/p>
&lt;ul>
&lt;li>「一台機器跑得好好的」— 預設讀者沒想過為什麼需要多環境&lt;/li>
&lt;li>「個人專案到團隊服務：infra 在哪裡出現」— 用 side project 故事引導讀者「發現」infra&lt;/li>
&lt;li>「用辦公室理解 infra」— 用辦公大樓、門禁卡、資產清冊比喻 VPC、IAM、state&lt;/li>
&lt;/ul>
&lt;p>這些框架的問題是它們預設讀者既不知道 infra 存在、也無法理解技術概念。但教材的目標讀者是專業工程師（缺 infra 經驗但有系統思考能力）和專業決策者（缺技術細節但懂營運風險）。宣導式語氣對這兩類讀者都是失配。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;h3 id="對工程師讀者">對工程師讀者&lt;/h3>
&lt;p>直接描述情境和操作需求，不用故事線包裝。不說「跑得好好的、直到有一天…」，而說「單機環境在需要測試環境時會遇到三個操作問題」。讀者有能力從情境描述中自行判斷這跟自己的關聯。&lt;/p>
&lt;p>每個概念用「它解什麼問題、不管理時的後果」框架帶入，不用「你可能沒注意到，其實你已經在用…」的發現式框架。後者暗示讀者對自己的工作環境不熟悉。&lt;/p>
&lt;h3 id="對非工程決策者">對非工程決策者&lt;/h3>
&lt;p>減少專業術語、讓討論的情境從簡單到複雜遞進，而非大量使用比喻。比喻的問題是它只傳遞形狀、不傳遞嚴重性 — 「VPC 像辦公大樓」讓人理解隔離的概念，但不讓人理解隔離失敗時的商業代價。從管理層面解釋「會發生什麼事、為什麼要避免、發生了怎麼處理」比從技術層面解釋「這個元件是什麼」有效。&lt;/p>
&lt;p>決策者需要的資訊是：這個風險的量級（影響多少客戶、停多久、多少錢）、補救的成本曲線（現在做 vs 半年後做的差距）、以及投入的時間框架。這些都是他們熟悉的決策維度，用這些維度講就好。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;p>宣導式寫法的具體代價：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>可信度損失&lt;/strong>：工程師讀到「你可能不知道」時，如果他其實知道（只是沒做過），教材在他心中的權威性立刻下降。一旦開頭失去信任，後面的技術判準也會被打折。&lt;/li>
&lt;li>&lt;strong>比喻阻礙深度理解&lt;/strong>：讀者記住了「VPC 像辦公大樓」，但當他需要判斷 CIDR 該切多大、需不需要跟其他 VPC peering 時，比喻反而成為思考的障礙 — 辦公大樓沒有地址空間的概念。&lt;/li>
&lt;li>&lt;strong>推動失效&lt;/strong>：infra 推不動的原因是「提案語言跟決策者語言對不上」，不是「決策者太笨聽不懂」。把溝通問題歸因成理解力問題，會導致越比喻越多、越比喻越離題。&lt;/li>
&lt;/ul>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>寫教材時如果發現自己在用以下句型，代表可能掉進了宣導式框架：&lt;/p>
&lt;ul>
&lt;li>「你可能沒注意到…」「你可能不知道…」— 預設讀者無知&lt;/li>
&lt;li>「想像一下…」「把 X 想成 Y…」— 用比喻替代直接說明&lt;/li>
&lt;li>「跑得好好的」「聽起來很複雜」— 用語氣管理讀者情緒&lt;/li>
&lt;li>「其實很簡單」「說穿了就是」— 降低複雜度的假象&lt;/li>
&lt;/ul>
&lt;p>替代方式：直接描述情境、列出操作需求、說明不做的後果。讀者有能力從事實中得出判斷。&lt;/p>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/register-violation-needs-cross-style-eyes/" data-link-title="register 違規：偵測可機械化、判定要靠文體異源的眼睛" data-link-desc="寫作規範的違規分兩類：形式違規（emoji / 編號 / broken link）可完全機械判定、該進工具鏈；register / 品味違規（概念前置 / 否定起手 / 喊話 / 誇飾）的判定有不可消除的品味核心。「不是 X、而是 Y」的陷阱是偵測可機械化（grep 抓得到句型）偽裝成判定可機械化、誘導無限投入更精緻的判定方法（grep → 概念位置 → 行為測試）、但判定始終在品味側、始終放水。更深一層：產出這類違規的 LLM 跟審查它的 LLM 共享文體直覺、同源自審對 register 違規有結構上限、加再多輪次都跨不過。結構解是引入文體異源的視角（人類冷讀 / reader-simulation / 對抗文體 reviewer）、並接受 100% 自動 catch 不可能。">#165 register 違規需要跨文體視角&lt;/a>：宣導語氣是一種 register 問題 — LLM 自然傾向「對讀者友善」的語氣，自審時很難察覺它已經偏向宣導&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/lead-with-the-point-cross-language/" data-link-title="重點優先陳述是跨語言的資訊結構原則、不是中文句型問題" data-link-desc="正向陳述優先的本質是資訊結構效率：讀者拿到核心概念的認知步驟越少越好。「不是 X、而是 Y」表達能力差、是因為它讓讀者先處理一個被否定的錯誤理解 X 才拿到正確的 Y、重點後置多繞一步。這個缺陷跨語言成立——英文 not X but Y、日文 X ではなく Y 同樣高頻、換語言不打破（證偽過的反例假設）。判別線是「核心概念在不在最前」、統一了 #94（重點先行合法）與 #149（重點後置違規）、且可操作。LLM 系統性放水的根因是高頻偏置（把語料高頻句型評為表達好、高頻不等於資訊結構優、跨語言）。主解是強制執行重點位置判準、#165 的異源視角降為補充。">#166 重點先行是跨語言的資訊結構&lt;/a>：宣導式框架常把重點藏在故事線之後（「跑得好好的…直到…」），經驗補足式直接把操作需求放句首&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/teaching-register-states-not-addresses-reader/" data-link-title="教材用中性陳述、不對讀者喊話" data-link-desc="教材的 register 是中性陳述概念、不是對讀者說話。三種對讀者喊話的形式 —— 安撫情緒（很多人卡在）、第二人稱代入（你天天寫）、祈使控制閱讀（先讀懂 / 別搞混）—— 表面不同、共同違反是把讀者當成要管理的對話對象、而非把概念講清楚。問題不在精度（「你天天寫的 int count」精度完全正確）、在 stance。修法是換成中性陳述（常見的 int count）或描述性名詞標題（簽章的型別與名字拆解）。邊界：hook / narrative 段落的輕度第二人稱可幫讀者進入、不一律禁。">教材用中性陳述、不對讀者喊話&lt;/a>：宣導語氣跟喊話是相鄰問題 — 都源自「讀者需要被管理」的隱含假設&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自 infra 教學模組的寫作 retrospective。21 篇文章初稿完成後，入門層文章（「個人專案到團隊服務」「一台機器到三個環境」）和溝通層文章（「給非工程人員的 infra 說明」）採用了宣導式框架（故事線導入、辦公室比喻、「跑得好好的」語氣），經作者 review 判定不適合目標讀者，重寫為「補足專業人士經驗缺口」的框架。限制：evidence 來自單一教學模組的一次重寫週期，跨領域適用性未驗證。</p>
<h2 id="核心原則">核心原則</h2>
<p>技術教材的讀者是在特定領域缺乏經驗的專業人士，不是完全不懂的外行人。他們有系統思考能力、理解風險與成本、能處理抽象概念，只是沒有經歷過這個領域的具體情境。</p>
<p>寫法的差別在於進入方式：</p>
<table>
  <thead>
      <tr>
          <th>寫法</th>
          <th>預設</th>
          <th>效果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>科普宣導</td>
          <td>讀者不懂、需要被說服</td>
          <td>降低可信度 — 專業人士感到被低估</td>
      </tr>
      <tr>
          <td>經驗補足</td>
          <td>讀者有能力判斷、缺的是情境</td>
          <td>建立信任 — 讀者在熟悉的認知框架裡接收新資訊</td>
      </tr>
  </tbody>
</table>
<h2 id="情境">情境</h2>
<p>infra 教學模組的入門層文章原本採用宣導式框架：</p>
<ul>
<li>「一台機器跑得好好的」— 預設讀者沒想過為什麼需要多環境</li>
<li>「個人專案到團隊服務：infra 在哪裡出現」— 用 side project 故事引導讀者「發現」infra</li>
<li>「用辦公室理解 infra」— 用辦公大樓、門禁卡、資產清冊比喻 VPC、IAM、state</li>
</ul>
<p>這些框架的問題是它們預設讀者既不知道 infra 存在、也無法理解技術概念。但教材的目標讀者是專業工程師（缺 infra 經驗但有系統思考能力）和專業決策者（缺技術細節但懂營運風險）。宣導式語氣對這兩類讀者都是失配。</p>
<h2 id="理想做法">理想做法</h2>
<h3 id="對工程師讀者">對工程師讀者</h3>
<p>直接描述情境和操作需求，不用故事線包裝。不說「跑得好好的、直到有一天…」，而說「單機環境在需要測試環境時會遇到三個操作問題」。讀者有能力從情境描述中自行判斷這跟自己的關聯。</p>
<p>每個概念用「它解什麼問題、不管理時的後果」框架帶入，不用「你可能沒注意到，其實你已經在用…」的發現式框架。後者暗示讀者對自己的工作環境不熟悉。</p>
<h3 id="對非工程決策者">對非工程決策者</h3>
<p>減少專業術語、讓討論的情境從簡單到複雜遞進，而非大量使用比喻。比喻的問題是它只傳遞形狀、不傳遞嚴重性 — 「VPC 像辦公大樓」讓人理解隔離的概念，但不讓人理解隔離失敗時的商業代價。從管理層面解釋「會發生什麼事、為什麼要避免、發生了怎麼處理」比從技術層面解釋「這個元件是什麼」有效。</p>
<p>決策者需要的資訊是：這個風險的量級（影響多少客戶、停多久、多少錢）、補救的成本曲線（現在做 vs 半年後做的差距）、以及投入的時間框架。這些都是他們熟悉的決策維度，用這些維度講就好。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<p>宣導式寫法的具體代價：</p>
<ul>
<li><strong>可信度損失</strong>：工程師讀到「你可能不知道」時，如果他其實知道（只是沒做過），教材在他心中的權威性立刻下降。一旦開頭失去信任，後面的技術判準也會被打折。</li>
<li><strong>比喻阻礙深度理解</strong>：讀者記住了「VPC 像辦公大樓」，但當他需要判斷 CIDR 該切多大、需不需要跟其他 VPC peering 時，比喻反而成為思考的障礙 — 辦公大樓沒有地址空間的概念。</li>
<li><strong>推動失效</strong>：infra 推不動的原因是「提案語言跟決策者語言對不上」，不是「決策者太笨聽不懂」。把溝通問題歸因成理解力問題，會導致越比喻越多、越比喻越離題。</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>寫教材時如果發現自己在用以下句型，代表可能掉進了宣導式框架：</p>
<ul>
<li>「你可能沒注意到…」「你可能不知道…」— 預設讀者無知</li>
<li>「想像一下…」「把 X 想成 Y…」— 用比喻替代直接說明</li>
<li>「跑得好好的」「聽起來很複雜」— 用語氣管理讀者情緒</li>
<li>「其實很簡單」「說穿了就是」— 降低複雜度的假象</li>
</ul>
<p>替代方式：直接描述情境、列出操作需求、說明不做的後果。讀者有能力從事實中得出判斷。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li>→ <a href="/blog/report/register-violation-needs-cross-style-eyes/" data-link-title="register 違規：偵測可機械化、判定要靠文體異源的眼睛" data-link-desc="寫作規範的違規分兩類：形式違規（emoji / 編號 / broken link）可完全機械判定、該進工具鏈；register / 品味違規（概念前置 / 否定起手 / 喊話 / 誇飾）的判定有不可消除的品味核心。「不是 X、而是 Y」的陷阱是偵測可機械化（grep 抓得到句型）偽裝成判定可機械化、誘導無限投入更精緻的判定方法（grep → 概念位置 → 行為測試）、但判定始終在品味側、始終放水。更深一層：產出這類違規的 LLM 跟審查它的 LLM 共享文體直覺、同源自審對 register 違規有結構上限、加再多輪次都跨不過。結構解是引入文體異源的視角（人類冷讀 / reader-simulation / 對抗文體 reviewer）、並接受 100% 自動 catch 不可能。">#165 register 違規需要跨文體視角</a>：宣導語氣是一種 register 問題 — LLM 自然傾向「對讀者友善」的語氣，自審時很難察覺它已經偏向宣導</li>
<li>→ <a href="/blog/report/lead-with-the-point-cross-language/" data-link-title="重點優先陳述是跨語言的資訊結構原則、不是中文句型問題" data-link-desc="正向陳述優先的本質是資訊結構效率：讀者拿到核心概念的認知步驟越少越好。「不是 X、而是 Y」表達能力差、是因為它讓讀者先處理一個被否定的錯誤理解 X 才拿到正確的 Y、重點後置多繞一步。這個缺陷跨語言成立——英文 not X but Y、日文 X ではなく Y 同樣高頻、換語言不打破（證偽過的反例假設）。判別線是「核心概念在不在最前」、統一了 #94（重點先行合法）與 #149（重點後置違規）、且可操作。LLM 系統性放水的根因是高頻偏置（把語料高頻句型評為表達好、高頻不等於資訊結構優、跨語言）。主解是強制執行重點位置判準、#165 的異源視角降為補充。">#166 重點先行是跨語言的資訊結構</a>：宣導式框架常把重點藏在故事線之後（「跑得好好的…直到…」），經驗補足式直接把操作需求放句首</li>
<li>→ <a href="/blog/report/teaching-register-states-not-addresses-reader/" data-link-title="教材用中性陳述、不對讀者喊話" data-link-desc="教材的 register 是中性陳述概念、不是對讀者說話。三種對讀者喊話的形式 —— 安撫情緒（很多人卡在）、第二人稱代入（你天天寫）、祈使控制閱讀（先讀懂 / 別搞混）—— 表面不同、共同違反是把讀者當成要管理的對話對象、而非把概念講清楚。問題不在精度（「你天天寫的 int count」精度完全正確）、在 stance。修法是換成中性陳述（常見的 int count）或描述性名詞標題（簽章的型別與名字拆解）。邊界：hook / narrative 段落的輕度第二人稱可幫讀者進入、不一律禁。">教材用中性陳述、不對讀者喊話</a>：宣導語氣跟喊話是相鄰問題 — 都源自「讀者需要被管理」的隱含假設</li>
</ul>
]]></content:encoded></item><item><title>技術教材要內嵌管理層可彙報的資訊</title><link>https://tarrragon.github.io/blog/report/technical-content-needs-management-reportable-info/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/technical-content-needs-management-reportable-info/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自 infra 教學模組的管理層視角掃描。22 篇技術文章完成三輪審查後，掃描「管理層會問什麼」發現 10 處缺口，集中在成本量級和時程估算。限制：evidence 來自單一教學模組；成本數字（AWS 定價）有時效性，寫入教材後需要維護。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>技術教材的讀者通常需要向上彙報：為什麼要做這件事、要花多久、花多少錢、做完怎麼知道有效果。如果教材只講技術機制（怎麼寫 HCL、怎麼設 IAM），讀者學會了做法卻沒有素材向管理層說明，結果是做法正確但推不動——因為管理層沒拿到他們決策需要的資訯。&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;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>成本量級&lt;/td>
 &lt;td>「這個選項每月多花多少？」&lt;/td>
 &lt;td>緊接取捨討論段，用量級而非精確數&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>時程估算&lt;/td>
 &lt;td>「導入/遷移/拆分要多久？」&lt;/td>
 &lt;td>緊接操作流程段，給範圍不給單點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>進度指標&lt;/td>
 &lt;td>「怎麼知道有在進步？」&lt;/td>
 &lt;td>治理或 review 流程段&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>決策簽核點&lt;/td>
 &lt;td>「這個決定要不要上層同意？」&lt;/td>
 &lt;td>影響全組織的架構決策段&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>infra 教學模組的 22 篇文章完成三輪寫作審查（compliance / cadence / steelman）後，從管理層視角掃描發現：&lt;/p>
&lt;ul>
&lt;li>NAT per-AZ vs 共享的段落講了可用性取捨，但沒說每個 NAT Gateway 月費約 $32——管理層看不到這筆錢的量級&lt;/li>
&lt;li>環境拆分的 retrofit 路徑講了操作步驟，但沒給時程估算——管理層問「要多久」時工程師得另外估&lt;/li>
&lt;li>tagging 講了為什麼要標，但沒說怎麼量化進度——管理層沒有可追蹤的指標&lt;/li>
&lt;li>跨帳號策略講了 SCP 怎麼設，但沒標記這是需要 CTO 對齊的決策——工程師可能自己決定了影響全組織的設定&lt;/li>
&lt;/ul>
&lt;p>這些缺口的共同模式是：技術內容本身完整，但缺少讓讀者「帶出去用」的彙報素材。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>在技術段落旁邊嵌入管理層資訊，用 1-2 句帶過量級，不獨立成段。嵌入而非集中的理由是：工程師讀到技術取捨時，同時拿到彙報素材，不需要翻到另一篇文章去找對應的商業論證。&lt;/p>
&lt;p>成本用量級而非精確數字。「每個 NAT Gateway 月費約 $32」比「$31.54/月」有用——量級讓管理層判斷這是百元級、千元級還是萬元級的決策，精確數字會隨定價調整而過時。&lt;/p>
&lt;p>時程用範圍而非單點。「1-2 週」比「10 天」誠實——infra 工作的時程變數主要來自 stateful 資源的數量和 drift 的嚴重度，這些在動工前無法精確預估。&lt;/p>
&lt;p>進度用可查詢的指標。「缺 tag 資源數 / 總資源數」比「我們在做 tagging」可追蹤——管理層需要的是趨勢線，不是狀態報告。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>推動卡在溝通&lt;/strong>：工程師學會了怎麼做 IaC，但在預算會議上說不出「導入要 2-3 天、第一個里程碑是一條指令重建環境」，管理層聽到的是一個沒有時間框架的技術提案&lt;/li>
&lt;li>&lt;strong>成本決策沒有量級感&lt;/strong>：multi-AZ RDS 費用翻倍、NAT per-AZ 三倍固定費——這些取捨在技術上有道理，但管理層需要知道「翻倍是從 $50 到 $100 還是從 $5000 到 $10000」才能判斷值不值得&lt;/li>
&lt;li>&lt;strong>進度不可見&lt;/strong>：infra 工作的中間產出（state 設好了、第一批資源 import 了）對管理層不可見，看起來像「花了兩週什麼都沒產出」。有量化指標（覆蓋率從 40% 到 70%）才能讓進度可追蹤&lt;/li>
&lt;/ul>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>寫技術教材時，對每個取捨段落問兩個問題：&lt;/p>
&lt;ul>
&lt;li>「讀者的老闆會問什麼？」——如果答案是「多少錢」或「多久」而段落裡沒有，就是缺口&lt;/li>
&lt;li>「這個決定影響範圍多大？」——如果影響跨團隊或跨帳號，標記為需簽核的決策點&lt;/li>
&lt;/ul>
&lt;p>成本數字寫入教材後要標明是量級參考而非精確報價，避免讀者直接拿去做預算。雲端定價會變，量級通常穩定——$30/月級的服務不太會跳到 $300/月。&lt;/p>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/audience-is-professional-not-layperson/" data-link-title="讀者是缺經驗的專業人士、不是外行人" data-link-desc="技術教材的讀者定位應該是「在這個領域缺乏經驗的專業人士」，不是「完全不懂的外行人」。寫法是補足經驗缺口、不是從零科普。宣導式語氣（跑得好好的、你可能不知道）預設讀者無能，實際上會降低教材的可信度。">讀者是缺經驗的專業人士、不是外行人&lt;/a>：本卡是該原則的延伸——讀者是專業人士，他們的工作流程包含向上彙報，教材應該支援這個流程&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/cross-expertise-communication-scenario-not-analogy/" data-link-title="跨專業溝通用情境遞進、不用比喻堆疊" data-link-desc="向非本領域的專業人士解釋技術議題時，減少術語並從簡單情境遞進到複雜情境，比堆疊比喻有效。比喻傳遞形狀但不傳遞嚴重性；情境遞進讓對方用自己熟悉的決策框架（成本、風險、時間）消化資訊。">跨專業溝通用情境遞進、不用比喻堆疊&lt;/a>：管理層資訊用量級和範圍表達，不用比喻——「月費約 $32」比「大約一頓飯的錢」精確且專業&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/infra/09-driving-adoption/infra-business-justification/" data-link-title="infra 投資的商業論證" data-link-desc="用成本、風險、速度三條論述線把 infra 投資翻譯成商業語言，附一頁簡報邏輯與常見反對意見的回應">infra 投資的商業論證&lt;/a>：該文集中處理商業論證，本卡講的是把商業素材分散嵌入技術段落，兩者互補&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自 infra 教學模組的管理層視角掃描。22 篇技術文章完成三輪審查後，掃描「管理層會問什麼」發現 10 處缺口，集中在成本量級和時程估算。限制：evidence 來自單一教學模組；成本數字（AWS 定價）有時效性，寫入教材後需要維護。</p>
<h2 id="核心原則">核心原則</h2>
<p>技術教材的讀者通常需要向上彙報：為什麼要做這件事、要花多久、花多少錢、做完怎麼知道有效果。如果教材只講技術機制（怎麼寫 HCL、怎麼設 IAM），讀者學會了做法卻沒有素材向管理層說明，結果是做法正確但推不動——因為管理層沒拿到他們決策需要的資訯。</p>
<p>管理層需要的資訊有四類，跟技術段落的位置關係明確：</p>
<table>
  <thead>
      <tr>
          <th>資訊類型</th>
          <th>管理層的問題</th>
          <th>嵌入位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>成本量級</td>
          <td>「這個選項每月多花多少？」</td>
          <td>緊接取捨討論段，用量級而非精確數</td>
      </tr>
      <tr>
          <td>時程估算</td>
          <td>「導入/遷移/拆分要多久？」</td>
          <td>緊接操作流程段，給範圍不給單點</td>
      </tr>
      <tr>
          <td>進度指標</td>
          <td>「怎麼知道有在進步？」</td>
          <td>治理或 review 流程段</td>
      </tr>
      <tr>
          <td>決策簽核點</td>
          <td>「這個決定要不要上層同意？」</td>
          <td>影響全組織的架構決策段</td>
      </tr>
  </tbody>
</table>
<h2 id="情境">情境</h2>
<p>infra 教學模組的 22 篇文章完成三輪寫作審查（compliance / cadence / steelman）後，從管理層視角掃描發現：</p>
<ul>
<li>NAT per-AZ vs 共享的段落講了可用性取捨，但沒說每個 NAT Gateway 月費約 $32——管理層看不到這筆錢的量級</li>
<li>環境拆分的 retrofit 路徑講了操作步驟，但沒給時程估算——管理層問「要多久」時工程師得另外估</li>
<li>tagging 講了為什麼要標，但沒說怎麼量化進度——管理層沒有可追蹤的指標</li>
<li>跨帳號策略講了 SCP 怎麼設，但沒標記這是需要 CTO 對齊的決策——工程師可能自己決定了影響全組織的設定</li>
</ul>
<p>這些缺口的共同模式是：技術內容本身完整，但缺少讓讀者「帶出去用」的彙報素材。</p>
<h2 id="理想做法">理想做法</h2>
<p>在技術段落旁邊嵌入管理層資訊，用 1-2 句帶過量級，不獨立成段。嵌入而非集中的理由是：工程師讀到技術取捨時，同時拿到彙報素材，不需要翻到另一篇文章去找對應的商業論證。</p>
<p>成本用量級而非精確數字。「每個 NAT Gateway 月費約 $32」比「$31.54/月」有用——量級讓管理層判斷這是百元級、千元級還是萬元級的決策，精確數字會隨定價調整而過時。</p>
<p>時程用範圍而非單點。「1-2 週」比「10 天」誠實——infra 工作的時程變數主要來自 stateful 資源的數量和 drift 的嚴重度，這些在動工前無法精確預估。</p>
<p>進度用可查詢的指標。「缺 tag 資源數 / 總資源數」比「我們在做 tagging」可追蹤——管理層需要的是趨勢線，不是狀態報告。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<ul>
<li><strong>推動卡在溝通</strong>：工程師學會了怎麼做 IaC，但在預算會議上說不出「導入要 2-3 天、第一個里程碑是一條指令重建環境」，管理層聽到的是一個沒有時間框架的技術提案</li>
<li><strong>成本決策沒有量級感</strong>：multi-AZ RDS 費用翻倍、NAT per-AZ 三倍固定費——這些取捨在技術上有道理，但管理層需要知道「翻倍是從 $50 到 $100 還是從 $5000 到 $10000」才能判斷值不值得</li>
<li><strong>進度不可見</strong>：infra 工作的中間產出（state 設好了、第一批資源 import 了）對管理層不可見，看起來像「花了兩週什麼都沒產出」。有量化指標（覆蓋率從 40% 到 70%）才能讓進度可追蹤</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>寫技術教材時，對每個取捨段落問兩個問題：</p>
<ul>
<li>「讀者的老闆會問什麼？」——如果答案是「多少錢」或「多久」而段落裡沒有，就是缺口</li>
<li>「這個決定影響範圍多大？」——如果影響跨團隊或跨帳號，標記為需簽核的決策點</li>
</ul>
<p>成本數字寫入教材後要標明是量級參考而非精確報價，避免讀者直接拿去做預算。雲端定價會變，量級通常穩定——$30/月級的服務不太會跳到 $300/月。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li>→ <a href="/blog/report/audience-is-professional-not-layperson/" data-link-title="讀者是缺經驗的專業人士、不是外行人" data-link-desc="技術教材的讀者定位應該是「在這個領域缺乏經驗的專業人士」，不是「完全不懂的外行人」。寫法是補足經驗缺口、不是從零科普。宣導式語氣（跑得好好的、你可能不知道）預設讀者無能，實際上會降低教材的可信度。">讀者是缺經驗的專業人士、不是外行人</a>：本卡是該原則的延伸——讀者是專業人士，他們的工作流程包含向上彙報，教材應該支援這個流程</li>
<li>→ <a href="/blog/report/cross-expertise-communication-scenario-not-analogy/" data-link-title="跨專業溝通用情境遞進、不用比喻堆疊" data-link-desc="向非本領域的專業人士解釋技術議題時，減少術語並從簡單情境遞進到複雜情境，比堆疊比喻有效。比喻傳遞形狀但不傳遞嚴重性；情境遞進讓對方用自己熟悉的決策框架（成本、風險、時間）消化資訊。">跨專業溝通用情境遞進、不用比喻堆疊</a>：管理層資訊用量級和範圍表達，不用比喻——「月費約 $32」比「大約一頓飯的錢」精確且專業</li>
<li>→ <a href="/blog/infra/09-driving-adoption/infra-business-justification/" data-link-title="infra 投資的商業論證" data-link-desc="用成本、風險、速度三條論述線把 infra 投資翻譯成商業語言，附一頁簡報邏輯與常見反對意見的回應">infra 投資的商業論證</a>：該文集中處理商業論證，本卡講的是把商業素材分散嵌入技術段落，兩者互補</li>
</ul>
]]></content:encoded></item><item><title>多輪審查缺 outside-in 讀者 frame：六個系統性盲點</title><link>https://tarrragon.github.io/blog/report/review-lacks-outside-in-reader-frames/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/review-lacks-outside-in-reader-frames/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自 infra 教學模組的完整生產週期 retrospective。43 篇文章 + 21 張知識卡經歷三輪多輪審查（compliance / cadence+冷讀 / steelman+outbound），審查通過後使用者連續指出六個 review 未 catch 的問題，每個都導致大量修改。限制：evidence 來自單一教學模組的一次完整週期，盲點清單可能不窮盡。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>多輪審查框架的所有 frame 從「已寫的內容」出發（inside-out）：字句層看已寫的字、cadence 看已寫的結構、fact-check 看已寫的事實、steelman 看已寫的論述。缺的是從「讀者的完整需求」出發的 frame（outside-in）：讀者是誰、讀者從哪裡來、讀者讀完後要做什麼、讀者搜尋什麼問題。&lt;/p>
&lt;p>inside-out 能保證已寫內容的品質，outside-in 才能發現「應該寫但沒寫」的缺口。兩者的盲區正交：inside-out 的盲區是缺口（看不到不存在的東西），outside-in 的盲區是細節（看不到已寫內容的字句問題）。完整的審查需要兩者交替。&lt;/p>
&lt;h2 id="六個盲點">六個盲點&lt;/h2>
&lt;h3 id="一宣導語氣通過三輪審查">一：宣導語氣通過三輪審查&lt;/h3>
&lt;p>三輪審查判定文章 clean，使用者指出「一台機器跑得好好的」「辦公大樓比喻」是對專業讀者的失配後，14 處需要重寫。&lt;/p>
&lt;p>keyword bank 的設計對象是字面違規。宣導語氣的問題在 register——用教導外行人的姿態對專業人士說話，字面上每個字都合規。reviewer 跟作者共享同一套文體直覺，都覺得「用故事帶入」是好的教學手法，同源盲區讓整批宣導語氣被合理化放行。&lt;/p>
&lt;p>缺的 frame：&lt;strong>reader-persona register 適配&lt;/strong>——指定具體讀者角色，問「這個人讀到這段會覺得被低估嗎」。&lt;/p>
&lt;h3 id="二管理層彙報資訊缺失">二：管理層彙報資訊缺失&lt;/h3>
&lt;p>所有 reviewer 檢查了技術正確性和寫作規範，沒有一個問「讀者讀完後能不能跟老闆說明為什麼要做、要花多久」。使用者提出後掃描出 10 處成本/時程缺口。&lt;/p>
&lt;p>review frame 全部從「內容品質」出發，沒有從「讀者的下游任務」出發。技術文章的讀者不只要「學會怎麼做」，還要「能向上彙報為什麼做」——後者是讀者的工作流程，品質導向的 review 結構性看不到。&lt;/p>
&lt;p>缺的 frame：&lt;strong>downstream-task 審查&lt;/strong>——問「讀者讀完後的下一個動作是什麼？他需要什麼素材？」&lt;/p>
&lt;h3 id="三接手-vs-自建是不同情境">三：接手 vs 自建是不同情境&lt;/h3>
&lt;p>模組負一定位為「還沒有 infra 的手動環境」，所有 reviewer 都接受了這個前提。使用者指出「接手前人的專案」是完全不同的操作情境後，獨立成一個橫切模組。&lt;/p>
&lt;p>review 的 scope 是「已寫的內容對不對」，不質疑結構本身的覆蓋範圍。steelman reviewer 問的是已有文章的論述有沒有漏洞，不是教材的讀者群有沒有被遺漏的情境。&lt;/p>
&lt;p>缺的 frame：&lt;strong>persona-coverage 審查&lt;/strong>——列出目標讀者可能進入教材的情境，檢查每個情境是否有對應入口。&lt;/p>
&lt;h3 id="四操作步驟缺工具指引">四：操作步驟缺工具指引&lt;/h3>
&lt;p>文章寫「拍下現況」「匯出資料庫」，reviewer 確認了邏輯正確性。使用者問「用什麼拍？怎麼拍？」後才發現停在 WHAT 層、沒到 HOW WITH WHAT 層。&lt;/p>
&lt;p>fact-check reviewer 驗證「描述是否正確」，不是「描述是否可執行」。「用 FTP 下載整站存進 Git」事實正確，但讀者照做時需要知道用哪個 FTP client、大檔案怎麼處理。&lt;/p>
&lt;p>缺的 frame：&lt;strong>executable-walkthrough 審查&lt;/strong>——假裝讀者從零照做，每步問「下一個動作是打開什麼軟體、輸入什麼指令」。&lt;/p>
&lt;h3 id="五概覽級深度不拆分">五：概覽級深度不拆分&lt;/h3>
&lt;p>350 行文章涵蓋四個面向，reviewer 認為「結構完整」。使用者指出「資料庫備份和安全管理其實都是大問題」後拆成 5 篇。後續又在 8 個模組發生同樣的拆分。&lt;/p>
&lt;p>reviewer 評估「這篇文章本身好不好」，不是「搜尋特定問題的讀者能不能找到足夠深度的內容」。一篇涵蓋四面向的文章通讀體驗良好，但搜尋「共享主機 MySQL 備份」的讀者需要專題文章。&lt;/p>
&lt;p>缺的 frame：&lt;strong>search-landing 審查&lt;/strong>——列出讀者可能搜尋的具體問題，檢查每個問題能不能落在聚焦的文章上。跟 cold-read (B&amp;rsquo;) 相關但不同——B&amp;rsquo; 看「落地後讀不讀得懂」，這裡看「能不能落地到足夠聚焦的內容」。&lt;/p>
&lt;h3 id="六讀者定位未預設">六：讀者定位未預設&lt;/h3>
&lt;p>「讀者是缺經驗的專業人士」這個原則在文章寫完、審查完、使用者反饋後才抽出來。它影響了語氣、比喻策略、管理層溝通——幾乎所有後續大修都源自這個原則。但它不在任何 reviewer prompt 裡。&lt;/p>
&lt;p>寫作規範定義了「怎麼寫」的規則，沒有定義「寫給誰」——讀者定位被當成隱性決定。LLM 預設用「教外行人」的姿態寫教學內容，這個預設不被 review 挑戰，因為 reviewer 也共享同一個預設。&lt;/p>
&lt;p>這不是 review frame 的問題——是&lt;strong>生成端的前提缺失&lt;/strong>。每個教學模組在第一篇文章生成前就應該顯式聲明讀者定位。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>在現有 inside-out review 框架之外，補五個 outside-in frame：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Frame&lt;/th>
 &lt;th>問什麼&lt;/th>
 &lt;th>在哪個 Round 跑&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Reader persona + register&lt;/td>
 &lt;td>讀者讀到這段會覺得被低估嗎？&lt;/td>
 &lt;td>Round 2（讀者旅程）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Downstream task&lt;/td>
 &lt;td>讀者讀完後要做什麼、需要什麼素材？&lt;/td>
 &lt;td>Round 1（基線 audit）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Persona coverage&lt;/td>
 &lt;td>所有讀者情境都有入口嗎？&lt;/td>
 &lt;td>Round 3（outbound）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Executable walkthrough&lt;/td>
 &lt;td>讀者能從零照做嗎？每步的工具在嗎？&lt;/td>
 &lt;td>Round 2（操作型文章專用）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Search landing&lt;/td>
 &lt;td>搜尋特定問題能落在聚焦文章嗎？&lt;/td>
 &lt;td>Round 3（outbound）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>生成端的修正：每個教學模組在撰寫前顯式聲明「讀者定位文件」（一段話描述目標讀者的背景、已有能力、缺的經驗），讓生成和 review 都有可檢查的基準。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;p>六個盲點的修法總工程量遠超預防成本：14 處宣導語氣重寫 + 10 處管理層資訊補充 + 11 篇接手維運新文章 + 全模組工具補充 + 12 篇子文章拆分 + 3 篇入門/溝通層重寫。如果讀者定位在第一篇文章前就聲明、outside-in frame 在 Round 1 就跑，多數修改可以在初稿階段就避免。&lt;/p>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>review 完成後如果使用者的第一個反饋是關於「內容缺口」而非「內容品質」，代表 review 框架偏向 inside-out。inside-out 的 review 報告 clean 只代表「已寫的內容沒問題」，不代表「該寫的都寫了」。&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自 infra 教學模組的完整生產週期 retrospective。43 篇文章 + 21 張知識卡經歷三輪多輪審查（compliance / cadence+冷讀 / steelman+outbound），審查通過後使用者連續指出六個 review 未 catch 的問題，每個都導致大量修改。限制：evidence 來自單一教學模組的一次完整週期，盲點清單可能不窮盡。</p>
<h2 id="核心原則">核心原則</h2>
<p>多輪審查框架的所有 frame 從「已寫的內容」出發（inside-out）：字句層看已寫的字、cadence 看已寫的結構、fact-check 看已寫的事實、steelman 看已寫的論述。缺的是從「讀者的完整需求」出發的 frame（outside-in）：讀者是誰、讀者從哪裡來、讀者讀完後要做什麼、讀者搜尋什麼問題。</p>
<p>inside-out 能保證已寫內容的品質，outside-in 才能發現「應該寫但沒寫」的缺口。兩者的盲區正交：inside-out 的盲區是缺口（看不到不存在的東西），outside-in 的盲區是細節（看不到已寫內容的字句問題）。完整的審查需要兩者交替。</p>
<h2 id="六個盲點">六個盲點</h2>
<h3 id="一宣導語氣通過三輪審查">一：宣導語氣通過三輪審查</h3>
<p>三輪審查判定文章 clean，使用者指出「一台機器跑得好好的」「辦公大樓比喻」是對專業讀者的失配後，14 處需要重寫。</p>
<p>keyword bank 的設計對象是字面違規。宣導語氣的問題在 register——用教導外行人的姿態對專業人士說話，字面上每個字都合規。reviewer 跟作者共享同一套文體直覺，都覺得「用故事帶入」是好的教學手法，同源盲區讓整批宣導語氣被合理化放行。</p>
<p>缺的 frame：<strong>reader-persona register 適配</strong>——指定具體讀者角色，問「這個人讀到這段會覺得被低估嗎」。</p>
<h3 id="二管理層彙報資訊缺失">二：管理層彙報資訊缺失</h3>
<p>所有 reviewer 檢查了技術正確性和寫作規範，沒有一個問「讀者讀完後能不能跟老闆說明為什麼要做、要花多久」。使用者提出後掃描出 10 處成本/時程缺口。</p>
<p>review frame 全部從「內容品質」出發，沒有從「讀者的下游任務」出發。技術文章的讀者不只要「學會怎麼做」，還要「能向上彙報為什麼做」——後者是讀者的工作流程，品質導向的 review 結構性看不到。</p>
<p>缺的 frame：<strong>downstream-task 審查</strong>——問「讀者讀完後的下一個動作是什麼？他需要什麼素材？」</p>
<h3 id="三接手-vs-自建是不同情境">三：接手 vs 自建是不同情境</h3>
<p>模組負一定位為「還沒有 infra 的手動環境」，所有 reviewer 都接受了這個前提。使用者指出「接手前人的專案」是完全不同的操作情境後，獨立成一個橫切模組。</p>
<p>review 的 scope 是「已寫的內容對不對」，不質疑結構本身的覆蓋範圍。steelman reviewer 問的是已有文章的論述有沒有漏洞，不是教材的讀者群有沒有被遺漏的情境。</p>
<p>缺的 frame：<strong>persona-coverage 審查</strong>——列出目標讀者可能進入教材的情境，檢查每個情境是否有對應入口。</p>
<h3 id="四操作步驟缺工具指引">四：操作步驟缺工具指引</h3>
<p>文章寫「拍下現況」「匯出資料庫」，reviewer 確認了邏輯正確性。使用者問「用什麼拍？怎麼拍？」後才發現停在 WHAT 層、沒到 HOW WITH WHAT 層。</p>
<p>fact-check reviewer 驗證「描述是否正確」，不是「描述是否可執行」。「用 FTP 下載整站存進 Git」事實正確，但讀者照做時需要知道用哪個 FTP client、大檔案怎麼處理。</p>
<p>缺的 frame：<strong>executable-walkthrough 審查</strong>——假裝讀者從零照做，每步問「下一個動作是打開什麼軟體、輸入什麼指令」。</p>
<h3 id="五概覽級深度不拆分">五：概覽級深度不拆分</h3>
<p>350 行文章涵蓋四個面向，reviewer 認為「結構完整」。使用者指出「資料庫備份和安全管理其實都是大問題」後拆成 5 篇。後續又在 8 個模組發生同樣的拆分。</p>
<p>reviewer 評估「這篇文章本身好不好」，不是「搜尋特定問題的讀者能不能找到足夠深度的內容」。一篇涵蓋四面向的文章通讀體驗良好，但搜尋「共享主機 MySQL 備份」的讀者需要專題文章。</p>
<p>缺的 frame：<strong>search-landing 審查</strong>——列出讀者可能搜尋的具體問題，檢查每個問題能不能落在聚焦的文章上。跟 cold-read (B&rsquo;) 相關但不同——B&rsquo; 看「落地後讀不讀得懂」，這裡看「能不能落地到足夠聚焦的內容」。</p>
<h3 id="六讀者定位未預設">六：讀者定位未預設</h3>
<p>「讀者是缺經驗的專業人士」這個原則在文章寫完、審查完、使用者反饋後才抽出來。它影響了語氣、比喻策略、管理層溝通——幾乎所有後續大修都源自這個原則。但它不在任何 reviewer prompt 裡。</p>
<p>寫作規範定義了「怎麼寫」的規則，沒有定義「寫給誰」——讀者定位被當成隱性決定。LLM 預設用「教外行人」的姿態寫教學內容，這個預設不被 review 挑戰，因為 reviewer 也共享同一個預設。</p>
<p>這不是 review frame 的問題——是<strong>生成端的前提缺失</strong>。每個教學模組在第一篇文章生成前就應該顯式聲明讀者定位。</p>
<h2 id="理想做法">理想做法</h2>
<p>在現有 inside-out review 框架之外，補五個 outside-in frame：</p>
<table>
  <thead>
      <tr>
          <th>Frame</th>
          <th>問什麼</th>
          <th>在哪個 Round 跑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Reader persona + register</td>
          <td>讀者讀到這段會覺得被低估嗎？</td>
          <td>Round 2（讀者旅程）</td>
      </tr>
      <tr>
          <td>Downstream task</td>
          <td>讀者讀完後要做什麼、需要什麼素材？</td>
          <td>Round 1（基線 audit）</td>
      </tr>
      <tr>
          <td>Persona coverage</td>
          <td>所有讀者情境都有入口嗎？</td>
          <td>Round 3（outbound）</td>
      </tr>
      <tr>
          <td>Executable walkthrough</td>
          <td>讀者能從零照做嗎？每步的工具在嗎？</td>
          <td>Round 2（操作型文章專用）</td>
      </tr>
      <tr>
          <td>Search landing</td>
          <td>搜尋特定問題能落在聚焦文章嗎？</td>
          <td>Round 3（outbound）</td>
      </tr>
  </tbody>
</table>
<p>生成端的修正：每個教學模組在撰寫前顯式聲明「讀者定位文件」（一段話描述目標讀者的背景、已有能力、缺的經驗），讓生成和 review 都有可檢查的基準。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<p>六個盲點的修法總工程量遠超預防成本：14 處宣導語氣重寫 + 10 處管理層資訊補充 + 11 篇接手維運新文章 + 全模組工具補充 + 12 篇子文章拆分 + 3 篇入門/溝通層重寫。如果讀者定位在第一篇文章前就聲明、outside-in frame 在 Round 1 就跑，多數修改可以在初稿階段就避免。</p>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>review 完成後如果使用者的第一個反饋是關於「內容缺口」而非「內容品質」，代表 review 框架偏向 inside-out。inside-out 的 review 報告 clean 只代表「已寫的內容沒問題」，不代表「該寫的都寫了」。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li>→ <a href="/blog/report/audience-is-professional-not-layperson/" data-link-title="讀者是缺經驗的專業人士、不是外行人" data-link-desc="技術教材的讀者定位應該是「在這個領域缺乏經驗的專業人士」，不是「完全不懂的外行人」。寫法是補足經驗缺口、不是從零科普。宣導式語氣（跑得好好的、你可能不知道）預設讀者無能，實際上會降低教材的可信度。">讀者是缺經驗的專業人士、不是外行人</a>：盲點一和六的直接修法</li>
<li>→ <a href="/blog/report/technical-content-needs-management-reportable-info/" data-link-title="技術教材要內嵌管理層可彙報的資訊" data-link-desc="技術文章的讀者不只要知道怎麼做，還要能向上彙報為什麼做、花多久、花多少。成本量級、時程估算、進度指標與需簽核的決策點應該嵌在技術段落旁邊，而非集中在另一篇溝通指南裡。">技術教材要內嵌管理層可彙報的資訊</a>：盲點二的直接修法</li>
<li>→ <a href="/blog/report/cross-expertise-communication-scenario-not-analogy/" data-link-title="跨專業溝通用情境遞進、不用比喻堆疊" data-link-desc="向非本領域的專業人士解釋技術議題時，減少術語並從簡單情境遞進到複雜情境，比堆疊比喻有效。比喻傳遞形狀但不傳遞嚴重性；情境遞進讓對方用自己熟悉的決策框架（成本、風險、時間）消化資訊。">跨專業溝通用情境遞進、不用比喻堆疊</a>：盲點一的溝通層修法</li>
<li>→ <a href="/blog/report/cross-round-review-stopping-signal/" data-link-title="跨輪 review 停止訊號是 frame 涵蓋、不是 finding 數遞減" data-link-desc="判斷「該不該再來一輪 review」的訊號是『frame 軸是否還有未動』、不是『上一輪 finding 變少』；多輪 review 的 ROI 不是 monotonically decreasing、而是 frame 切換的質性轉換 — Round N 用新 frame 通常仍會抓出 substantial finding、但內容從 surface compliance 往深層 structural issue 走；停止訊號是「下一輪可用的新 frame 已經想不出來」、不是 finding 數遞減；本卡填補 #114 / #126 / #147 沒覆蓋的「何時夠了」判讀缺口">#148 跨輪 review 停止訊號</a>：本卡揭露的是「停止訊號齊備但覆蓋不完整」的情境——frame 涵蓋度的判斷要包含 outside-in frame</li>
<li>→ <a href="/blog/report/review-miss-diagnose-design-vs-execution-gap/" data-link-title="Review 漏抓先分 design gap 與 execution gap、再決定改框架還是改執行" data-link-desc="Review 漏抓某類問題時，有兩個不同成因：design gap（框架根本沒有對應 frame）跟 execution gap（框架有 frame、但 reviewer 沒跑）。修法相反 —— design gap 要改框架（補 frame / keyword）、execution gap 要改執行（真的跑完該跑的輪）。診斷前先分清：把 execution gap 誤判成 design gap 會 framework bloat（一直加 frame 卻沒解決偷跑子集）、把 design gap 誤判成 execution gap 會永遠漏同類。常見陷阱是『加 keyword』感覺像進步、但對沒跑的輪毫無幫助。">#153 Review 漏抓先分 design gap 與 execution gap</a>：六個盲點全部是 design gap（框架缺 frame），不是 execution gap（有 frame 沒跑）</li>
<li>→ <a href="/blog/report/cold-reader-frame-vs-informed-reviewer/" data-link-title="多輪審查要有冷讀者 frame：知情 reviewer 看不見行話洩漏" data-link-desc="多輪審查模擬讀者時要分兩種：知情讀者（讀完全部、走旅程）與冷讀者（經搜尋或直連落在單篇、零脈絡）。知情 reviewer 會自動腦補脈絡，結構性看不見洩漏撰寫者預設前提的行話。原子 / Zettelkasten / glossary 等可被直連抵達的內容，必須額外跑冷讀 frame。">#168 多輪審查要有冷讀者 frame</a>：cold-read 是 outside-in 的一個實例（從零脈絡讀者出發），本卡把這個方向擴展到五個 frame</li>
</ul>
]]></content:encoded></item><item><title>操作指引的「怎麼做」要帶環境專屬的工具路徑</title><link>https://tarrragon.github.io/blog/report/operational-how-needs-environment-specific-tooling/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/operational-how-needs-environment-specific-tooling/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自 infra 接手維運模組的兩次使用者反饋。第一次：文章寫「拍下現況」「建立本地環境」，使用者問「用什麼拍？非 Docker 怎麼做？」——補了 FTP client、本地環境工具選型表、備份自動化指令。第二次：文章寫「拍下完整現況（不動 prod）」，使用者問「如果不是在 container 上運作，怎麼取代拍下來的動作？」——補了 phpinfo 擷取、cron 記錄、AMI 快照、系統軟體清單。兩次反饋的根因相同。限制：evidence 來自單一教學模組。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>操作型教材的一個動作（「拍下現況」「匯出資料庫」「建立備份」）在不同執行環境裡對應完全不同的工具路徑：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>動作&lt;/th>
 &lt;th>Container 環境&lt;/th>
 &lt;th>VM（有 SSH）&lt;/th>
 &lt;th>共享主機（只有 FTP）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>拍下現況&lt;/td>
 &lt;td>&lt;code>docker commit&lt;/code> / image tag&lt;/td>
 &lt;td>AMI / machine image + 軟體清單&lt;/td>
 &lt;td>FTP mirror + phpinfo + cron 截圖&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>匯出資料庫&lt;/td>
 &lt;td>&lt;code>docker exec mysqldump&lt;/code>&lt;/td>
 &lt;td>&lt;code>mysqldump&lt;/code> via SSH&lt;/td>
 &lt;td>phpMyAdmin 匯出（有 timeout 限制）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>定期備份&lt;/td>
 &lt;td>volume snapshot / registry&lt;/td>
 &lt;td>cron + mysqldump + S3&lt;/td>
 &lt;td>本機排程 + lftp mirror&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>查執行環境&lt;/td>
 &lt;td>&lt;code>docker inspect&lt;/code>&lt;/td>
 &lt;td>&lt;code>systemctl&lt;/code> / &lt;code>ss -tlnp&lt;/code>&lt;/td>
 &lt;td>phpinfo + 主機面板&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>只寫動作不寫工具路徑，等於把「選工具」的認知負擔轉嫁給讀者。讀者知道該做「拍下現況」，但坐在電腦前不知道該打開什麼軟體。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>infra 接手維運模組的文章經過三輪多輪審查（compliance / cadence / steelman），所有 reviewer 都判定操作步驟邏輯正確、順序合理。使用者兩次指出同一個缺口：&lt;/p>
&lt;p>第一次：「用什麼拍？怎麼拍？非 Docker 的環境怎麼做？」——三篇文章各補了 15-20 個工具提及，總修改量 138 行。&lt;/p>
&lt;p>第二次：「如果不是在 container 上運作，怎麼取代拍下來的動作？」——兩篇文章各補了環境設定的拍照方法（phpinfo、cron、SSL、AMI 快照、系統套件清單），總修改量 87 行。&lt;/p>
&lt;p>兩次的操作步驟在邏輯層都通過了 fact-check（「拍下現況」這個動作描述正確）和 steelman（「先拍後改」的順序合理）。問題出在「正確」跟「可執行」之間的落差——動作正確不代表讀者能執行，執行需要知道用什麼工具、在什麼環境限制下、有什麼替代方案。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>操作型教材的每一步至少帶一條環境專屬的工具路徑。如果教材涵蓋多種環境（container / VM / 共享主機），每一步要按環境分列工具，或明確標示「本篇的工具路徑適用於 X 環境、Y 環境的做法見另一篇」。&lt;/p>
&lt;p>寫操作步驟時的自測問題：「讀者坐在電腦前、打開這篇文章，下一個動作是啟動什麼軟體或輸入什麼指令？」如果答案是「看情況」，就要把「情況」展開成環境分支。&lt;/p>
&lt;p>生成端的檢查清單（寫完每一步後問）：&lt;/p>
&lt;ul>
&lt;li>這一步的工具是什麼？有沒有寫出來？&lt;/li>
&lt;li>這個工具在目標環境可用嗎？（共享主機沒有 SSH、沒有 CLI）&lt;/li>
&lt;li>如果不可用，替代工具是什麼？&lt;/li>
&lt;li>工具的操作有沒有環境限制？（phpMyAdmin 的 timeout、FTP 的非原子上傳）&lt;/li>
&lt;/ul>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>兩次同根因的返工&lt;/strong>：同一個缺口（動作缺工具）被使用者指出兩次、修了兩輪，因為第一輪只補了「用什麼工具」沒補「在不同環境怎麼替代」。如果第一次就按環境分列工具路徑，第二次不會發生。&lt;/li>
&lt;li>&lt;strong>審查結構性盲區&lt;/strong>：fact-check 驗「正確性」、steelman 驗「完整性」，兩者都不驗「可執行性」。操作型文章的品質門檻比概念型文章多一層——除了正確和完整，還要可執行。這層門檻需要 executable-walkthrough frame（見&lt;a href="https://tarrragon.github.io/blog/report/review-lacks-outside-in-reader-frames/" data-link-title="多輪審查缺 outside-in 讀者 frame：六個系統性盲點" data-link-desc="review 框架的所有 frame 從已寫的內容出發（inside-out），缺從讀者完整需求出發的 frame（outside-in）。六個盲點全部由使用者而非 reviewer 發現：宣導語氣、管理層資訊缺失、接手情境遺漏、工具指引缺失、深度不拆分、讀者定位未預設。">outside-in reader frames report&lt;/a>）。&lt;/li>
&lt;/ul>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>操作型文章裡出現以下動詞但沒有跟著工具名稱或指令，就是候選缺口：&lt;/p>
&lt;p>「拍下」「匯出」「備份」「部署」「掃描」「盤點」「監控」「還原」&lt;/p>
&lt;p>這些動詞描述的都是需要工具才能完成的操作。概念型文章用這些動詞是在描述能力（「IaC 的責任是讓環境可重建」），操作型文章用這些動詞是在指引行動——行動需要工具。&lt;/p>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/review-lacks-outside-in-reader-frames/" data-link-title="多輪審查缺 outside-in 讀者 frame：六個系統性盲點" data-link-desc="review 框架的所有 frame 從已寫的內容出發（inside-out），缺從讀者完整需求出發的 frame（outside-in）。六個盲點全部由使用者而非 reviewer 發現：宣導語氣、管理層資訊缺失、接手情境遺漏、工具指引缺失、深度不拆分、讀者定位未預設。">多輪審查缺 outside-in 讀者 frame&lt;/a>：本卡是該卡盲點四（操作步驟缺工具指引）的具體展開，補充了「為什麼同根因會被指出兩次」的機制&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/technical-content-needs-management-reportable-info/" data-link-title="技術教材要內嵌管理層可彙報的資訊" data-link-desc="技術文章的讀者不只要知道怎麼做，還要能向上彙報為什麼做、花多久、花多少。成本量級、時程估算、進度指標與需簽核的決策點應該嵌在技術段落旁邊，而非集中在另一篇溝通指南裡。">技術教材要內嵌管理層可彙報的資訊&lt;/a>：工具路徑跟管理層資訊是同一類缺口——都是「讀者的下游任務需要但文章沒給的素材」&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/audience-is-professional-not-layperson/" data-link-title="讀者是缺經驗的專業人士、不是外行人" data-link-desc="技術教材的讀者定位應該是「在這個領域缺乏經驗的專業人士」，不是「完全不懂的外行人」。寫法是補足經驗缺口、不是從零科普。宣導式語氣（跑得好好的、你可能不知道）預設讀者無能，實際上會降低教材的可信度。">讀者是缺經驗的專業人士、不是外行人&lt;/a>：專業人士缺的不是概念（「要備份」），而是特定環境下的操作經驗（「共享主機沒有 mysqldump 時怎麼備份」）&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自 infra 接手維運模組的兩次使用者反饋。第一次：文章寫「拍下現況」「建立本地環境」，使用者問「用什麼拍？非 Docker 怎麼做？」——補了 FTP client、本地環境工具選型表、備份自動化指令。第二次：文章寫「拍下完整現況（不動 prod）」，使用者問「如果不是在 container 上運作，怎麼取代拍下來的動作？」——補了 phpinfo 擷取、cron 記錄、AMI 快照、系統軟體清單。兩次反饋的根因相同。限制：evidence 來自單一教學模組。</p>
<h2 id="核心原則">核心原則</h2>
<p>操作型教材的一個動作（「拍下現況」「匯出資料庫」「建立備份」）在不同執行環境裡對應完全不同的工具路徑：</p>
<table>
  <thead>
      <tr>
          <th>動作</th>
          <th>Container 環境</th>
          <th>VM（有 SSH）</th>
          <th>共享主機（只有 FTP）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>拍下現況</td>
          <td><code>docker commit</code> / image tag</td>
          <td>AMI / machine image + 軟體清單</td>
          <td>FTP mirror + phpinfo + cron 截圖</td>
      </tr>
      <tr>
          <td>匯出資料庫</td>
          <td><code>docker exec mysqldump</code></td>
          <td><code>mysqldump</code> via SSH</td>
          <td>phpMyAdmin 匯出（有 timeout 限制）</td>
      </tr>
      <tr>
          <td>定期備份</td>
          <td>volume snapshot / registry</td>
          <td>cron + mysqldump + S3</td>
          <td>本機排程 + lftp mirror</td>
      </tr>
      <tr>
          <td>查執行環境</td>
          <td><code>docker inspect</code></td>
          <td><code>systemctl</code> / <code>ss -tlnp</code></td>
          <td>phpinfo + 主機面板</td>
      </tr>
  </tbody>
</table>
<p>只寫動作不寫工具路徑，等於把「選工具」的認知負擔轉嫁給讀者。讀者知道該做「拍下現況」，但坐在電腦前不知道該打開什麼軟體。</p>
<h2 id="情境">情境</h2>
<p>infra 接手維運模組的文章經過三輪多輪審查（compliance / cadence / steelman），所有 reviewer 都判定操作步驟邏輯正確、順序合理。使用者兩次指出同一個缺口：</p>
<p>第一次：「用什麼拍？怎麼拍？非 Docker 的環境怎麼做？」——三篇文章各補了 15-20 個工具提及，總修改量 138 行。</p>
<p>第二次：「如果不是在 container 上運作，怎麼取代拍下來的動作？」——兩篇文章各補了環境設定的拍照方法（phpinfo、cron、SSL、AMI 快照、系統套件清單），總修改量 87 行。</p>
<p>兩次的操作步驟在邏輯層都通過了 fact-check（「拍下現況」這個動作描述正確）和 steelman（「先拍後改」的順序合理）。問題出在「正確」跟「可執行」之間的落差——動作正確不代表讀者能執行，執行需要知道用什麼工具、在什麼環境限制下、有什麼替代方案。</p>
<h2 id="理想做法">理想做法</h2>
<p>操作型教材的每一步至少帶一條環境專屬的工具路徑。如果教材涵蓋多種環境（container / VM / 共享主機），每一步要按環境分列工具，或明確標示「本篇的工具路徑適用於 X 環境、Y 環境的做法見另一篇」。</p>
<p>寫操作步驟時的自測問題：「讀者坐在電腦前、打開這篇文章，下一個動作是啟動什麼軟體或輸入什麼指令？」如果答案是「看情況」，就要把「情況」展開成環境分支。</p>
<p>生成端的檢查清單（寫完每一步後問）：</p>
<ul>
<li>這一步的工具是什麼？有沒有寫出來？</li>
<li>這個工具在目標環境可用嗎？（共享主機沒有 SSH、沒有 CLI）</li>
<li>如果不可用，替代工具是什麼？</li>
<li>工具的操作有沒有環境限制？（phpMyAdmin 的 timeout、FTP 的非原子上傳）</li>
</ul>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<ul>
<li><strong>兩次同根因的返工</strong>：同一個缺口（動作缺工具）被使用者指出兩次、修了兩輪，因為第一輪只補了「用什麼工具」沒補「在不同環境怎麼替代」。如果第一次就按環境分列工具路徑，第二次不會發生。</li>
<li><strong>審查結構性盲區</strong>：fact-check 驗「正確性」、steelman 驗「完整性」，兩者都不驗「可執行性」。操作型文章的品質門檻比概念型文章多一層——除了正確和完整，還要可執行。這層門檻需要 executable-walkthrough frame（見<a href="/blog/report/review-lacks-outside-in-reader-frames/" data-link-title="多輪審查缺 outside-in 讀者 frame：六個系統性盲點" data-link-desc="review 框架的所有 frame 從已寫的內容出發（inside-out），缺從讀者完整需求出發的 frame（outside-in）。六個盲點全部由使用者而非 reviewer 發現：宣導語氣、管理層資訊缺失、接手情境遺漏、工具指引缺失、深度不拆分、讀者定位未預設。">outside-in reader frames report</a>）。</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>操作型文章裡出現以下動詞但沒有跟著工具名稱或指令，就是候選缺口：</p>
<p>「拍下」「匯出」「備份」「部署」「掃描」「盤點」「監控」「還原」</p>
<p>這些動詞描述的都是需要工具才能完成的操作。概念型文章用這些動詞是在描述能力（「IaC 的責任是讓環境可重建」），操作型文章用這些動詞是在指引行動——行動需要工具。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li>→ <a href="/blog/report/review-lacks-outside-in-reader-frames/" data-link-title="多輪審查缺 outside-in 讀者 frame：六個系統性盲點" data-link-desc="review 框架的所有 frame 從已寫的內容出發（inside-out），缺從讀者完整需求出發的 frame（outside-in）。六個盲點全部由使用者而非 reviewer 發現：宣導語氣、管理層資訊缺失、接手情境遺漏、工具指引缺失、深度不拆分、讀者定位未預設。">多輪審查缺 outside-in 讀者 frame</a>：本卡是該卡盲點四（操作步驟缺工具指引）的具體展開，補充了「為什麼同根因會被指出兩次」的機制</li>
<li>→ <a href="/blog/report/technical-content-needs-management-reportable-info/" data-link-title="技術教材要內嵌管理層可彙報的資訊" data-link-desc="技術文章的讀者不只要知道怎麼做，還要能向上彙報為什麼做、花多久、花多少。成本量級、時程估算、進度指標與需簽核的決策點應該嵌在技術段落旁邊，而非集中在另一篇溝通指南裡。">技術教材要內嵌管理層可彙報的資訊</a>：工具路徑跟管理層資訊是同一類缺口——都是「讀者的下游任務需要但文章沒給的素材」</li>
<li>→ <a href="/blog/report/audience-is-professional-not-layperson/" data-link-title="讀者是缺經驗的專業人士、不是外行人" data-link-desc="技術教材的讀者定位應該是「在這個領域缺乏經驗的專業人士」，不是「完全不懂的外行人」。寫法是補足經驗缺口、不是從零科普。宣導式語氣（跑得好好的、你可能不知道）預設讀者無能，實際上會降低教材的可信度。">讀者是缺經驗的專業人士、不是外行人</a>：專業人士缺的不是概念（「要備份」），而是特定環境下的操作經驗（「共享主機沒有 mysqldump 時怎麼備份」）</li>
</ul>
]]></content:encoded></item><item><title>常識是相對於讀者背景的、不是作者背景的</title><link>https://tarrragon.github.io/blog/report/common-knowledge-is-relative-to-reader-background/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/common-knowledge-is-relative-to-reader-background/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自 infra 教學模組的知識卡建卡過程。最初建了 14 張卡（IaC、VPC、subnet 等雲端 infra 概念），後續補了 7 張（route-table、SCP 等進階概念），但 legacy 環境的工具（phpMyAdmin、FileZilla、.htaccess、.env）一直沒建卡——作者和 reviewer 都覺得「這些是常識、不需要建卡」。使用者指出「現代工程師不一定認識這些老工具，接手的工程師不一定是寫 PHP 的」後才意識到這是建卡判準的盲點。限制：evidence 來自單一教學模組。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>知識卡的建卡判準是「目標讀者群裡最不熟悉的那個人能不能理解」，不是「作者覺得這個術語夠不夠常見」。&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;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>.htaccess&lt;/td>
 &lt;td>PHP / Apache 工程師&lt;/td>
 &lt;td>Node.js / Go / Python 工程師&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DNS TTL&lt;/td>
 &lt;td>後端 / DevOps&lt;/td>
 &lt;td>前端 / 行動端&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>phpMyAdmin&lt;/td>
 &lt;td>PHP 生態&lt;/td>
 &lt;td>任何非 PHP 背景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>cron&lt;/td>
 &lt;td>Linux 使用者&lt;/td>
 &lt;td>Windows 背景、純雲端開發者&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>opcache&lt;/td>
 &lt;td>PHP 效能調校者&lt;/td>
 &lt;td>任何非 PHP 背景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VPC&lt;/td>
 &lt;td>雲端工程師&lt;/td>
 &lt;td>只用過 PaaS 的開發者&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>作者的盲點是：寫某個領域的教材時，作者已經熟悉該領域的術語，把自己的熟悉度投射成「讀者也知道」。reviewer 如果跟作者背景相似（同源），會有相同的盲點。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>infra 接手維運模組的文章大量使用 phpMyAdmin、FileZilla、.htaccess、.env、cPanel 等術語。三輪多輪審查（compliance / cadence / steelman）都沒有指出這些術語需要知識卡——因為 reviewer 跟作者都把它們當成「寫過 PHP 就知道的東西」。&lt;/p>
&lt;p>使用者指出：「接手的工程師不一定是寫 PHP 的，他只是被叫來接專案。」這句話揭露了建卡判準的錯誤假設——教材的讀者不是「寫 PHP 的人」，而是「被指派接手一個 PHP 專案的任何背景的工程師」。後者的術語熟悉度遠低於前者。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>建卡判準用「最不熟悉的目標讀者」而非「作者的熟悉度」：&lt;/p>
&lt;ol>
&lt;li>定義目標讀者群的背景光譜（接手維運的讀者可能是 PHP / Node / Go / Python / 前端背景）&lt;/li>
&lt;li>對每個術語問：「光譜裡最不熟悉的那端，看到這個詞能理解嗎？」&lt;/li>
&lt;li>如果答案是「部分讀者需要查」，就建卡——卡的成本很低（40-50 行），但缺卡讓讀者卡住的成本很高（關掉頁面去 Google、可能找到不準確的解釋）&lt;/li>
&lt;/ol>
&lt;p>建卡的邊際成本判斷：一張 40 行的卡花 5 分鐘寫，讀者搜尋到一張不存在的卡花 10 分鐘去外部找答案（可能不準確）。建卡的 CP 值幾乎總是正的——除非術語真的只在一篇文章出現一次且已有完整 inline 解釋。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>讀者流失&lt;/strong>：非 PHP 背景的工程師讀到第三個不認識的術語（phpMyAdmin → .htaccess → opcache）後放棄，因為教材假設了他沒有的背景知識&lt;/li>
&lt;li>&lt;strong>外部搜尋的風險&lt;/strong>：讀者離開教材去 Google「什麼是 .htaccess」，找到的解釋可能跟教材的上下文不一致（例如 Google 結果講的是 Apache 2.2 的語法，教材用的是 2.4+）&lt;/li>
&lt;li>&lt;strong>review 結構性漏抓&lt;/strong>：同源 reviewer 跟作者有相同的「常識」盲點，加再多輪也抓不到——這是 outside-in 的 reader-persona frame 才能 catch 的問題&lt;/li>
&lt;/ul>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>寫教材時如果某個術語「不需要解釋」的直覺反應來得太快，問自己：「一個完全不同背景的專業人士看到這個詞，能理解嗎？」如果要想超過三秒才能回答，建卡。&lt;/p>
&lt;p>另一個徵兆：如果教材的目標讀者群跨越多個技術背景（如「任何被指派接手 legacy 專案的工程師」），幾乎所有領域特定的術語都需要建卡——因為沒有任何一個術語對所有背景都是常識。&lt;/p>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/audience-is-professional-not-layperson/" data-link-title="讀者是缺經驗的專業人士、不是外行人" data-link-desc="技術教材的讀者定位應該是「在這個領域缺乏經驗的專業人士」，不是「完全不懂的外行人」。寫法是補足經驗缺口、不是從零科普。宣導式語氣（跑得好好的、你可能不知道）預設讀者無能，實際上會降低教材的可信度。">讀者是缺經驗的專業人士、不是外行人&lt;/a>：讀者有系統思考能力、缺的是特定領域的術語和經驗。知識卡補的正是這個缺口——給他一個 40 行的快速入口，讓他回到教材繼續讀&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/review-lacks-outside-in-reader-frames/" data-link-title="多輪審查缺 outside-in 讀者 frame：六個系統性盲點" data-link-desc="review 框架的所有 frame 從已寫的內容出發（inside-out），缺從讀者完整需求出發的 frame（outside-in）。六個盲點全部由使用者而非 reviewer 發現：宣導語氣、管理層資訊缺失、接手情境遺漏、工具指引缺失、深度不拆分、讀者定位未預設。">多輪審查缺 outside-in 讀者 frame&lt;/a>：「作者覺得是常識」是 inside-out 盲點的又一個實例——inside-out 從內容看品質（術語用得對不對），outside-in 從讀者看缺口（讀者認不認識這個術語）&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/atomic-note-needs-situational-entry/" data-link-title="原子筆記要有向上的議題入口：讀者要知道為何讀這張、何時會撞到" data-link-desc="承載知識的原子筆記不是字典條目。每張卡（或其上層）要回答「你在討論什麼議題、撞到什麼問題，才需要這個知識」——從情境進入，而非從定義進入。做法是建『議題 hub』上層筆記討論問題、再分流到術語卡，術語卡頂部回指議題。">原子筆記要有向上的議題入口&lt;/a>：知識卡從情境進入（「你在接手 legacy 專案時會遇到這個工具」），不是字典定義&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自 infra 教學模組的知識卡建卡過程。最初建了 14 張卡（IaC、VPC、subnet 等雲端 infra 概念），後續補了 7 張（route-table、SCP 等進階概念），但 legacy 環境的工具（phpMyAdmin、FileZilla、.htaccess、.env）一直沒建卡——作者和 reviewer 都覺得「這些是常識、不需要建卡」。使用者指出「現代工程師不一定認識這些老工具，接手的工程師不一定是寫 PHP 的」後才意識到這是建卡判準的盲點。限制：evidence 來自單一教學模組。</p>
<h2 id="核心原則">核心原則</h2>
<p>知識卡的建卡判準是「目標讀者群裡最不熟悉的那個人能不能理解」，不是「作者覺得這個術語夠不夠常見」。</p>
<p>常識是相對於背景的：</p>
<table>
  <thead>
      <tr>
          <th>術語</th>
          <th>哪些背景覺得是常識</th>
          <th>哪些背景需要解釋</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>.htaccess</td>
          <td>PHP / Apache 工程師</td>
          <td>Node.js / Go / Python 工程師</td>
      </tr>
      <tr>
          <td>DNS TTL</td>
          <td>後端 / DevOps</td>
          <td>前端 / 行動端</td>
      </tr>
      <tr>
          <td>phpMyAdmin</td>
          <td>PHP 生態</td>
          <td>任何非 PHP 背景</td>
      </tr>
      <tr>
          <td>cron</td>
          <td>Linux 使用者</td>
          <td>Windows 背景、純雲端開發者</td>
      </tr>
      <tr>
          <td>opcache</td>
          <td>PHP 效能調校者</td>
          <td>任何非 PHP 背景</td>
      </tr>
      <tr>
          <td>VPC</td>
          <td>雲端工程師</td>
          <td>只用過 PaaS 的開發者</td>
      </tr>
  </tbody>
</table>
<p>作者的盲點是：寫某個領域的教材時，作者已經熟悉該領域的術語，把自己的熟悉度投射成「讀者也知道」。reviewer 如果跟作者背景相似（同源），會有相同的盲點。</p>
<h2 id="情境">情境</h2>
<p>infra 接手維運模組的文章大量使用 phpMyAdmin、FileZilla、.htaccess、.env、cPanel 等術語。三輪多輪審查（compliance / cadence / steelman）都沒有指出這些術語需要知識卡——因為 reviewer 跟作者都把它們當成「寫過 PHP 就知道的東西」。</p>
<p>使用者指出：「接手的工程師不一定是寫 PHP 的，他只是被叫來接專案。」這句話揭露了建卡判準的錯誤假設——教材的讀者不是「寫 PHP 的人」，而是「被指派接手一個 PHP 專案的任何背景的工程師」。後者的術語熟悉度遠低於前者。</p>
<h2 id="理想做法">理想做法</h2>
<p>建卡判準用「最不熟悉的目標讀者」而非「作者的熟悉度」：</p>
<ol>
<li>定義目標讀者群的背景光譜（接手維運的讀者可能是 PHP / Node / Go / Python / 前端背景）</li>
<li>對每個術語問：「光譜裡最不熟悉的那端，看到這個詞能理解嗎？」</li>
<li>如果答案是「部分讀者需要查」，就建卡——卡的成本很低（40-50 行），但缺卡讓讀者卡住的成本很高（關掉頁面去 Google、可能找到不準確的解釋）</li>
</ol>
<p>建卡的邊際成本判斷：一張 40 行的卡花 5 分鐘寫，讀者搜尋到一張不存在的卡花 10 分鐘去外部找答案（可能不準確）。建卡的 CP 值幾乎總是正的——除非術語真的只在一篇文章出現一次且已有完整 inline 解釋。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<ul>
<li><strong>讀者流失</strong>：非 PHP 背景的工程師讀到第三個不認識的術語（phpMyAdmin → .htaccess → opcache）後放棄，因為教材假設了他沒有的背景知識</li>
<li><strong>外部搜尋的風險</strong>：讀者離開教材去 Google「什麼是 .htaccess」，找到的解釋可能跟教材的上下文不一致（例如 Google 結果講的是 Apache 2.2 的語法，教材用的是 2.4+）</li>
<li><strong>review 結構性漏抓</strong>：同源 reviewer 跟作者有相同的「常識」盲點，加再多輪也抓不到——這是 outside-in 的 reader-persona frame 才能 catch 的問題</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>寫教材時如果某個術語「不需要解釋」的直覺反應來得太快，問自己：「一個完全不同背景的專業人士看到這個詞，能理解嗎？」如果要想超過三秒才能回答，建卡。</p>
<p>另一個徵兆：如果教材的目標讀者群跨越多個技術背景（如「任何被指派接手 legacy 專案的工程師」），幾乎所有領域特定的術語都需要建卡——因為沒有任何一個術語對所有背景都是常識。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li>→ <a href="/blog/report/audience-is-professional-not-layperson/" data-link-title="讀者是缺經驗的專業人士、不是外行人" data-link-desc="技術教材的讀者定位應該是「在這個領域缺乏經驗的專業人士」，不是「完全不懂的外行人」。寫法是補足經驗缺口、不是從零科普。宣導式語氣（跑得好好的、你可能不知道）預設讀者無能，實際上會降低教材的可信度。">讀者是缺經驗的專業人士、不是外行人</a>：讀者有系統思考能力、缺的是特定領域的術語和經驗。知識卡補的正是這個缺口——給他一個 40 行的快速入口，讓他回到教材繼續讀</li>
<li>→ <a href="/blog/report/review-lacks-outside-in-reader-frames/" data-link-title="多輪審查缺 outside-in 讀者 frame：六個系統性盲點" data-link-desc="review 框架的所有 frame 從已寫的內容出發（inside-out），缺從讀者完整需求出發的 frame（outside-in）。六個盲點全部由使用者而非 reviewer 發現：宣導語氣、管理層資訊缺失、接手情境遺漏、工具指引缺失、深度不拆分、讀者定位未預設。">多輪審查缺 outside-in 讀者 frame</a>：「作者覺得是常識」是 inside-out 盲點的又一個實例——inside-out 從內容看品質（術語用得對不對），outside-in 從讀者看缺口（讀者認不認識這個術語）</li>
<li>→ <a href="/blog/report/atomic-note-needs-situational-entry/" data-link-title="原子筆記要有向上的議題入口：讀者要知道為何讀這張、何時會撞到" data-link-desc="承載知識的原子筆記不是字典條目。每張卡（或其上層）要回答「你在討論什麼議題、撞到什麼問題，才需要這個知識」——從情境進入，而非從定義進入。做法是建『議題 hub』上層筆記討論問題、再分流到術語卡，術語卡頂部回指議題。">原子筆記要有向上的議題入口</a>：知識卡從情境進入（「你在接手 legacy 專案時會遇到這個工具」），不是字典定義</li>
</ul>
]]></content:encoded></item><item><title>一篇文章只承擔一種功能：SOP 跟 retrospective 混寫兩邊都做不好</title><link>https://tarrragon.github.io/blog/report/single-function-per-article-sop-vs-retrospective/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/single-function-per-article-sop-vs-retrospective/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自四篇方法論文章同時塞 SOP 和驗證紀錄、導致兩種讀者都服務不好的分類檢討。limitation：evidence 來自同一個 blog 的四篇文章，都是寫作方法論主題。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>操作步驟（SOP：結構模板、流程 checklist、怎麼做）和演化紀錄（retrospective：批次驗證數據、實際跑出來學到什麼）服務不同讀者。混寫本身不一定失敗（SRE 手冊和 postmortem 模板都成功交織兩者），但在本 repo 的場景下會造成兩個具體問題：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>SOP 同時存在於 skill 和文章裡，改 skill 時文章沒同步更新、兩處內容分歧&lt;/strong>。這是主要痛點。&lt;/li>
&lt;li>沒有清楚的分節標示時，讀者要跳過大量「不是給我看的」段落。&lt;/li>
&lt;/ol>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>四篇 &lt;code>posts/&lt;/code> 文章的共通症狀：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>文章&lt;/th>
 &lt;th>SOP 段內容&lt;/th>
 &lt;th>Retrospective 段內容&lt;/th>
 &lt;th>混合比例&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>migration-playbook-methodology&lt;/td>
 &lt;td>6 type 結構模板、diff dimension audit 步驟&lt;/td>
 &lt;td>三輪 batch 驗證、cadence dogfood、self-aware limitation update&lt;/td>
 &lt;td>SOP 40% / retro 60%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>vendor-deep-article-methodology&lt;/td>
 &lt;td>選題判準、6 段結構、寫作流程 7 step&lt;/td>
 &lt;td>兩輪 batch 驗證、跨兩輪 cadence 對照&lt;/td>
 &lt;td>SOP 35% / retro 65%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>verification-driven-cli-tool-articles&lt;/td>
 &lt;td>分類 → fixture → 標註 → gotcha 回寫流程&lt;/td>
 &lt;td>「為什麼官方 docs 不夠」+ 實測落差清單&lt;/td>
 &lt;td>SOP 70% / retro 30%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>ci-silent-hang-diagnosis&lt;/td>
 &lt;td>無明確 SOP（不可重複流程）&lt;/td>
 &lt;td>完整 case study + 原則提取&lt;/td>
 &lt;td>不適用此分類&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>前三篇的共通模式：文章開頭像方法論手冊（SOP 感），中段突然變成「第一輪 demo 驗證」「第二輪 batch 對照」（retrospective 感），讀者在兩種模式之間切換的認知成本高。&lt;/p>
&lt;p>第四篇 ci-silent-hang 是不同問題 — 它不是功能混合，是資料夾歸類錯（debugging case study 放在 &lt;code>posts/&lt;/code> 而非 &lt;code>work-log/&lt;/code>）。&lt;/p>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>功能拆分到對應的 surface：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>功能&lt;/th>
 &lt;th>Surface&lt;/th>
 &lt;th>讀者&lt;/th>
 &lt;th>格式&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>SOP（操作步驟）&lt;/td>
 &lt;td>&lt;code>.claude/skills/&lt;/code>&lt;/td>
 &lt;td>Claude runtime + 人類執行者&lt;/td>
 &lt;td>Skill 格式（H1 + body、portable）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Retrospective（驗證證據）&lt;/td>
 &lt;td>&lt;code>posts/&lt;/code> 或 &lt;code>content/skills/&lt;/code> 鏡像&lt;/td>
 &lt;td>人類讀者&lt;/td>
 &lt;td>文章格式（Hugo frontmatter）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Debugging case&lt;/td>
 &lt;td>&lt;code>work-log/&lt;/code>&lt;/td>
 &lt;td>人類讀者&lt;/td>
 &lt;td>事件紀錄&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>抽象原則&lt;/td>
 &lt;td>&lt;code>report/&lt;/code>&lt;/td>
 &lt;td>所有讀者&lt;/td>
 &lt;td>Report 卡片&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>拆分後的文章只保留 retrospective 段（去掉跟 skill 重複的 SOP 步驟），開頭引用 skill 路徑建立 context。去掉 SOP 後文章若不能獨立成篇（冷讀者讀不懂、或只剩表格沒有判讀），降級成 &lt;code>content/skills/&lt;/code> 鏡像。&lt;/p>
&lt;p>已有先例：&lt;code>case-first-agent-team-review-workflow&lt;/code> 已經走這條路 — 文章是方法論敘事、skill 是操作步驟、兩者共存互連。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>機器讀者找不到步驟&lt;/strong>：Claude runtime 透過 skill 觸發操作流程；SOP 埋在文章的 retrospective 段落裡，觸發路徑不通&lt;/li>
&lt;li>&lt;strong>人類讀者跳著讀&lt;/strong>：讀者進來看「migration playbook 怎麼寫」，要跳過三輪 batch 驗證表才找到 6 type 結構模板；或者進來看「為什麼三輪 batch collapse 率不同」，要跳過 diff dimension audit 步驟才到驗證段&lt;/li>
&lt;li>&lt;strong>維護雙份&lt;/strong>：SOP 同時存在於 skill 和文章裡（migration-playbook 已發生），改 skill 時文章沒同步更新，兩處內容分歧&lt;/li>
&lt;li>&lt;strong>新文章不知道放哪&lt;/strong>：下一篇方法論文章也會自然累積 SOP + retrospective，如果沒有拆分慣例，就會繼續混寫&lt;/li>
&lt;/ul>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>寫方法論文章時，如果文章裡同時出現以下兩類段落，就是功能混合的訊號：&lt;/p></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自四篇方法論文章同時塞 SOP 和驗證紀錄、導致兩種讀者都服務不好的分類檢討。limitation：evidence 來自同一個 blog 的四篇文章，都是寫作方法論主題。</p>
<h2 id="核心原則">核心原則</h2>
<p>操作步驟（SOP：結構模板、流程 checklist、怎麼做）和演化紀錄（retrospective：批次驗證數據、實際跑出來學到什麼）服務不同讀者。混寫本身不一定失敗（SRE 手冊和 postmortem 模板都成功交織兩者），但在本 repo 的場景下會造成兩個具體問題：</p>
<ol>
<li><strong>SOP 同時存在於 skill 和文章裡，改 skill 時文章沒同步更新、兩處內容分歧</strong>。這是主要痛點。</li>
<li>沒有清楚的分節標示時，讀者要跳過大量「不是給我看的」段落。</li>
</ol>
<h2 id="情境">情境</h2>
<p>四篇 <code>posts/</code> 文章的共通症狀：</p>
<table>
  <thead>
      <tr>
          <th>文章</th>
          <th>SOP 段內容</th>
          <th>Retrospective 段內容</th>
          <th>混合比例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>migration-playbook-methodology</td>
          <td>6 type 結構模板、diff dimension audit 步驟</td>
          <td>三輪 batch 驗證、cadence dogfood、self-aware limitation update</td>
          <td>SOP 40% / retro 60%</td>
      </tr>
      <tr>
          <td>vendor-deep-article-methodology</td>
          <td>選題判準、6 段結構、寫作流程 7 step</td>
          <td>兩輪 batch 驗證、跨兩輪 cadence 對照</td>
          <td>SOP 35% / retro 65%</td>
      </tr>
      <tr>
          <td>verification-driven-cli-tool-articles</td>
          <td>分類 → fixture → 標註 → gotcha 回寫流程</td>
          <td>「為什麼官方 docs 不夠」+ 實測落差清單</td>
          <td>SOP 70% / retro 30%</td>
      </tr>
      <tr>
          <td>ci-silent-hang-diagnosis</td>
          <td>無明確 SOP（不可重複流程）</td>
          <td>完整 case study + 原則提取</td>
          <td>不適用此分類</td>
      </tr>
  </tbody>
</table>
<p>前三篇的共通模式：文章開頭像方法論手冊（SOP 感），中段突然變成「第一輪 demo 驗證」「第二輪 batch 對照」（retrospective 感），讀者在兩種模式之間切換的認知成本高。</p>
<p>第四篇 ci-silent-hang 是不同問題 — 它不是功能混合，是資料夾歸類錯（debugging case study 放在 <code>posts/</code> 而非 <code>work-log/</code>）。</p>
<h2 id="理想做法">理想做法</h2>
<p>功能拆分到對應的 surface：</p>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>Surface</th>
          <th>讀者</th>
          <th>格式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SOP（操作步驟）</td>
          <td><code>.claude/skills/</code></td>
          <td>Claude runtime + 人類執行者</td>
          <td>Skill 格式（H1 + body、portable）</td>
      </tr>
      <tr>
          <td>Retrospective（驗證證據）</td>
          <td><code>posts/</code> 或 <code>content/skills/</code> 鏡像</td>
          <td>人類讀者</td>
          <td>文章格式（Hugo frontmatter）</td>
      </tr>
      <tr>
          <td>Debugging case</td>
          <td><code>work-log/</code></td>
          <td>人類讀者</td>
          <td>事件紀錄</td>
      </tr>
      <tr>
          <td>抽象原則</td>
          <td><code>report/</code></td>
          <td>所有讀者</td>
          <td>Report 卡片</td>
      </tr>
  </tbody>
</table>
<p>拆分後的文章只保留 retrospective 段（去掉跟 skill 重複的 SOP 步驟），開頭引用 skill 路徑建立 context。去掉 SOP 後文章若不能獨立成篇（冷讀者讀不懂、或只剩表格沒有判讀），降級成 <code>content/skills/</code> 鏡像。</p>
<p>已有先例：<code>case-first-agent-team-review-workflow</code> 已經走這條路 — 文章是方法論敘事、skill 是操作步驟、兩者共存互連。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<ul>
<li><strong>機器讀者找不到步驟</strong>：Claude runtime 透過 skill 觸發操作流程；SOP 埋在文章的 retrospective 段落裡，觸發路徑不通</li>
<li><strong>人類讀者跳著讀</strong>：讀者進來看「migration playbook 怎麼寫」，要跳過三輪 batch 驗證表才找到 6 type 結構模板；或者進來看「為什麼三輪 batch collapse 率不同」，要跳過 diff dimension audit 步驟才到驗證段</li>
<li><strong>維護雙份</strong>：SOP 同時存在於 skill 和文章裡（migration-playbook 已發生），改 skill 時文章沒同步更新，兩處內容分歧</li>
<li><strong>新文章不知道放哪</strong>：下一篇方法論文章也會自然累積 SOP + retrospective，如果沒有拆分慣例，就會繼續混寫</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>寫方法論文章時，如果文章裡同時出現以下兩類段落，就是功能混合的訊號：</p>
<ol>
<li><strong>步驟型段落</strong>：「Step 1 → Step 2 → Step 3」、結構模板、checklist、「照這個跑」</li>
<li><strong>證據型段落</strong>：「第 N 輪 batch 驗證」、「N/N collapse 率」、「跨兩輪對照」、「self-aware limitation update」</li>
</ol>
<p>另一個徵兆：文章已有對應的 skill（或適合建 skill），但文章裡仍重複 skill 的 SOP 內容。</p>
<p>本徵兆適用 <code>posts/</code> 方法論文章。<code>report/</code> 卡片的修法步驟 + case 證據並存是正常形態（report 卡格式本就含情境 + 原則 + 修法）。</p>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li>→ <a href="/blog/report/article-body-must-align-with-title-commitment/" data-link-title="文章主體要對齊標題承諾、WRAP 內部分析不該喧賓奪主" data-link-desc="文章標題對讀者做了承諾、文章主體必須對齊這個承諾。WRAP 內部分析（Widen Options &#43; Reality Test 含 prior 引用 &#43; evidence weight）即使方法論做得好、如果不是標題承諾的內容、就不該佔文章主體—屬於 scope mismatch、跟 process metadata 暴露（#141）的議題分開。附帶議題：當 WRAP 內部分析喧賓奪主、為了支撐 prior 容易引入沒實際出處的 source citation；把 WRAP 內部分析從主體移除、hallucination 風險自然降低。是 #141 的姊妹卡—#141 處理章節標題 surface、本卡處理章節內容 scope。">#142 文章主體要對齊標題承諾</a>：#142 處理「章節內容偏離標題」，本卡處理「整篇文章功能定位混合」— #142 是段落層、本卡是文章層，同屬「內容要對齊承諾」家族</li>
<li>→ <a href="/blog/report/cadence-homogenization-in-batch-writing/" data-link-title="Cadence 同質化是模板的隱形維度" data-link-desc="規範定義「模板」時通常只指內容欄位（規模對照、tripwire、失敗模式），忽略句型骨架 / 段首語 / 段末收尾語 / 表格前導句 / 過渡詞同樣是模板的一種；批量寫作時最易讓 cadence 同質化、單篇看起來都合規、連讀多篇才浮現預期化；51 vendor 都用「四件事 → 任一缺失就是 X 邊界的待補項目」是案例；自檢要 grep 首句 / 段末句 / 表格前導句、不是只看欄位">#122 cadence 同質化</a>：本卡四篇文章中的 retrospective 段大量引用 #122 的 cadence 概念；拆分後 retrospective 段落成為 #122 的 evidence 文件，SOP 進 skill 不再重複</li>
<li>→ <a href="/blog/report/summary-section-signals-scattered-prose/" data-link-title="教材的『重點 / 總結』段是內容發散的訊號、該重組正文不該補丁" data-link-desc="教材尾端的『重點』『一句話總結』段、若功能是重述前面已講過的內容、就是正文組織不佳的補丁。讀者需要回頭被提醒、代表概念在正文裡散掉了 —— 該做的是重拆正文段落、把概念在它該出現的位置一次講清、而不是另開總結段替發散的正文善後。判準：刪掉總結段後正文若仍站得住、證明總結本就冗餘；若站不住、是正文要重組、不是總結要補。處理總結段內容時先分『提醒 vs 概念』—— 純提醒（養成習慣 / 回頭確認）刪、有概念價值的（為何這樣設計）併回它本該所屬的正文位置。">#154 教材的重點/總結段是內容發散訊號</a>：#154 說「刪掉總結段看正文站不站得住」，本卡的對應操作是「刪掉 SOP 段看 retrospective 站不站得住」— 同類「減法測試」判準</li>
<li>→ AGENTS.md 跨 surface 內容處理原則：本卡的拆分動作跨 <code>.claude/skills/</code> 和 <code>content/</code> 兩個 surface，各自獨立、不交叉引用</li>
</ul>
]]></content:encoded></item><item><title>Report 卡的論述基礎記結論和 evidence 來源、不記檢討過程</title><link>https://tarrragon.github.io/blog/report/report-basis-states-conclusion-not-process/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/report-basis-states-conclusion-not-process/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自 #199 論述基礎段的修改。原稿寫了「四篇文章在寫作時自然累積了兩種內容、發表後讀起來沒頭沒尾不好讀、用 WRAP 完整模式分析後確認問題出在功能定位混合」— 包含發現問題的經過、使用的分析工具、主觀感受。修改後只留「本卡抽自四篇方法論文章同時塞 SOP 和驗證紀錄、導致兩種讀者都服務不好的分類檢討」。limitation：evidence 來自單一 report 卡的修改，但同模式在多張卡的論述基礎段出現過。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>Report 卡的「論述基礎與限制」段承擔兩個功能：告訴讀者 evidence 從哪來（來源）、以及 evidence 的邊界是什麼（limitation）。不承擔第三個功能：告訴讀者這張卡怎麼被發起的（過程）。&lt;/p>
&lt;p>過程是作者的工作紀錄（「讀起來沒頭沒尾」「用 WRAP 分析」「用結構化決策分析」），結論才是讀者需要的判讀前提（「四篇文章混寫 SOP 和 retrospective」「evidence 來自同一個 blog」）。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>#199 的論述基礎段原稿：&lt;/p>
&lt;blockquote>
&lt;p>四篇文章在寫作時自然累積了「怎麼做」（SOP）和「跑出來學到什麼」（retrospective）兩種內容，發表後讀起來「沒頭沒尾不好讀」。用結構化決策分析後確認：問題出在功能定位混合，跟寫作品質無關。&lt;/p>&lt;/blockquote>
&lt;p>三個問題：&lt;/p>
&lt;ol>
&lt;li>「自然累積了」「讀起來沒頭沒尾不好讀」是發起檢討的觸發描述、不是 evidence 邊界&lt;/li>
&lt;li>「用結構化決策分析後確認」是作者使用的工具、讀者不需要知道用了什麼工具才信任結論&lt;/li>
&lt;li>「跟寫作品質無關」是排除診斷的過程、結論段的「SOP 跟 retrospective 服務不同讀者」已經涵蓋&lt;/li>
&lt;/ol>
&lt;h2 id="理想做法">理想做法&lt;/h2>
&lt;p>論述基礎段只寫兩件事：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Evidence 來源&lt;/strong>：「本卡抽自 X」— X 是具體的 case / 事件 / 文章 / 批次&lt;/li>
&lt;li>&lt;strong>Evidence 邊界&lt;/strong>：「limitation：Y」— Y 是樣本量、適用範圍、已知盲區&lt;/li>
&lt;/ol>
&lt;p>不寫：&lt;/p>
&lt;ul>
&lt;li>怎麼發現問題的（「讀起來不好讀」「review 時發現」）&lt;/li>
&lt;li>用了什麼分析工具（「用 WRAP」「跑了三輪 review」）&lt;/li>
&lt;li>排除了什麼診斷（「跟 X 無關」）&lt;/li>
&lt;li>主觀感受（「沒頭沒尾」「覺得怪」）&lt;/li>
&lt;/ul>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>論述基礎段膨脹&lt;/strong>：過程描述比結論長，讀者要翻過「怎麼來的」才看到「邊界是什麼」&lt;/li>
&lt;li>&lt;strong>工具名耦合&lt;/strong>：寫了「用 WRAP 分析」，讀者不知道 WRAP 是什麼就卡住（冷讀者行話洩漏）&lt;/li>
&lt;li>&lt;strong>過時風險&lt;/strong>：過程描述綁定當時的工具和對話脈絡，卡片長期維護時過程段最先過時&lt;/li>
&lt;/ul>
&lt;h2 id="判讀徵兆">判讀徵兆&lt;/h2>
&lt;p>寫完論述基礎段後，問兩個問題：&lt;/p>
&lt;ol>
&lt;li>「如果我把這段貼給一個沒參與這次檢討的人，他能從中知道 evidence 的來源和邊界嗎？」— 能 → 合格&lt;/li>
&lt;li>「這段有沒有只有參與者才懂的脈絡？」— 有 → 刪掉那些脈絡&lt;/li>
&lt;/ol>
&lt;h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係&lt;/h2>
&lt;ul>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/single-function-per-article-sop-vs-retrospective/" data-link-title="一篇文章只承擔一種功能：SOP 跟 retrospective 混寫兩邊都做不好" data-link-desc="文章同時塞操作步驟（SOP）和批次驗證紀錄（retrospective）時，機器讀者找不到可執行的步驟、人類讀者不知道哪段是給自己看的。">#199 一篇文章只承擔一種功能&lt;/a>：本卡的 trigger case；#199 論述基礎段的修改揭露此原則&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/summary-section-signals-scattered-prose/" data-link-title="教材的『重點 / 總結』段是內容發散的訊號、該重組正文不該補丁" data-link-desc="教材尾端的『重點』『一句話總結』段、若功能是重述前面已講過的內容、就是正文組織不佳的補丁。讀者需要回頭被提醒、代表概念在正文裡散掉了 —— 該做的是重拆正文段落、把概念在它該出現的位置一次講清、而不是另開總結段替發散的正文善後。判準：刪掉總結段後正文若仍站得住、證明總結本就冗餘；若站不住、是正文要重組、不是總結要補。處理總結段內容時先分『提醒 vs 概念』—— 純提醒（養成習慣 / 回頭確認）刪、有概念價值的（為何這樣設計）併回它本該所屬的正文位置。">#154 教材的重點/總結段是內容發散訊號&lt;/a>：#154 說「刪掉看正文站不站得住」，本卡的對應操作是「刪掉過程描述看論述基礎段站不站得住」&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/report/reader-does-not-need-to-know/" data-link-title="讀者不需要知道 — 刪除比解釋更尊重讀者" data-link-desc="「整理目的」blockquote 告訴讀者這篇文章的寫作動機和邊界。但讀者不需要知道作者為什麼寫這篇文章——他們需要知道讀完能帶走什麼。meta 資訊（寫作動機、邊界聲明、脈絡解釋）服務的是作者的組織需求，不是讀者的閱讀需求。">讀者不需要知道的資訊不該出現在最終文件&lt;/a>：過程描述是 meta 資訊、服務作者不服務讀者，同根原則在 report 卡 surface 的體現&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自 #199 論述基礎段的修改。原稿寫了「四篇文章在寫作時自然累積了兩種內容、發表後讀起來沒頭沒尾不好讀、用 WRAP 完整模式分析後確認問題出在功能定位混合」— 包含發現問題的經過、使用的分析工具、主觀感受。修改後只留「本卡抽自四篇方法論文章同時塞 SOP 和驗證紀錄、導致兩種讀者都服務不好的分類檢討」。limitation：evidence 來自單一 report 卡的修改，但同模式在多張卡的論述基礎段出現過。</p>
<h2 id="核心原則">核心原則</h2>
<p>Report 卡的「論述基礎與限制」段承擔兩個功能：告訴讀者 evidence 從哪來（來源）、以及 evidence 的邊界是什麼（limitation）。不承擔第三個功能：告訴讀者這張卡怎麼被發起的（過程）。</p>
<p>過程是作者的工作紀錄（「讀起來沒頭沒尾」「用 WRAP 分析」「用結構化決策分析」），結論才是讀者需要的判讀前提（「四篇文章混寫 SOP 和 retrospective」「evidence 來自同一個 blog」）。</p>
<h2 id="情境">情境</h2>
<p>#199 的論述基礎段原稿：</p>
<blockquote>
<p>四篇文章在寫作時自然累積了「怎麼做」（SOP）和「跑出來學到什麼」（retrospective）兩種內容，發表後讀起來「沒頭沒尾不好讀」。用結構化決策分析後確認：問題出在功能定位混合，跟寫作品質無關。</p></blockquote>
<p>三個問題：</p>
<ol>
<li>「自然累積了」「讀起來沒頭沒尾不好讀」是發起檢討的觸發描述、不是 evidence 邊界</li>
<li>「用結構化決策分析後確認」是作者使用的工具、讀者不需要知道用了什麼工具才信任結論</li>
<li>「跟寫作品質無關」是排除診斷的過程、結論段的「SOP 跟 retrospective 服務不同讀者」已經涵蓋</li>
</ol>
<h2 id="理想做法">理想做法</h2>
<p>論述基礎段只寫兩件事：</p>
<ol>
<li><strong>Evidence 來源</strong>：「本卡抽自 X」— X 是具體的 case / 事件 / 文章 / 批次</li>
<li><strong>Evidence 邊界</strong>：「limitation：Y」— Y 是樣本量、適用範圍、已知盲區</li>
</ol>
<p>不寫：</p>
<ul>
<li>怎麼發現問題的（「讀起來不好讀」「review 時發現」）</li>
<li>用了什麼分析工具（「用 WRAP」「跑了三輪 review」）</li>
<li>排除了什麼診斷（「跟 X 無關」）</li>
<li>主觀感受（「沒頭沒尾」「覺得怪」）</li>
</ul>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<ul>
<li><strong>論述基礎段膨脹</strong>：過程描述比結論長，讀者要翻過「怎麼來的」才看到「邊界是什麼」</li>
<li><strong>工具名耦合</strong>：寫了「用 WRAP 分析」，讀者不知道 WRAP 是什麼就卡住（冷讀者行話洩漏）</li>
<li><strong>過時風險</strong>：過程描述綁定當時的工具和對話脈絡，卡片長期維護時過程段最先過時</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>寫完論述基礎段後，問兩個問題：</p>
<ol>
<li>「如果我把這段貼給一個沒參與這次檢討的人，他能從中知道 evidence 的來源和邊界嗎？」— 能 → 合格</li>
<li>「這段有沒有只有參與者才懂的脈絡？」— 有 → 刪掉那些脈絡</li>
</ol>
<h2 id="跟其他抽象層原則的關係">跟其他抽象層原則的關係</h2>
<ul>
<li>→ <a href="/blog/report/single-function-per-article-sop-vs-retrospective/" data-link-title="一篇文章只承擔一種功能：SOP 跟 retrospective 混寫兩邊都做不好" data-link-desc="文章同時塞操作步驟（SOP）和批次驗證紀錄（retrospective）時，機器讀者找不到可執行的步驟、人類讀者不知道哪段是給自己看的。">#199 一篇文章只承擔一種功能</a>：本卡的 trigger case；#199 論述基礎段的修改揭露此原則</li>
<li>→ <a href="/blog/report/summary-section-signals-scattered-prose/" data-link-title="教材的『重點 / 總結』段是內容發散的訊號、該重組正文不該補丁" data-link-desc="教材尾端的『重點』『一句話總結』段、若功能是重述前面已講過的內容、就是正文組織不佳的補丁。讀者需要回頭被提醒、代表概念在正文裡散掉了 —— 該做的是重拆正文段落、把概念在它該出現的位置一次講清、而不是另開總結段替發散的正文善後。判準：刪掉總結段後正文若仍站得住、證明總結本就冗餘；若站不住、是正文要重組、不是總結要補。處理總結段內容時先分『提醒 vs 概念』—— 純提醒（養成習慣 / 回頭確認）刪、有概念價值的（為何這樣設計）併回它本該所屬的正文位置。">#154 教材的重點/總結段是內容發散訊號</a>：#154 說「刪掉看正文站不站得住」，本卡的對應操作是「刪掉過程描述看論述基礎段站不站得住」</li>
<li>→ <a href="/blog/report/reader-does-not-need-to-know/" data-link-title="讀者不需要知道 — 刪除比解釋更尊重讀者" data-link-desc="「整理目的」blockquote 告訴讀者這篇文章的寫作動機和邊界。但讀者不需要知道作者為什麼寫這篇文章——他們需要知道讀完能帶走什麼。meta 資訊（寫作動機、邊界聲明、脈絡解釋）服務的是作者的組織需求，不是讀者的閱讀需求。">讀者不需要知道的資訊不該出現在最終文件</a>：過程描述是 meta 資訊、服務作者不服務讀者，同根原則在 report 卡 surface 的體現</li>
</ul>
]]></content:encoded></item><item><title>經驗分享文章的寫作準則</title><link>https://tarrragon.github.io/blog/record/%E7%B6%93%E9%A9%97%E5%88%86%E4%BA%AB%E6%96%87%E7%AB%A0%E7%9A%84%E5%AF%AB%E4%BD%9C%E6%BA%96%E5%89%87/</link><pubDate>Thu, 12 Mar 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/record/%E7%B6%93%E9%A9%97%E5%88%86%E4%BA%AB%E6%96%87%E7%AB%A0%E7%9A%84%E5%AF%AB%E4%BD%9C%E6%BA%96%E5%89%87/</guid><description>&lt;p>整理自 2026-03 測試經驗記錄的多次修改過程。
每一條都是實際犯過的寫作錯誤，附上修改前後的對比。&lt;/p></description><content:encoded><![CDATA[<p>整理自 2026-03 測試經驗記錄的多次修改過程。
每一條都是實際犯過的寫作錯誤，附上修改前後的對比。</p>
<h2 id="1-語氣經驗分享不是教人">1. 語氣：經驗分享，不是教人</h2>
<p>不要用「你應該」「要記得」這種由上往下的口氣。這是在記錄自己的經歷，不是在寫教材。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>教訓：測試應該驅動被測程式碼的真實路徑</td>
          <td>後來改成從入口方法開始呼叫，Bug 隨即被發現</td>
      </tr>
      <tr>
          <td>教訓：覆寫子類別時，要測試上層呼叫者實際會用到的方法</td>
          <td>測試覆蓋到的方法，和實際執行路徑走到的方法不是同一個</td>
      </tr>
      <tr>
          <td>關鍵原則：如果你的功能涉及多個元件協作，只寫單元測試是不夠的</td>
          <td>（直接移除，用案例本身說明）</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="2-語氣陳述事實不帶情緒">2. 語氣：陳述事實，不帶情緒</h2>
<p>避免用強調語氣、反問、或帶有自責/誇張的措辭。平鋪直敘地描述發生了什麼。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>我到底哪裡搞砸了</td>
          <td>經驗記錄</td>
      </tr>
      <tr>
          <td>炸了四次</td>
          <td>陸續發現四個 Bug</td>
      </tr>
      <tr>
          <td>說到底，不是測試寫得不夠多，是測試走的路不夠深</td>
          <td>這次的問題在測試覆蓋的路徑深度</td>
      </tr>
      <tr>
          <td>我寫了一個永遠會過的斷言</td>
          <td>這個斷言無法區分成功和失敗</td>
      </tr>
      <tr>
          <td>真正會爆的那個完全沒碰</td>
          <td>測試覆蓋到的方法和實際執行路徑使用的方法不同</td>
      </tr>
      <tr>
          <td>但我偷懶了</td>
          <td>但模擬的回傳資料只有一行純文字</td>
      </tr>
      <tr>
          <td>其他路根本沒碰</td>
          <td>其他分支沒有被覆蓋到</td>
      </tr>
      <tr>
          <td>測試全過是假象</td>
          <td>測試通過不代表修改生效</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="3-用功能描述不要用函式名稱">3. 用功能描述，不要用函式名稱</h2>
<p>文章的讀者不一定看過這份程式碼。如果只寫函式名稱，只有自己看得懂。函式名稱可以出現在程式碼範例裡，但前後的解說要用功能語言。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>_buildItemPrinterMapping</code> 沒有被執行</td>
          <td>品項分派的程式碼沒有被執行</td>
      </tr>
      <tr>
          <td><code>applyPrintResult</code> 的資料儲存功能</td>
          <td>把結果存進去再讀出來，資料有沒有一致</td>
      </tr>
      <tr>
          <td>只測了覆寫的 <code>sendBytes</code>，沒測繼承的 <code>printText</code></td>
          <td>只測了「送出資料」，沒測「組裝列印指令」這個步驟</td>
      </tr>
      <tr>
          <td><code>generator</code> 未初始化</td>
          <td>印表機內部元件未初始化</td>
      </tr>
      <tr>
          <td><code>_getLexemes('')</code> 對 <code>text[0]</code> 越界</td>
          <td>解析文字時沒有處理空字串，直接取第一個字元導致越界</td>
      </tr>
      <tr>
          <td><code>GeneralPrinterAdapter.printText</code> 加了空字串檢查</td>
          <td>在呼叫 library 之前加了空字串的前置檢查</td>
      </tr>
  </tbody>
</table>
<p>程式碼區塊裡的函式名稱不需要替換——那是具體的範例，讀者看到程式碼會理解。要替換的是程式碼區塊外的描述文字。</p>
<hr>
<h2 id="4-敘事角度不是每件事都是犯錯">4. 敘事角度：不是每件事都是「犯錯」</h2>
<p>有些問題不是自己造成的，不需要用自責的角度來寫。例如第三方 library 的 bug 本來就存在，能觸發它代表前面的工作都做對了。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>修完一個 Bug 我就以為沒事了</td>
          <td>第三方 library 的地雷——前面都做對了才踩到</td>
      </tr>
      <tr>
          <td>我沒想到修完之後下游還有問題</td>
          <td>前三個 Bug 都修好之後，執行路徑才真正打通，觸發了這個潛在問題</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="5-每個案例要有脈絡發現--找因--修復">5. 每個案例要有脈絡：發現 → 找因 → 修復</h2>
<p>只說「問題是 X，改成 Y」不夠。讀者需要知道完整的脈絡：是怎麼意識到有問題的、怎麼一步步定位原因的、最後怎麼修的。</p>
<h3 id="修改前">修改前</h3>
<blockquote>
<p>測試名稱是「品項分派邏輯」，但分派邏輯沒有被執行。後來改成從入口方法開始呼叫，Bug 隨即被發現。</p></blockquote>
<h3 id="修改後">修改後</h3>
<blockquote>
<p><strong>怎麼發現的：</strong> 實機上兩台廚房印表機只有一台收到品項，另一台完全沒動。但測試裡的分派測試是通過的。</p>
<p><strong>怎麼找到原因的：</strong> 回頭看測試程式碼，發現測試裡的分派結果是手動寫死的，不是由分派邏輯算出來的。測試驗證的是「把結果存進去再讀出來」，但品項分派的程式碼從頭到尾沒有被執行過。</p>
<p><strong>怎麼修的：</strong> 改成從入口方法開始呼叫，讓品項分派的邏輯實際跑一遍。跑完之後 Bug 就出現了——分派邏輯的 fallback 條件寫錯，所有品項都被送到同一台。</p></blockquote>
<hr>
<h2 id="6-不要用特定產品sdk-名稱">6. 不要用特定產品/SDK 名稱</h2>
<p>具體的產品名稱（如某個 SDK 的名字）讓文章變成只適用於特定情境。著重描述問題的結構，而非特定技術。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>imin SDK 不驗證 width 總和</td>
          <td>POS 主機不驗證欄位寬度總和</td>
      </tr>
      <tr>
          <td>imin vs ESC/POS 有不同的 width 規則</td>
          <td>兩種印表機對同一個參數的限制不同</td>
      </tr>
  </tbody>
</table>
<p>例外：第三方 library 的名稱可以出現在「最終修復」等技術細節區段，因為那是給自己未來查閱用的。</p>
<hr>
<h2 id="檢查清單">檢查清單</h2>
<p>寫完經驗分享文章後，對照這些問題：</p>
<ol>
<li>有沒有「你應該」「要記得」「教訓是」這類由上往下的用語？→ 改成描述自己做了什麼、發現了什麼</li>
<li>有沒有情緒化的措辭（搞砸、偷懶、炸了、根本沒）？→ 改成陳述事實</li>
<li>程式碼區塊外的函式名稱，不看程式碼的人能理解嗎？→ 用功能描述替代</li>
<li>每個案例有完整的脈絡嗎？（怎麼發現 → 怎麼找因 → 怎麼修）</li>
<li>有沒有把不是自己造成的問題寫成自己的錯？→ 用適當的角度描述</li>
<li>有沒有出現特定產品/SDK 名稱？→ 除了技術細節區段外，用功能描述替代</li>
</ol>]]></content:encoded></item></channel></rss>