<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>溝通 on Tarragon</title><link>https://tarrragon.github.io/blog/tags/%E6%BA%9D%E9%80%9A/</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>Fri, 26 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E6%BA%9D%E9%80%9A/index.xml" rel="self" type="application/rss+xml"/><item><title>空間 / 尺寸類指令的澄清時機</title><link>https://tarrragon.github.io/blog/report/spatial-instruction-clarification/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/spatial-instruction-clarification/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>空間 / 尺寸類指令缺少明確數值時、先列計算過程或假設、確認後再實作。&lt;/strong> 直接用估算寫死會在使用者實際看到結果時才被發現不對、引起多輪試錯。澄清的成本是「多打一句話」、收益是「一次到位」。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼空間指令需要澄清">為什麼空間指令需要澄清&lt;/h2>
&lt;h3 id="商業邏輯">商業邏輯&lt;/h3>
&lt;p>「對齊」「擺在旁邊」這類描述是&lt;strong>關係性指令&lt;/strong> — 描述了兩個元素的相對位置，但沒給絕對數值。實作時需要把關係轉成具體數字（padding 多少、top 多少）。&lt;/p>
&lt;p>執行者依憑感覺取數字 = 用自己的估算代替使用者的意圖。估算與意圖不一致時、使用者看到結果才知道、糾正成本高。&lt;/p>
&lt;p>把計算過程列出來確認 = 把「估算」變成「協商」 — 使用者有機會在實作前指正。&lt;/p>
&lt;hr>
&lt;h2 id="這次任務的實際情境">這次任務的實際情境&lt;/h2>
&lt;h3 id="觀察">觀察&lt;/h3>
&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>Filter 的 padding 對齊&lt;/td>
 &lt;td>「padding 對齊到搜尋欄下緣」&lt;/td>
 &lt;td>估算 padding-top: 152px 寫死&lt;/td>
 &lt;td>視覺差 ~10px、要重做&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Breakpoint 取值&lt;/td>
 &lt;td>「桌面顯示左欄、手機隱藏」&lt;/td>
 &lt;td>取 768px 寫死&lt;/td>
 &lt;td>視窗 1200 時看不到 filter、要重做&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Filter 寬度&lt;/td>
 &lt;td>「左欄 400px」&lt;/td>
 &lt;td>直接用 400&lt;/td>
 &lt;td>一次到位&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>第三個是少數有明確數值的情境、那次一次到位。前兩個沒給數字、靠估算、結果都要重做。&lt;/p>
&lt;h3 id="判讀">判讀&lt;/h3>
&lt;p>差別在「使用者有沒有給確定值」。沒給時、執行者該做的不是「自己決定」、是「把計算列出來確認」。&lt;/p>
&lt;h3 id="執行澄清-protocol">執行：澄清 protocol&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;/tbody>
&lt;/table>
&lt;p>例：&lt;/p>
&lt;blockquote>
&lt;p>「padding 對齊到搜尋欄下緣 — 我會用 H1 64px + form 68px = 132px 當基準、加 8px buffer 共 140px、OK 嗎？或是你想要其他數字？」&lt;/p>&lt;/blockquote>
&lt;p>把計算過程攤開、使用者可以指正「H1 沒這麼高、應該 70px」、避免實作後重做。&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;th>適用情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>直接照使用者給的數值寫&lt;/td>
 &lt;td>100%&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>數值可推算&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>不適用&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="1-攤開假設">1. 攤開假設&lt;/h3>





&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">計算 filter padding-top：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> H1 height = 64px（假設、實際看 theme 渲染可能不同）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> Form height = 68px（pagefind input 64 + border 4，鎖定 scale=1.0）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> Gap = 20px（pagefind drawer 預設 margin-top）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> Total = 152px&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>每個值來源寫清楚 — 使用者可以指出某個假設錯了。&lt;/p>
&lt;h3 id="2-用變數表達">2. 用變數表達&lt;/h3>





&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">padding-top: calc(var(--search-title-h) + var(--search-form-h) + var(--search-gap));&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用變數取代 magic number — 改一處全部跟著動、未來調整成本低。&lt;/p>
&lt;h3 id="3-區分設計值與量測值">3. 區分「設計值」與「量測值」&lt;/h3>
&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>filter 寬度 400px&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>量測值&lt;/td>
 &lt;td>runtime 才知道&lt;/td>
 &lt;td>scope UI 高度（受字型換行）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推算值&lt;/td>
 &lt;td>由其他值計算&lt;/td>
 &lt;td>filter padding = title + form + gap&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>確認時把每個值的類型寫清楚、使用者知道哪些是「我可以決定」、哪些是「實作時才知道」。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>空間 / 尺寸類指令缺少明確數值時、先列計算過程或假設、確認後再實作。</strong> 直接用估算寫死會在使用者實際看到結果時才被發現不對、引起多輪試錯。澄清的成本是「多打一句話」、收益是「一次到位」。</p>
<hr>
<h2 id="為什麼空間指令需要澄清">為什麼空間指令需要澄清</h2>
<h3 id="商業邏輯">商業邏輯</h3>
<p>「對齊」「擺在旁邊」這類描述是<strong>關係性指令</strong> — 描述了兩個元素的相對位置，但沒給絕對數值。實作時需要把關係轉成具體數字（padding 多少、top 多少）。</p>
<p>執行者依憑感覺取數字 = 用自己的估算代替使用者的意圖。估算與意圖不一致時、使用者看到結果才知道、糾正成本高。</p>
<p>把計算過程列出來確認 = 把「估算」變成「協商」 — 使用者有機會在實作前指正。</p>
<hr>
<h2 id="這次任務的實際情境">這次任務的實際情境</h2>
<h3 id="觀察">觀察</h3>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>指令</th>
          <th>我的處理</th>
          <th>結果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Filter 的 padding 對齊</td>
          <td>「padding 對齊到搜尋欄下緣」</td>
          <td>估算 padding-top: 152px 寫死</td>
          <td>視覺差 ~10px、要重做</td>
      </tr>
      <tr>
          <td>Breakpoint 取值</td>
          <td>「桌面顯示左欄、手機隱藏」</td>
          <td>取 768px 寫死</td>
          <td>視窗 1200 時看不到 filter、要重做</td>
      </tr>
      <tr>
          <td>Filter 寬度</td>
          <td>「左欄 400px」</td>
          <td>直接用 400</td>
          <td>一次到位</td>
      </tr>
  </tbody>
</table>
<p>第三個是少數有明確數值的情境、那次一次到位。前兩個沒給數字、靠估算、結果都要重做。</p>
<h3 id="判讀">判讀</h3>
<p>差別在「使用者有沒有給確定值」。沒給時、執行者該做的不是「自己決定」、是「把計算列出來確認」。</p>
<h3 id="執行澄清-protocol">執行：澄清 protocol</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>
  </tbody>
</table>
<p>例：</p>
<blockquote>
<p>「padding 對齊到搜尋欄下緣 — 我會用 H1 64px + form 68px = 132px 當基準、加 8px buffer 共 140px、OK 嗎？或是你想要其他數字？」</p></blockquote>
<p>把計算過程攤開、使用者可以指正「H1 沒這麼高、應該 70px」、避免實作後重做。</p>
<hr>
<h2 id="內在屬性比較四種空間指令處理方式">內在屬性比較：四種空間指令處理方式</h2>
<table>
  <thead>
      <tr>
          <th>處理方式</th>
          <th>一次到位機率</th>
          <th>重做成本</th>
          <th>適用情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>直接照使用者給的數值寫</td>
          <td>100%</td>
          <td>無</td>
          <td>使用者明確給數值</td>
      </tr>
      <tr>
          <td>列計算過程確認後寫</td>
          <td>高</td>
          <td>低</td>
          <td>數值可推算</td>
      </tr>
      <tr>
          <td>用估算值寫、之後再調</td>
          <td>中</td>
          <td>中 — 一兩輪</td>
          <td>視覺差容易調的場景</td>
      </tr>
      <tr>
          <td>不確認直接寫死</td>
          <td>低</td>
          <td>高 — 多輪試錯</td>
          <td>不適用</td>
      </tr>
  </tbody>
</table>
<p>優先順序：<strong>有數值用、可算就算、估算寫死最後選</strong>。</p>
<hr>
<h2 id="列計算的好習慣">列計算的好習慣</h2>
<h3 id="1-攤開假設">1. 攤開假設</h3>





<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">計算 filter padding-top：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  H1 height = 64px（假設、實際看 theme 渲染可能不同）
</span></span><span class="line"><span class="ln">3</span><span class="cl">  Form height = 68px（pagefind input 64 + border 4，鎖定 scale=1.0）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  Gap = 20px（pagefind drawer 預設 margin-top）
</span></span><span class="line"><span class="ln">5</span><span class="cl">  Total = 152px</span></span></code></pre></div><p>每個值來源寫清楚 — 使用者可以指出某個假設錯了。</p>
<h3 id="2-用變數表達">2. 用變數表達</h3>





<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">padding-top: calc(var(--search-title-h) + var(--search-form-h) + var(--search-gap));</span></span></code></pre></div><p>使用變數取代 magic number — 改一處全部跟著動、未來調整成本低。</p>
<h3 id="3-區分設計值與量測值">3. 區分「設計值」與「量測值」</h3>
<table>
  <thead>
      <tr>
          <th>值類型</th>
          <th>來源</th>
          <th>例子</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>設計值</td>
          <td>設計師決定的固定值</td>
          <td>filter 寬度 400px</td>
      </tr>
      <tr>
          <td>量測值</td>
          <td>runtime 才知道</td>
          <td>scope UI 高度（受字型換行）</td>
      </tr>
      <tr>
          <td>推算值</td>
          <td>由其他值計算</td>
          <td>filter padding = title + form + gap</td>
      </tr>
  </tbody>
</table>
<p>確認時把每個值的類型寫清楚、使用者知道哪些是「我可以決定」、哪些是「實作時才知道」。</p>
<hr>
<h2 id="設計取捨空間尺寸指令的處理策略">設計取捨：空間/尺寸指令的處理策略</h2>
<p>四種做法、各自機會成本不同。這個專案在缺數值時選 A（列計算過程確認）當預設、其他做法在特定情境合理。</p>
<h3 id="a列計算過程確認後實作這個專案的預設">A：列計算過程確認後實作（這個專案的預設）</h3>
<ul>
<li><strong>機制</strong>：把計算過程與假設攤開、給使用者確認、再用 <code>calc(var(...) + var(...))</code> 實作</li>
<li><strong>選 A 的理由</strong>：使用者能指正特定假設（不只「對」「不對」）、實作後改 token 自動跟上</li>
<li><strong>適合</strong>：缺數值的空間 / 尺寸指令（大多數情境）</li>
<li><strong>代價</strong>：多一輪對話確認</li>
</ul>
<h3 id="b直接照使用者給的數值寫">B：直接照使用者給的數值寫</h3>
<ul>
<li><strong>機制</strong>：使用者給「filter 寬 400px」就直接 <code>width: 400px</code></li>
<li><strong>跟 A 的取捨</strong>：B 一次到位、無需確認；前提是使用者已給確切數值</li>
<li><strong>B 比 A 好的情境</strong>：使用者明確指定數值、執行者只需照寫</li>
</ul>
<h3 id="c用估算值寫之後再調">C：用估算值寫、之後再調</h3>
<ul>
<li><strong>機制</strong>：執行者依感覺給數字（「padding-top: 152px」）、寫了之後等使用者試</li>
<li><strong>跟 A 的取捨</strong>：C 看似省溝通成本、實際把確認延後到實作後；C 在估算錯時要重做</li>
<li><strong>C 才合理的情境</strong>：視覺差容易調（&lt; 5px 微差）、且確認成本比實作高（罕見）</li>
</ul>
<h3 id="d不確認直接寫死">D：不確認直接寫死</h3>
<ul>
<li><strong>機制</strong>：執行者自己決定數值、不問也不告知</li>
<li><strong>成本特別高的原因</strong>：跟使用者意圖不一致時要重做、多輪試錯</li>
<li><strong>D 是反模式</strong>：「使用者會看到的數字」屬於該確認的決定（<a href="../decide-vs-confirm-boundary/">#21 可決定 vs 該先確認</a>）— 自決會跟意圖不一致、被退回時白做</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>應該觸發澄清的指令</th>
          <th>第一個該確認的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「對齊到 X」</td>
          <td>對齊基準是 X 的哪個邊（top / bottom / center）？</td>
          <td>基準位置</td>
      </tr>
      <tr>
          <td>「靠在 Y 旁邊」</td>
          <td>多近？同 row 還是 above / below？</td>
          <td>相對方向與距離</td>
      </tr>
      <tr>
          <td>「desktop 顯示、mobile 隱藏」</td>
          <td>Breakpoint 多少 px？</td>
          <td>viewport 切換點</td>
      </tr>
      <tr>
          <td>「跟 Z 一樣高」</td>
          <td>Z 的高度是固定還是動態？</td>
          <td>量測 vs 寫死</td>
      </tr>
      <tr>
          <td>「適中的 padding」</td>
          <td>「適中」對應多少 px？</td>
          <td>給選項供選擇</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：空間關係描述只是意圖、不是實作數字。把意圖翻譯成數字的過程要對外可見、讓使用者參與。</p>
<p>第三輪指令類型現有五類：空間（本卡）/ 相對位置（<a href="../relative-position-instruction-clarification/">#17</a>）/ 隔離（<a href="../isolation-instruction-clarification/">#18</a>）/ 決定權（<a href="../decide-vs-confirm-boundary/">#21</a>）/ 篩選（<a href="../filter-instruction-clarification/">#58</a>）。前四類缺幾何 / 邊界 / 拍板資訊、第 5 類缺操作層級資訊。</p>
]]></content:encoded></item><item><title>元件相對位置類指令的澄清時機</title><link>https://tarrragon.github.io/blog/report/relative-position-instruction-clarification/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/relative-position-instruction-clarification/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>相對位置指令（「X 在 Y 旁邊」「Y 顯示在 main 左側」）是模糊的 — 同一句話可以對應多種 layout 結構。實作前用文字描述意圖中的 layout 草圖、讓使用者確認後再寫 CSS。&lt;/strong> 沒確認直接擺、實作出來常與使用者預期不同、要重做。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼相對位置需要澄清">為什麼相對位置需要澄清&lt;/h2>
&lt;h3 id="商業邏輯">商業邏輯&lt;/h3>
&lt;p>「X 在 Y 旁邊」這類描述至少對應四種 layout 實作：&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>Y 與 X 同 row、grid / flex 並排&lt;/td>
 &lt;td>並排、Y 影響 X 寬度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>X absolute 浮在 Y 旁邊&lt;/td>
 &lt;td>並排、X 不影響 Y&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Y 與 X 不同層、Y 在 main 內、X 在 main 外&lt;/td>
 &lt;td>跨 main 邊界、視覺感不同&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>X fixed 永遠在 viewport 同位置&lt;/td>
 &lt;td>隨捲動固定、Y 隨內容捲動&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>執行者選哪種、結果不同。憑直覺選 ≠ 使用者意圖。&lt;/p>
&lt;hr>
&lt;h2 id="這次任務的實際情境">這次任務的實際情境&lt;/h2>
&lt;h3 id="觀察">觀察&lt;/h3>
&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>「scope UI 在搜尋框附近」&lt;/td>
 &lt;td>放搜尋框上方&lt;/td>
 &lt;td>應該在搜尋框下方&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「filter 在主欄左側」&lt;/td>
 &lt;td>放進 main 的 grid 左 column&lt;/td>
 &lt;td>是 main 外的 absolute sidebar&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「左右兩欄獨立排版」&lt;/td>
 &lt;td>同 grid container 兩個 column&lt;/td>
 &lt;td>兩個獨立 layer、用 absolute 疊層&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>每個指令都讓我選了使用者沒想要的實作。&lt;/p>
&lt;h3 id="判讀">判讀&lt;/h3>
&lt;p>問題在「相對位置」這類描述本質就是模糊的 — 沒指定座標系、沒指定相對層級、沒指定誰是 layout flow 主角。&lt;/p>
&lt;p>執行前該做的：把我準備寫的 layout 用文字描述出來、讓使用者確認意圖一致。&lt;/p>
&lt;h3 id="執行layout-草圖-protocol">執行：layout 草圖 protocol&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">我準備這樣寫：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> - main 維持 70ch 置中（layout flow 主角）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> - filter 用 absolute 浮在 main 左外側、寬 400px、間距 2rem
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> - scope UI 在 main 內、緊接 search input 下方、結果上方
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> - 三者位置關係：filter 與 main 同 viewport 中段、scope 在 main 內
&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>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>把意圖中的 layout 結構攤開 — 使用者可以指正「filter 應該在 grid 內、不是 absolute」、避免實作後重做。&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>加層級指示（「在 main 內」「跨 main 外」）&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>縮小範圍&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>加 layout 結構（「同 grid」「absolute 疊層」）&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>執行者該主動把對話從「純位置詞」推到「文字草圖 + 確認」 — 縮小模糊範圍。&lt;/p>
&lt;hr>
&lt;h2 id="文字草圖的好習慣">文字草圖的好習慣&lt;/h2>
&lt;h3 id="1-描述-layout-主角">1. 描述 layout 主角&lt;/h3>
&lt;p>哪個元素是「決定其他元素位置的 anchor」？通常是內容主體（main、article）。其他元素相對這個主角描述。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>相對位置指令（「X 在 Y 旁邊」「Y 顯示在 main 左側」）是模糊的 — 同一句話可以對應多種 layout 結構。實作前用文字描述意圖中的 layout 草圖、讓使用者確認後再寫 CSS。</strong> 沒確認直接擺、實作出來常與使用者預期不同、要重做。</p>
<hr>
<h2 id="為什麼相對位置需要澄清">為什麼相對位置需要澄清</h2>
<h3 id="商業邏輯">商業邏輯</h3>
<p>「X 在 Y 旁邊」這類描述至少對應四種 layout 實作：</p>
<table>
  <thead>
      <tr>
          <th>實作方式</th>
          <th>視覺結果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Y 與 X 同 row、grid / flex 並排</td>
          <td>並排、Y 影響 X 寬度</td>
      </tr>
      <tr>
          <td>X absolute 浮在 Y 旁邊</td>
          <td>並排、X 不影響 Y</td>
      </tr>
      <tr>
          <td>Y 與 X 不同層、Y 在 main 內、X 在 main 外</td>
          <td>跨 main 邊界、視覺感不同</td>
      </tr>
      <tr>
          <td>X fixed 永遠在 viewport 同位置</td>
          <td>隨捲動固定、Y 隨內容捲動</td>
      </tr>
  </tbody>
</table>
<p>執行者選哪種、結果不同。憑直覺選 ≠ 使用者意圖。</p>
<hr>
<h2 id="這次任務的實際情境">這次任務的實際情境</h2>
<h3 id="觀察">觀察</h3>
<table>
  <thead>
      <tr>
          <th>指令</th>
          <th>我的初次理解</th>
          <th>使用者實際意圖</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「scope UI 在搜尋框附近」</td>
          <td>放搜尋框上方</td>
          <td>應該在搜尋框下方</td>
      </tr>
      <tr>
          <td>「filter 在主欄左側」</td>
          <td>放進 main 的 grid 左 column</td>
          <td>是 main 外的 absolute sidebar</td>
      </tr>
      <tr>
          <td>「左右兩欄獨立排版」</td>
          <td>同 grid container 兩個 column</td>
          <td>兩個獨立 layer、用 absolute 疊層</td>
      </tr>
  </tbody>
</table>
<p>每個指令都讓我選了使用者沒想要的實作。</p>
<h3 id="判讀">判讀</h3>
<p>問題在「相對位置」這類描述本質就是模糊的 — 沒指定座標系、沒指定相對層級、沒指定誰是 layout flow 主角。</p>
<p>執行前該做的：把我準備寫的 layout 用文字描述出來、讓使用者確認意圖一致。</p>
<h3 id="執行layout-草圖-protocol">執行：layout 草圖 protocol</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">我準備這樣寫：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  - main 維持 70ch 置中（layout flow 主角）
</span></span><span class="line"><span class="ln">3</span><span class="cl">  - filter 用 absolute 浮在 main 左外側、寬 400px、間距 2rem
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - scope UI 在 main 內、緊接 search input 下方、結果上方
</span></span><span class="line"><span class="ln">5</span><span class="cl">  - 三者位置關係：filter 與 main 同 viewport 中段、scope 在 main 內
</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></code></pre></div><p>把意圖中的 layout 結構攤開 — 使用者可以指正「filter 應該在 grid 內、不是 absolute」、避免實作後重做。</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>加層級指示（「在 main 內」「跨 main 外」）</td>
          <td>中</td>
          <td>縮小範圍</td>
      </tr>
      <tr>
          <td>加 layout 結構（「同 grid」「absolute 疊層」）</td>
          <td>低</td>
          <td>接近實作</td>
      </tr>
      <tr>
          <td>文字草圖 + 確認</td>
          <td>最低</td>
          <td>實作前最後確認</td>
      </tr>
  </tbody>
</table>
<p>執行者該主動把對話從「純位置詞」推到「文字草圖 + 確認」 — 縮小模糊範圍。</p>
<hr>
<h2 id="文字草圖的好習慣">文字草圖的好習慣</h2>
<h3 id="1-描述-layout-主角">1. 描述 layout 主角</h3>
<p>哪個元素是「決定其他元素位置的 anchor」？通常是內容主體（main、article）。其他元素相對這個主角描述。</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">Layout 主角：main（70ch 置中）
</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">  - H1：main 內、第一個元素
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - filter：main 左外側 400px
</span></span><span class="line"><span class="ln">5</span><span class="cl">  - footer：main 之後</span></span></code></pre></div><h3 id="2-描述層級關係">2. 描述層級關係</h3>
<p>哪些元素在同一 layout 流、哪些是疊層？</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">Layout flow 內：H1、search input、results
</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">  - filter：absolute、浮在 main 左外
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - scope UI：absolute、浮在 search input 下方</span></span></code></pre></div><h3 id="3-描述-viewport-行為">3. 描述 viewport 行為</h3>
<p>不同 viewport 下、layout 怎麼變？</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">Desktop ≥ 1400：filter 顯示在左外、scope UI 浮在 input 下方
</span></span><span class="line"><span class="ln">2</span><span class="cl">Mobile &lt; 1400：filter 移到 pagefind drawer 內、scope UI 維持原位</span></span></code></pre></div><hr>
<h2 id="對使用者描述-layout-的格式">對使用者描述 layout 的格式</h2>
<h3 id="inline-ascii-草圖">Inline ASCII 草圖</h3>
<p>文字環境下、ASCII 比 PNG 圖更實用：</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">│            │ H1 搜尋           │
</span></span><span class="line"><span class="ln">3</span><span class="cl">│ filter     ├──────────────────┤
</span></span><span class="line"><span class="ln">4</span><span class="cl">│ (sticky)   │ Search input     │
</span></span><span class="line"><span class="ln">5</span><span class="cl">│            ├──────────────────┤
</span></span><span class="line"><span class="ln">6</span><span class="cl">│            │ Scope UI         │
</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">│            │ Results          │
</span></span><span class="line"><span class="ln">9</span><span class="cl">└────────────┴──────────────────┘</span></span></code></pre></div><p>幾秒鐘畫出來、使用者一眼看出意圖、可以指正特定區域。</p>
<h3 id="敘述列表">敘述列表</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">從上到下、從左到右：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  1. 左欄：filter（400px、main 外、sticky）
</span></span><span class="line"><span class="ln">3</span><span class="cl">  2. 右欄：
</span></span><span class="line"><span class="ln">4</span><span class="cl">     a. H1 搜尋
</span></span><span class="line"><span class="ln">5</span><span class="cl">     b. Search input（中央欄）
</span></span><span class="line"><span class="ln">6</span><span class="cl">     c. Scope UI（input 下、results 上）
</span></span><span class="line"><span class="ln">7</span><span class="cl">     d. Results</span></span></code></pre></div><p>兩種格式選一種、確認後再寫 CSS。</p>
<hr>
<h2 id="設計取捨相對位置指令的處理策略">設計取捨：相對位置指令的處理策略</h2>
<p>四種做法、各自機會成本不同。這個專案選 A（文字草圖確認）當預設、其他做法在特定情境合理。</p>
<h3 id="a文字-layout-草圖--主角疊層說明確認這個專案的預設">A：文字 layout 草圖 + 主角/疊層說明確認（這個專案的預設）</h3>
<ul>
<li><strong>機制</strong>：把意圖翻成「main 70ch 置中、filter absolute 浮在 main 左外、scope 在 main 內 absolute 浮在 input 下」這類具體描述、使用者確認</li>
<li><strong>選 A 的理由</strong>：草圖 30 秒打完、使用者 30 秒內 yes/no、避免寫完 CSS 才被指正</li>
<li><strong>適合</strong>：相對位置指令的多數情境</li>
<li><strong>代價</strong>：多 30 秒對話成本</li>
</ul>
<h3 id="bascii-圖更詳細">B：ASCII 圖更詳細</h3>
<ul>
<li><strong>機制</strong>：用 box-drawing 字元畫實際 layout 草圖</li>
<li><strong>跟 A 的取捨</strong>：B 視覺直觀、A 文字描述更精確；B 對複雜 layout 表達力強</li>
<li><strong>B 比 A 好的情境</strong>：layout 涉及 ≥ 4 個區塊、文字描述容易混淆</li>
</ul>
<h3 id="c加層級指示中間步驟">C：加層級指示（中間步驟）</h3>
<ul>
<li><strong>機制</strong>：「filter 在 main 外的 sidebar」（不是「在 main 旁邊」）</li>
<li><strong>跟 A 的取捨</strong>：C 比純位置詞具體、比草圖簡略；用於初步對話</li>
<li><strong>C 比 A 好的情境</strong>：對話初期、還沒到實作決策的階段</li>
</ul>
<h3 id="d純位置詞直接實作">D：純位置詞直接實作</h3>
<ul>
<li><strong>機制</strong>：照「filter 在 main 旁邊」字面意思挑一種實作</li>
<li><strong>成本特別高的原因</strong>：同一句話對應多種 layout 結構、選錯就重做</li>
<li><strong>D 是反模式</strong>：「相對位置」永遠模糊、跳過確認等於賭 — 選錯重做的成本遠大於確認的對話成本</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>應該觸發澄清的指令</th>
          <th>第一個該確認的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「X 在 Y 旁邊」</td>
          <td>同 row 還是疊層？X 影響 Y 的位置嗎？</td>
          <td>Layout 結構（grid / absolute）</td>
      </tr>
      <tr>
          <td>「Y 顯示在 main 左側」</td>
          <td>在 main 內的 column 還是 main 外的 sidebar？</td>
          <td>跨界與否</td>
      </tr>
      <tr>
          <td>「左右兩欄獨立」</td>
          <td>「獨立」是 DOM 獨立、layout 獨立、還是 state 獨立？</td>
          <td>隔離程度</td>
      </tr>
      <tr>
          <td>「跟 Z 對齊」</td>
          <td>Z 的哪個邊（top / bottom / left / right）？</td>
          <td>對齊基準</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：相對位置描述只是意圖、不是實作藍圖。實作前先把意圖畫成 layout 草圖、確認後再開工。</p>
<p>第三輪指令類型現有五類：空間（<a href="../spatial-instruction-clarification/">#16</a>）/ 相對位置（本卡）/ 隔離（<a href="../isolation-instruction-clarification/">#18</a>）/ 決定權（<a href="../decide-vs-confirm-boundary/">#21</a>）/ 篩選（<a href="../filter-instruction-clarification/">#58</a>）。</p>
]]></content:encoded></item><item><title>隔離程度類指令的澄清時機</title><link>https://tarrragon.github.io/blog/report/isolation-instruction-clarification/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/isolation-instruction-clarification/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>「隔離」「不要動 X」是描述意圖的詞、不是描述實作的詞。&lt;/strong> 實作前先確認隔離邊界是哪一種：DOM 結構、layout flow、state、framework 管轄區。每種邊界的實作策略不同、混淆會做出不符合使用者意圖的隔離。&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>DOM 結構隔離&lt;/td>
 &lt;td>兩個元件不在同一 DOM 子樹&lt;/td>
 &lt;td>分開放在不同 ancestor&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Layout flow 隔離&lt;/td>
 &lt;td>一個元件的 layout 不影響另一個&lt;/td>
 &lt;td>absolute / fixed 跳出 flow&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>State 隔離&lt;/td>
 &lt;td>兩個元件的 state 互不影響&lt;/td>
 &lt;td>各自有獨立 state container&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Framework 管轄區隔離&lt;/td>
 &lt;td>客製 UI 與 framework UI 各自管自己&lt;/td>
 &lt;td>客製 UI 留在 framework 邊界外&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>每種需要的實作完全不同。執行者選錯邊界 = 做了不符合使用者意圖的「隔離」。&lt;/p>
&lt;hr>
&lt;h2 id="這次任務的實際情境">這次任務的實際情境&lt;/h2>
&lt;h3 id="觀察">觀察&lt;/h3>
&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>「不動 pagefind 行為」&lt;/td>
 &lt;td>不改 pagefind 的 search 邏輯&lt;/td>
 &lt;td>包含「不在 pagefind DOM 內塞客製元素」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「左右不要在同一層」&lt;/td>
 &lt;td>DOM 層級分開&lt;/td>
 &lt;td>Layout flow 互不影響（用 absolute 疊層）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>「不動 pagefind 行為」這句、我多次把 scope UI 注入 pagefind DOM、違反使用者的隔離意圖 — 我以為「不動」只指邏輯、實際包含 DOM 結構。&lt;/p>
&lt;h3 id="判讀">判讀&lt;/h3>
&lt;p>執行前該確認：「不動 / 隔離」的邊界是哪一種類型？&lt;/p>
&lt;h3 id="執行邊界類型確認-protocol">執行：邊界類型確認 protocol&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">你說的「不動 pagefind」涵蓋哪些？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> □ 不改 pagefind 的搜尋邏輯（不 fork / patch source）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> □ 不改 pagefind 渲染的 DOM 結構（不在內部 appendChild）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> □ 不改 pagefind 的 state（checkbox 勾選等）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> □ 完全不互動（連 CSS 都不覆寫）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用者勾選對應項、執行者照那個邊界實作。&lt;/p>
&lt;p>或更簡單的問法：「具體來說、什麼算動、什麼不算動？」&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>DOM 結構&lt;/td>
 &lt;td>看 ancestor chain 是否相同&lt;/td>
 &lt;td>一個元件可能影響另一個的 layout / 樣式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Layout flow&lt;/td>
 &lt;td>看是否在同一 flow（grid / flex / block）&lt;/td>
 &lt;td>一個元件撐開影響另一個位置&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>State&lt;/td>
 &lt;td>看 state 是否共用 store&lt;/td>
 &lt;td>一個元件改 state 影響另一個顯示&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Framework 管轄區&lt;/td>
 &lt;td>看是否在 framework 渲染週期內&lt;/td>
 &lt;td>Framework patch 時客製被清掉&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>執行前確認邊界類型 — 不確定就問。&lt;/p>
&lt;hr>
&lt;h2 id="隔離邊界的辨識技巧">隔離邊界的辨識技巧&lt;/h2>
&lt;h3 id="1-從會發生什麼反推">1. 從「會發生什麼」反推&lt;/h3>
&lt;p>問使用者：「如果 X 改了、Y 應該也跟著改嗎？」&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>是 — Y 跟著動&lt;/td>
 &lt;td>沒有隔離、共用 state&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>否 — Y 不動&lt;/td>
 &lt;td>State 隔離&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>否 — 連 layout 都不變&lt;/td>
 &lt;td>Layout flow 隔離&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>否 — Y 完全感知不到 X&lt;/td>
 &lt;td>DOM 隔離&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="2-從動誰會壞反推">2. 從「動誰會壞」反推&lt;/h3>
&lt;p>問：「我能在哪個 DOM 區域加東西？」&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>「隔離」「不要動 X」是描述意圖的詞、不是描述實作的詞。</strong> 實作前先確認隔離邊界是哪一種：DOM 結構、layout flow、state、framework 管轄區。每種邊界的實作策略不同、混淆會做出不符合使用者意圖的隔離。</p>
<hr>
<h2 id="為什麼隔離需要澄清">為什麼隔離需要澄清</h2>
<h3 id="商業邏輯">商業邏輯</h3>
<p>「隔離」這個詞涵蓋多種獨立的概念：</p>
<table>
  <thead>
      <tr>
          <th>隔離類型</th>
          <th>含義</th>
          <th>實作策略</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>DOM 結構隔離</td>
          <td>兩個元件不在同一 DOM 子樹</td>
          <td>分開放在不同 ancestor</td>
      </tr>
      <tr>
          <td>Layout flow 隔離</td>
          <td>一個元件的 layout 不影響另一個</td>
          <td>absolute / fixed 跳出 flow</td>
      </tr>
      <tr>
          <td>State 隔離</td>
          <td>兩個元件的 state 互不影響</td>
          <td>各自有獨立 state container</td>
      </tr>
      <tr>
          <td>Framework 管轄區隔離</td>
          <td>客製 UI 與 framework UI 各自管自己</td>
          <td>客製 UI 留在 framework 邊界外</td>
      </tr>
  </tbody>
</table>
<p>每種需要的實作完全不同。執行者選錯邊界 = 做了不符合使用者意圖的「隔離」。</p>
<hr>
<h2 id="這次任務的實際情境">這次任務的實際情境</h2>
<h3 id="觀察">觀察</h3>
<table>
  <thead>
      <tr>
          <th>指令</th>
          <th>我的初次理解</th>
          <th>使用者實際意圖</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「不動 pagefind 行為」</td>
          <td>不改 pagefind 的 search 邏輯</td>
          <td>包含「不在 pagefind DOM 內塞客製元素」</td>
      </tr>
      <tr>
          <td>「左右不要在同一層」</td>
          <td>DOM 層級分開</td>
          <td>Layout flow 互不影響（用 absolute 疊層）</td>
      </tr>
  </tbody>
</table>
<p>「不動 pagefind 行為」這句、我多次把 scope UI 注入 pagefind DOM、違反使用者的隔離意圖 — 我以為「不動」只指邏輯、實際包含 DOM 結構。</p>
<h3 id="判讀">判讀</h3>
<p>執行前該確認：「不動 / 隔離」的邊界是哪一種類型？</p>
<h3 id="執行邊界類型確認-protocol">執行：邊界類型確認 protocol</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">你說的「不動 pagefind」涵蓋哪些？
</span></span><span class="line"><span class="ln">2</span><span class="cl">  □ 不改 pagefind 的搜尋邏輯（不 fork / patch source）
</span></span><span class="line"><span class="ln">3</span><span class="cl">  □ 不改 pagefind 渲染的 DOM 結構（不在內部 appendChild）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  □ 不改 pagefind 的 state（checkbox 勾選等）
</span></span><span class="line"><span class="ln">5</span><span class="cl">  □ 完全不互動（連 CSS 都不覆寫）</span></span></code></pre></div><p>使用者勾選對應項、執行者照那個邊界實作。</p>
<p>或更簡單的問法：「具體來說、什麼算動、什麼不算動？」</p>
<hr>
<h2 id="內在屬性比較四種隔離邊界的特徵">內在屬性比較：四種隔離邊界的特徵</h2>
<table>
  <thead>
      <tr>
          <th>邊界類型</th>
          <th>偵測方式</th>
          <th>違反的後果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>DOM 結構</td>
          <td>看 ancestor chain 是否相同</td>
          <td>一個元件可能影響另一個的 layout / 樣式</td>
      </tr>
      <tr>
          <td>Layout flow</td>
          <td>看是否在同一 flow（grid / flex / block）</td>
          <td>一個元件撐開影響另一個位置</td>
      </tr>
      <tr>
          <td>State</td>
          <td>看 state 是否共用 store</td>
          <td>一個元件改 state 影響另一個顯示</td>
      </tr>
      <tr>
          <td>Framework 管轄區</td>
          <td>看是否在 framework 渲染週期內</td>
          <td>Framework patch 時客製被清掉</td>
      </tr>
  </tbody>
</table>
<p>執行前確認邊界類型 — 不確定就問。</p>
<hr>
<h2 id="隔離邊界的辨識技巧">隔離邊界的辨識技巧</h2>
<h3 id="1-從會發生什麼反推">1. 從「會發生什麼」反推</h3>
<p>問使用者：「如果 X 改了、Y 應該也跟著改嗎？」</p>
<table>
  <thead>
      <tr>
          <th>答案</th>
          <th>對應邊界</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>是 — Y 跟著動</td>
          <td>沒有隔離、共用 state</td>
      </tr>
      <tr>
          <td>否 — Y 不動</td>
          <td>State 隔離</td>
      </tr>
      <tr>
          <td>否 — 連 layout 都不變</td>
          <td>Layout flow 隔離</td>
      </tr>
      <tr>
          <td>否 — Y 完全感知不到 X</td>
          <td>DOM 隔離</td>
      </tr>
  </tbody>
</table>
<h3 id="2-從動誰會壞反推">2. 從「動誰會壞」反推</h3>
<p>問：「我能在哪個 DOM 區域加東西？」</p>
<table>
  <thead>
      <tr>
          <th>答案</th>
          <th>對應邊界</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>任何地方都可以</td>
          <td>沒有隔離</td>
      </tr>
      <tr>
          <td>自家元件內可以、X 元件內不行</td>
          <td>Framework 管轄區隔離</td>
      </tr>
      <tr>
          <td>自家元件內也要小心、不能影響 X 的 layout</td>
          <td>Layout flow 隔離</td>
      </tr>
      <tr>
          <td>完全分開、不能放在同一 DOM 子樹</td>
          <td>DOM 結構隔離</td>
      </tr>
  </tbody>
</table>
<h3 id="3-從升級時誰要動反推">3. 從「升級時誰要動」反推</h3>
<p>問：「X 升級時、我們要回頭改什麼嗎？」</p>
<table>
  <thead>
      <tr>
          <th>答案</th>
          <th>對應邊界</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>不用、客製跟 X 完全分開</td>
          <td>DOM + framework 管轄區隔離</td>
      </tr>
      <tr>
          <td>可能要調整客製 CSS</td>
          <td>Layout / state 邊界內客製</td>
      </tr>
      <tr>
          <td>客製要重做</td>
          <td>沒有隔離、客製深入 X 內部</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="設計取捨隔離指令的處理策略">設計取捨：隔離指令的處理策略</h2>
<p>四種做法、各自機會成本不同。這個專案選 A（列邊界類型確認）當預設、其他做法在特定情境合理。</p>
<h3 id="a列四種邊界類型確認這個專案的預設">A：列四種邊界類型確認（這個專案的預設）</h3>
<ul>
<li><strong>機制</strong>：列出 DOM 結構 / layout flow / state / framework 管轄區四選項、使用者勾選對應項</li>
<li><strong>選 A 的理由</strong>：明確 + 完整、使用者快速指出真正想要的隔離</li>
<li><strong>適合</strong>：隔離意圖不明確的情境</li>
<li><strong>代價</strong>：多一段四選項描述</li>
</ul>
<h3 id="b反推法從會發生什麼動誰會壞反推">B：反推法（從「會發生什麼」「動誰會壞」反推）</h3>
<ul>
<li><strong>機制</strong>：問「如果 X 改了、Y 應該也跟著改嗎？」「我能在哪個區域加東西？」根據答案歸類邊界</li>
<li><strong>跟 A 的取捨</strong>：B 對使用者比較不負擔（不需理解四種邊界術語）、A 直接呈現答案空間</li>
<li><strong>B 比 A 好的情境</strong>：使用者不熟悉 DOM / layout / framework 術語</li>
</ul>
<h3 id="c依直覺選一種實作">C：依直覺選一種實作</h3>
<ul>
<li><strong>機制</strong>：執行者自己解讀「隔離」、選一種實作</li>
<li><strong>跟 A/B 的取捨</strong>：C 跳過確認、A/B 確認；C 在意圖一致時省時間、不一致時重做</li>
<li><strong>C 是反模式</strong>：「隔離」這個詞本身就太模糊、跳過確認等於賭 — 意圖不一致時重做的成本遠大於確認的對話成本</li>
</ul>
<h3 id="d通用問法具體什麼算動">D：通用問法「具體什麼算動」</h3>
<ul>
<li><strong>機制</strong>：直接問「具體來說、什麼算動、什麼不算動？」</li>
<li><strong>跟 A 的取捨</strong>：D 比 A 更簡略、把分類負擔丟給使用者；A 直接給選項使用者只需勾選</li>
<li><strong>D 比 A 好的情境</strong>：使用者已經想得很清楚、只需要表達 — A 反而過於 structured</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>應該觸發澄清的指令</th>
          <th>第一個該確認的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「不要動 X」</td>
          <td>動哪個層面（邏輯 / DOM / state / 樣式）？</td>
          <td>邊界類型</td>
      </tr>
      <tr>
          <td>「X 跟 Y 隔離」</td>
          <td>隔離 DOM、layout、state、還是 framework？</td>
          <td>邊界類型</td>
      </tr>
      <tr>
          <td>「X 跟 Y 獨立」</td>
          <td>獨立指什麼？哪個改不影響另一個？</td>
          <td>哪個維度獨立</td>
      </tr>
      <tr>
          <td>「X 不能影響 Y」</td>
          <td>影響的方式（layout / state / 樣式）？</td>
          <td>影響途徑</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：隔離指令的核心是「隔離邊界類型」 — 這個答案決定實作策略。沒確認邊界就動手 = 隨機選一種隔離、可能與使用者意圖不一致。</p>
<p>第三輪指令類型現有五類：空間（<a href="../spatial-instruction-clarification/">#16</a>）/ 相對位置（<a href="../relative-position-instruction-clarification/">#17</a>）/ 隔離（本卡）/ 決定權（<a href="../decide-vs-confirm-boundary/">#21</a>）/ 篩選（<a href="../filter-instruction-clarification/">#58</a>）。</p>
]]></content:encoded></item><item><title>覆寫深度的成本告知</title><link>https://tarrragon.github.io/blog/report/override-depth-cost-report/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/override-depth-cost-report/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>覆寫成本要在開工前報、不能默默承擔。&lt;/strong> 客製要對抗多層（UA 預設 + 跨瀏覽器 + framework specificity）時、先把「需要寫多少 / 哪幾條 / 是否有殘留風險」攤開、讓使用者用「視覺改善 vs 維護成本」的角度判斷值不值。&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;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>執行者覺得值得、使用者覺得太貴&lt;/td>
 &lt;td>寫了 5 條 CSS 後使用者說「先還原」、白做&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;hr>
&lt;h2 id="這次任務的實際情境">這次任務的實際情境&lt;/h2>
&lt;h3 id="觀察">觀察&lt;/h3>
&lt;p>要移除 Pagefind filter 的 &lt;code>&amp;lt;details&amp;gt;&amp;lt;summary&amp;gt;&lt;/code> disclosure 三角圖示。&lt;/p>
&lt;p>我嘗試了：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c">/* 1. UA 預設 marker（Chrome / Firefox） */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="nt">summary&lt;/span>&lt;span class="p">::&lt;/span>&lt;span class="nd">marker&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">transparent&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">font-size&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c">/* 2. UA 預設 marker（Safari / 老 Chrome） */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="nt">summary&lt;/span>&lt;span class="p">::&lt;/span>&lt;span class="nd">-webkit-details-marker&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">display&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">none&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c">/* 3. 改 summary display 避免 list-item 行為 */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="nt">summary&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">display&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">block&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">list-style&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">none&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c">/* 4. 蓋過 pagefind 的 ::after 自訂 chevron */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="p">.&lt;/span>&lt;span class="nc">pagefind-ui__filter-name&lt;/span>&lt;span class="p">::&lt;/span>&lt;span class="nd">after&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">display&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">none&lt;/span> &lt;span class="cp">!important&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c">/* 5. 處理 reset 邊界外的 fallback */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c">/* ... */&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>寫完後使用者說：「如果要做到這麼大的複寫原設計、先還原回去、先不要做這個變更」。&lt;/p>
&lt;h3 id="判讀">判讀&lt;/h3>
&lt;p>我的失敗：開工前沒報「這個客製需要對抗 UA + 跨瀏覽器 + framework 三層、預估 5+ 條 CSS、跨瀏覽器有殘留風險」。直接做、使用者看到改動規模才退回。&lt;/p>
&lt;p>正確流程應該在嘗試第 2 條 CSS 時就停下來報告：&lt;/p>
&lt;blockquote>
&lt;p>移除 disclosure 三角需要對抗：&lt;/p>
&lt;ul>
&lt;li>UA 預設 marker（Chrome / Firefox 的 &lt;code>::marker&lt;/code>、Safari / 老 Chrome 的 &lt;code>::-webkit-details-marker&lt;/code>）&lt;/li>
&lt;li>Summary 預設 display: list-item 行為&lt;/li>
&lt;li>Pagefind 的自訂 &lt;code>::after&lt;/code> chevron&lt;/li>
&lt;/ul>
&lt;p>預估 4-5 條 CSS 跨 3 種瀏覽器寫法、可能有殘留風險（&lt;code>::marker&lt;/code> 在某些瀏覽器版本不能用 display: none）。&lt;/p>
&lt;p>視覺改善：filter 名稱旁邊少一個小三角。&lt;/p>
&lt;p>值得做嗎？&lt;/p>&lt;/blockquote>
&lt;p>讓使用者判斷再決定。&lt;/p>
&lt;h3 id="執行覆寫成本告知-protocol">執行：覆寫成本告知 protocol&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>UA 預設&lt;/td>
 &lt;td>跨瀏覽器有差異嗎？需要寫幾種 pseudo？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Framework specificity&lt;/td>
 &lt;td>框架 CSS 用 hash class 提升 specificity 嗎？需要 layers / important / 雙寫嗎？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Framework 渲染週期&lt;/td>
 &lt;td>改了會被 reset 嗎？需要 observer 補打嗎？&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>任一層有「需要對抗」就把成本報出來、讓使用者參與決定。&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>1 條 CSS、單一瀏覽器&lt;/td>
 &lt;td>低&lt;/td>
 &lt;td>任何&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>1-2 條 CSS、跨瀏覽器（用 layers / important）&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>影響 UX 的視覺改善&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3+ 條 CSS、跨瀏覽器 + framework&lt;/td>
 &lt;td>高&lt;/td>
 &lt;td>必要的核心客製&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>跨 framework 渲染週期、需要 observer 補打&lt;/td>
 &lt;td>最高&lt;/td>
 &lt;td>改善價值極高才值得&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>「成本 vs 改善價值」的對應 — 高成本只用在高價值場景。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>覆寫成本要在開工前報、不能默默承擔。</strong> 客製要對抗多層（UA 預設 + 跨瀏覽器 + framework specificity）時、先把「需要寫多少 / 哪幾條 / 是否有殘留風險」攤開、讓使用者用「視覺改善 vs 維護成本」的角度判斷值不值。</p>
<hr>
<h2 id="為什麼成本要事先告知">為什麼成本要事先告知</h2>
<h3 id="商業邏輯">商業邏輯</h3>
<p>執行者單方決定「這客製值不值得做」會出現兩種失敗：</p>
<table>
  <thead>
      <tr>
          <th>失敗模式</th>
          <th>表現</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>執行者覺得值得、使用者覺得太貴</td>
          <td>寫了 5 條 CSS 後使用者說「先還原」、白做</td>
      </tr>
      <tr>
          <td>執行者覺得不值、使用者覺得很重要</td>
          <td>沒做、使用者覺得敷衍</td>
      </tr>
  </tbody>
</table>
<p>兩種失敗都來自「成本與價值的判斷沒對齊」。把成本攤開讓使用者參與判斷、避免兩種失敗。</p>
<hr>
<h2 id="這次任務的實際情境">這次任務的實際情境</h2>
<h3 id="觀察">觀察</h3>
<p>要移除 Pagefind filter 的 <code>&lt;details&gt;&lt;summary&gt;</code> disclosure 三角圖示。</p>
<p>我嘗試了：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c">/* 1. UA 預設 marker（Chrome / Firefox） */</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nt">summary</span><span class="p">::</span><span class="nd">marker</span> <span class="p">{</span> <span class="k">content</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">;</span> <span class="k">color</span><span class="p">:</span> <span class="kc">transparent</span><span class="p">;</span> <span class="k">font-size</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c">/* 2. UA 預設 marker（Safari / 老 Chrome） */</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nt">summary</span><span class="p">::</span><span class="nd">-webkit-details-marker</span> <span class="p">{</span> <span class="k">display</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c">/* 3. 改 summary display 避免 list-item 行為 */</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nt">summary</span> <span class="p">{</span> <span class="k">display</span><span class="p">:</span> <span class="kc">block</span><span class="p">;</span> <span class="k">list-style</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c">/* 4. 蓋過 pagefind 的 ::after 自訂 chevron */</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="p">.</span><span class="nc">pagefind-ui__filter-name</span><span class="p">::</span><span class="nd">after</span> <span class="p">{</span> <span class="k">display</span><span class="p">:</span> <span class="kc">none</span> <span class="cp">!important</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c">/* 5. 處理 reset 邊界外的 fallback */</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c">/* ... */</span></span></span></code></pre></div><p>寫完後使用者說：「如果要做到這麼大的複寫原設計、先還原回去、先不要做這個變更」。</p>
<h3 id="判讀">判讀</h3>
<p>我的失敗：開工前沒報「這個客製需要對抗 UA + 跨瀏覽器 + framework 三層、預估 5+ 條 CSS、跨瀏覽器有殘留風險」。直接做、使用者看到改動規模才退回。</p>
<p>正確流程應該在嘗試第 2 條 CSS 時就停下來報告：</p>
<blockquote>
<p>移除 disclosure 三角需要對抗：</p>
<ul>
<li>UA 預設 marker（Chrome / Firefox 的 <code>::marker</code>、Safari / 老 Chrome 的 <code>::-webkit-details-marker</code>）</li>
<li>Summary 預設 display: list-item 行為</li>
<li>Pagefind 的自訂 <code>::after</code> chevron</li>
</ul>
<p>預估 4-5 條 CSS 跨 3 種瀏覽器寫法、可能有殘留風險（<code>::marker</code> 在某些瀏覽器版本不能用 display: none）。</p>
<p>視覺改善：filter 名稱旁邊少一個小三角。</p>
<p>值得做嗎？</p></blockquote>
<p>讓使用者判斷再決定。</p>
<h3 id="執行覆寫成本告知-protocol">執行：覆寫成本告知 protocol</h3>
<p>開始任何客製前、先評估這三個累積層：</p>
<table>
  <thead>
      <tr>
          <th>層</th>
          <th>評估問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>UA 預設</td>
          <td>跨瀏覽器有差異嗎？需要寫幾種 pseudo？</td>
      </tr>
      <tr>
          <td>Framework specificity</td>
          <td>框架 CSS 用 hash class 提升 specificity 嗎？需要 layers / important / 雙寫嗎？</td>
      </tr>
      <tr>
          <td>Framework 渲染週期</td>
          <td>改了會被 reset 嗎？需要 observer 補打嗎？</td>
      </tr>
  </tbody>
</table>
<p>任一層有「需要對抗」就把成本報出來、讓使用者參與決定。</p>
<hr>
<h2 id="內在屬性比較四種覆寫深度">內在屬性比較：四種覆寫深度</h2>
<table>
  <thead>
      <tr>
          <th>深度</th>
          <th>成本</th>
          <th>適合的視覺改善</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1 條 CSS、單一瀏覽器</td>
          <td>低</td>
          <td>任何</td>
      </tr>
      <tr>
          <td>1-2 條 CSS、跨瀏覽器（用 layers / important）</td>
          <td>中</td>
          <td>影響 UX 的視覺改善</td>
      </tr>
      <tr>
          <td>3+ 條 CSS、跨瀏覽器 + framework</td>
          <td>高</td>
          <td>必要的核心客製</td>
      </tr>
      <tr>
          <td>跨 framework 渲染週期、需要 observer 補打</td>
          <td>最高</td>
          <td>改善價值極高才值得</td>
      </tr>
  </tbody>
</table>
<p>「成本 vs 改善價值」的對應 — 高成本只用在高價值場景。</p>
<hr>
<h2 id="告知時機與格式">告知時機與格式</h2>
<h3 id="觸發點">觸發點</h3>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>應該停下來告知</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>寫到第 2 條 CSS 還沒蓋過原設計</td>
          <td>是 — 這通常表示有第二、第三層問題</td>
      </tr>
      <tr>
          <td>跨瀏覽器寫法（<code>-webkit-</code>、<code>::marker</code> 雙寫）</td>
          <td>是 — 跨層成本累積</td>
      </tr>
      <tr>
          <td>加 <code>!important</code></td>
          <td>是 — specificity 戰開始</td>
      </tr>
      <tr>
          <td>加 observer 補打防 reset</td>
          <td>是 — 跟 framework 渲染週期競爭</td>
      </tr>
  </tbody>
</table>
<h3 id="報告格式">報告格式</h3>





<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">  - 對抗 [UA / framework / 跨瀏覽器]：N 條 CSS
</span></span><span class="line"><span class="ln">3</span><span class="cl">  - 殘留風險：[列出可能在某些情境失效的 case]
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - 改善價值：[視覺差異、UX 改善]
</span></span><span class="line"><span class="ln">5</span><span class="cl">  
</span></span><span class="line"><span class="ln">6</span><span class="cl">值得做嗎？或先接受原設計？</span></span></code></pre></div><p>讓使用者用「成本 vs 價值」做決定。</p>
<hr>
<h2 id="設計取捨客製深度告知的時機">設計取捨：客製深度告知的時機</h2>
<p>四種做法、各自機會成本不同。這個專案選 A（開工前評估 + 第 2 條 CSS 失敗即告知）當預設、其他做法在特定情境合理。</p>
<h3 id="a開工前評估三層成本開工後第-2-條失敗即告知這個專案的預設">A：開工前評估三層成本、開工後第 2 條失敗即告知（這個專案的預設）</h3>
<ul>
<li><strong>機制</strong>：開工前評估 UA / framework / 渲染週期三層；開工後寫到第 2 條 CSS 還沒蓋過就停下告知</li>
<li><strong>選 A 的理由</strong>：使用者參與「值不值」判斷、避免做到一半被退回</li>
<li><strong>適合</strong>：所有有覆寫嫌疑的客製</li>
<li><strong>代價</strong>：對話成本（一段成本評估 + 等決定）</li>
</ul>
<h3 id="b寫到第-n-條才告知n--2">B：寫到第 N 條才告知（N &gt; 2）</h3>
<ul>
<li><strong>機制</strong>：執行者自己加碼、到 4-5 條才停</li>
<li><strong>跟 A 的取捨</strong>：B 給執行者更多嘗試空間、A 早提早決；B 在 N 增加時白費時間放大</li>
<li><strong>B 是反模式</strong>：第 2 次失敗就是 <a href="../two-occurrence-threshold/">#42 2 次門檻</a> 的訊號、繼續加碼只是放大沉沒成本</li>
</ul>
<h3 id="c默默寫到底不告知">C：默默寫到底、不告知</h3>
<ul>
<li><strong>機制</strong>：執行者自己承擔、不報告成本</li>
<li><strong>成本特別高的原因</strong>：使用者看到改動規模才退回、所有時間白費</li>
<li><strong>C 才合理的情境</strong>：客製極簡（&lt; 1 條 CSS）、確定不會對抗任何層</li>
</ul>
<h3 id="d開工前直接接受原設計不嘗試">D：開工前直接接受原設計、不嘗試</h3>
<ul>
<li><strong>機制</strong>：看到客製需求是「對抗多層」就直接拒絕、不寫</li>
<li><strong>跟 A 的取捨</strong>：D 完全省成本、A 留空間給「值得做」的客製</li>
<li><strong>D 比 A 好的情境</strong>：使用者明確說「這是視覺微調」+ 對抗三層、且預估成本高 — 直接接受原設計</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該觸發告知的時機</th>
          <th>報告內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>寫到第 2 條 CSS 還沒蓋過原設計</td>
          <td>立刻</td>
          <td>列出對抗的層、預估還要寫多少</td>
      </tr>
      <tr>
          <td>加跨瀏覽器寫法（pseudo 雙寫）</td>
          <td>立刻</td>
          <td>UA 差異、各瀏覽器寫法</td>
      </tr>
      <tr>
          <td>加 <code>!important</code></td>
          <td>立刻</td>
          <td>Specificity 戰開始、考慮 layers</td>
      </tr>
      <tr>
          <td>加 observer 補打</td>
          <td>立刻</td>
          <td>跟 framework 渲染競爭、可能不穩</td>
      </tr>
      <tr>
          <td>改善價值不明顯（純視覺微調）</td>
          <td>開工前</td>
          <td>列改善內容、讓使用者衡量</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：客製成本是使用者該知道的資訊、不是執行者單方承擔。事先告知 = 共同決定 = 不會做到一半被退回。</p>
<p>成本告知有兩種時機 — 本卡聚焦「實作前告知工程成本」、runtime 持續顯示掃描成本見 <a href="../pattern-honest-progress-ui/">#62 Pattern：誠實進度 UX</a>。共同精神是「不 silent 累積負擔」。</p>
]]></content:encoded></item><item><title>「可決定」與「該先確認」的邊界</title><link>https://tarrragon.github.io/blog/report/decide-vs-confirm-boundary/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/decide-vs-confirm-boundary/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>「可決定」與「該先確認」的分界線是「使用者會看到嗎」。&lt;/strong> 純技術實作細節（用 grid 或 flex、用 ResizeObserver 或 setInterval）可以自決；但只要結果會在 UI 上出現（數字、順序、文字、配色），就要先給選項讓使用者點頭。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼要分這條線">為什麼要分這條線&lt;/h2>
&lt;h3 id="商業邏輯">商業邏輯&lt;/h3>
&lt;p>執行者自決所有事 = 強迫使用者用「視覺驗收」做決定 — 看到結果才能說「這不對」、不對就要重做。&lt;/p>
&lt;p>把「使用者會看到的決定」拉出來事先確認 = 在實作前讓使用者參與決策、避免實作後被退回。&lt;/p>
&lt;p>但所有事都要確認 = 對話成本爆炸、使用者疲勞、效率低。&lt;/p>
&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;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>Filter sidebar breakpoint = 1400px&lt;/td>
 &lt;td>該確認 — 使用者視窗大小不確定&lt;/td>
 &lt;td>自決寫死&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Filter 順序 type → tag&lt;/td>
 &lt;td>該確認 — UX 偏好&lt;/td>
 &lt;td>自決寫死、後被肯定&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Scope-h 預設值 = 56px&lt;/td>
 &lt;td>該確認 — 視覺差異明顯&lt;/td>
 &lt;td>自決寫死、後被否定&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Filter 寬度 400px&lt;/td>
 &lt;td>使用者已給數值&lt;/td>
 &lt;td>直接用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>用 absolute 定位而非 grid&lt;/td>
 &lt;td>純技術選擇&lt;/td>
 &lt;td>自決、無需確認&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>用 ResizeObserver 而非 setInterval&lt;/td>
 &lt;td>純技術選擇&lt;/td>
 &lt;td>自決、無需確認&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>可以看出規則：使用者會看到的視覺結果（breakpoint 對應的 viewport 行為、順序對應的閱讀體驗、預設值對應的初始視覺）都該確認；底層工具選擇（grid / flex / absolute、ResizeObserver / setInterval）可以自決。&lt;/p>
&lt;h3 id="判讀">判讀&lt;/h3>
&lt;p>判斷標準是「這個決定會在 UI 上產生使用者能感知的差異嗎」：&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>Visible 數字&lt;/td>
 &lt;td>breakpoint、預設尺寸、初始值&lt;/td>
 &lt;td>內部 calculation 細節&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>順序&lt;/td>
 &lt;td>filter 排序、選單排序&lt;/td>
 &lt;td>DOM tree 排序（不影響視覺）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>文字&lt;/td>
 &lt;td>UI 標籤、訊息&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>grid / flex / observer 等&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="執行自決前的兩問">執行：自決前的兩問&lt;/h3>
&lt;p>每個決定執行前先問：&lt;/p>
&lt;ol>
&lt;li>這個決定在 UI 上會產生使用者能感知的差異嗎？&lt;/li>
&lt;li>是不是有多個合理選項、選不同會影響使用者體驗？&lt;/li>
&lt;/ol>
&lt;p>兩個都「是」 → 該確認。&lt;/p>
&lt;p>兩個都「否」或只有一個「是」 → 可自決。&lt;/p>
&lt;hr>
&lt;h2 id="確認的格式給選項而非開放問">確認的格式：給選項而非開放問&lt;/h2>
&lt;h3 id="較差的問法">較差的問法&lt;/h3>
&lt;blockquote>
&lt;p>「Breakpoint 應該設多少？」&lt;/p>&lt;/blockquote>
&lt;p>開放問題、使用者要自己想出答案。&lt;/p>
&lt;h3 id="較好的問法">較好的問法&lt;/h3>
&lt;blockquote>
&lt;p>「Breakpoint 我預估三個選項：&lt;/p>
&lt;ul>
&lt;li>1280px：物理上能放下、但邊緣情境可能擠壓&lt;/li>
&lt;li>1400px：較安全、有 120px 餘裕&lt;/li>
&lt;li>1564px：完全不溢出 body padding、最保守&lt;/li>
&lt;/ul>
&lt;p>我會選 1400px 作為平衡。OK 嗎？或要其他？」&lt;/p>&lt;/blockquote>
&lt;p>給選項 + 推薦 + 開放修改空間 — 使用者可以「OK」「換 1280」「再放寬到 1600」三種回應。對話成本低。&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;th>適用情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>全部自決&lt;/td>
 &lt;td>0&lt;/td>
 &lt;td>高&lt;/td>
 &lt;td>純技術實作細節&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>全部確認&lt;/td>
 &lt;td>高&lt;/td>
 &lt;td>0&lt;/td>
 &lt;td>不適用、太煩&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>自決技術細節、確認 visible 決定&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>涉及 UX 偏好的決定&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>優先「自決技術細節 + 列選項確認 visible 決定」 — 對話成本低、重做風險低。&lt;/p>
&lt;hr>
&lt;h2 id="使用者會看到嗎的測試">「使用者會看到嗎」的測試&lt;/h2>
&lt;p>當不確定某個決定該確認還是自決時、用三個測試：&lt;/p>
&lt;h3 id="1-ui-變動測試">1. UI 變動測試&lt;/h3>
&lt;p>「不同選擇會在 UI 上看到差異嗎？」&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>「可決定」與「該先確認」的分界線是「使用者會看到嗎」。</strong> 純技術實作細節（用 grid 或 flex、用 ResizeObserver 或 setInterval）可以自決；但只要結果會在 UI 上出現（數字、順序、文字、配色），就要先給選項讓使用者點頭。</p>
<hr>
<h2 id="為什麼要分這條線">為什麼要分這條線</h2>
<h3 id="商業邏輯">商業邏輯</h3>
<p>執行者自決所有事 = 強迫使用者用「視覺驗收」做決定 — 看到結果才能說「這不對」、不對就要重做。</p>
<p>把「使用者會看到的決定」拉出來事先確認 = 在實作前讓使用者參與決策、避免實作後被退回。</p>
<p>但所有事都要確認 = 對話成本爆炸、使用者疲勞、效率低。</p>
<p>兩者的平衡點：<strong>只把使用者實際在乎的決定攤出來確認、技術細節不打擾</strong>。</p>
<hr>
<h2 id="這次任務的實際情境">這次任務的實際情境</h2>
<h3 id="觀察">觀察</h3>
<p>我自決後被肯定或否定的決定：</p>
<table>
  <thead>
      <tr>
          <th>決定</th>
          <th>應該的處理</th>
          <th>實際處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Filter sidebar breakpoint = 1400px</td>
          <td>該確認 — 使用者視窗大小不確定</td>
          <td>自決寫死</td>
      </tr>
      <tr>
          <td>Filter 順序 type → tag</td>
          <td>該確認 — UX 偏好</td>
          <td>自決寫死、後被肯定</td>
      </tr>
      <tr>
          <td>Scope-h 預設值 = 56px</td>
          <td>該確認 — 視覺差異明顯</td>
          <td>自決寫死、後被否定</td>
      </tr>
      <tr>
          <td>Filter 寬度 400px</td>
          <td>使用者已給數值</td>
          <td>直接用</td>
      </tr>
      <tr>
          <td>用 absolute 定位而非 grid</td>
          <td>純技術選擇</td>
          <td>自決、無需確認</td>
      </tr>
      <tr>
          <td>用 ResizeObserver 而非 setInterval</td>
          <td>純技術選擇</td>
          <td>自決、無需確認</td>
      </tr>
  </tbody>
</table>
<p>可以看出規則：使用者會看到的視覺結果（breakpoint 對應的 viewport 行為、順序對應的閱讀體驗、預設值對應的初始視覺）都該確認；底層工具選擇（grid / flex / absolute、ResizeObserver / setInterval）可以自決。</p>
<h3 id="判讀">判讀</h3>
<p>判斷標準是「這個決定會在 UI 上產生使用者能感知的差異嗎」：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>該先確認</th>
          <th>可自決</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Visible 數字</td>
          <td>breakpoint、預設尺寸、初始值</td>
          <td>內部 calculation 細節</td>
      </tr>
      <tr>
          <td>順序</td>
          <td>filter 排序、選單排序</td>
          <td>DOM tree 排序（不影響視覺）</td>
      </tr>
      <tr>
          <td>文字</td>
          <td>UI 標籤、訊息</td>
          <td>內部變數名</td>
      </tr>
      <tr>
          <td>配色 / 視覺樣式</td>
          <td>使用者看得到</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>技術選擇</td>
          <td>不適用</td>
          <td>grid / flex / observer 等</td>
      </tr>
  </tbody>
</table>
<h3 id="執行自決前的兩問">執行：自決前的兩問</h3>
<p>每個決定執行前先問：</p>
<ol>
<li>這個決定在 UI 上會產生使用者能感知的差異嗎？</li>
<li>是不是有多個合理選項、選不同會影響使用者體驗？</li>
</ol>
<p>兩個都「是」 → 該確認。</p>
<p>兩個都「否」或只有一個「是」 → 可自決。</p>
<hr>
<h2 id="確認的格式給選項而非開放問">確認的格式：給選項而非開放問</h2>
<h3 id="較差的問法">較差的問法</h3>
<blockquote>
<p>「Breakpoint 應該設多少？」</p></blockquote>
<p>開放問題、使用者要自己想出答案。</p>
<h3 id="較好的問法">較好的問法</h3>
<blockquote>
<p>「Breakpoint 我預估三個選項：</p>
<ul>
<li>1280px：物理上能放下、但邊緣情境可能擠壓</li>
<li>1400px：較安全、有 120px 餘裕</li>
<li>1564px：完全不溢出 body padding、最保守</li>
</ul>
<p>我會選 1400px 作為平衡。OK 嗎？或要其他？」</p></blockquote>
<p>給選項 + 推薦 + 開放修改空間 — 使用者可以「OK」「換 1280」「再放寬到 1600」三種回應。對話成本低。</p>
<hr>
<h2 id="內在屬性比較四種決策模式">內在屬性比較：四種決策模式</h2>
<table>
  <thead>
      <tr>
          <th>模式</th>
          <th>對話成本</th>
          <th>重做風險</th>
          <th>適用情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>全部自決</td>
          <td>0</td>
          <td>高</td>
          <td>純技術實作細節</td>
      </tr>
      <tr>
          <td>全部確認</td>
          <td>高</td>
          <td>0</td>
          <td>不適用、太煩</td>
      </tr>
      <tr>
          <td>自決技術細節、確認 visible 決定</td>
          <td>低</td>
          <td>低</td>
          <td>一般情境</td>
      </tr>
      <tr>
          <td>列選項 + 推薦讓使用者選</td>
          <td>低</td>
          <td>最低</td>
          <td>涉及 UX 偏好的決定</td>
      </tr>
  </tbody>
</table>
<p>優先「自決技術細節 + 列選項確認 visible 決定」 — 對話成本低、重做風險低。</p>
<hr>
<h2 id="使用者會看到嗎的測試">「使用者會看到嗎」的測試</h2>
<p>當不確定某個決定該確認還是自決時、用三個測試：</p>
<h3 id="1-ui-變動測試">1. UI 變動測試</h3>
<p>「不同選擇會在 UI 上看到差異嗎？」</p>
<table>
  <thead>
      <tr>
          <th>例</th>
          <th>答</th>
          <th>結論</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>用 grid 還是 flex 排兩欄</td>
          <td>否（最終視覺一樣）</td>
          <td>自決</td>
      </tr>
      <tr>
          <td>Breakpoint 1280 vs 1400</td>
          <td>是（不同 viewport 下行為不同）</td>
          <td>確認</td>
      </tr>
  </tbody>
</table>
<h3 id="2-ux-偏好測試">2. UX 偏好測試</h3>
<p>「選不同會讓使用者覺得體驗不同嗎？」</p>
<table>
  <thead>
      <tr>
          <th>例</th>
          <th>答</th>
          <th>結論</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Filter 順序 type 在前 vs tag 在前</td>
          <td>是（掃描成本不同）</td>
          <td>確認</td>
      </tr>
      <tr>
          <td>用 ResizeObserver 還是 setInterval</td>
          <td>否（使用者感知不到差異）</td>
          <td>自決</td>
      </tr>
  </tbody>
</table>
<h3 id="3-不可逆測試">3. 不可逆測試</h3>
<p>「這個決定寫進 commit 後、之後改成本高嗎？」</p>
<table>
  <thead>
      <tr>
          <th>例</th>
          <th>答</th>
          <th>結論</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Section 名稱（content/report/）</td>
          <td>是（改動要 redirect、broken link）</td>
          <td>確認</td>
      </tr>
      <tr>
          <td>內部 helper function 名稱</td>
          <td>否（rename 一行 grep）</td>
          <td>自決</td>
      </tr>
  </tbody>
</table>
<p>三個測試任一個「是」 → 確認。</p>
<hr>
<h2 id="設計取捨決定權分配的策略">設計取捨：決定權分配的策略</h2>
<p>四種做法、各自機會成本不同。這個專案選 A（visible 決定先確認 + 技術自決 + 給選項）當預設、其他做法在特定情境合理。</p>
<h3 id="avisible-決定先確認技術自決確認時給選項這個專案的預設">A：Visible 決定先確認、技術自決、確認時給選項（這個專案的預設）</h3>
<ul>
<li><strong>機制</strong>：使用者會看到的數字 / 順序 / 文字先列選項給使用者選；純技術實作（grid / flex / observer）自決</li>
<li><strong>選 A 的理由</strong>：對話成本低（只確認該確認的）+ 重做風險低（visible 決定使用者參與）</li>
<li><strong>適合</strong>：所有客製情境</li>
<li><strong>代價</strong>：執行者要主動分辨「visible vs 技術細節」、給選項時要先想出選項</li>
</ul>
<h3 id="b全部自決">B：全部自決</h3>
<ul>
<li><strong>機制</strong>：執行者自己決定所有事</li>
<li><strong>跟 A 的取捨</strong>：B 對話成本 0、A 適度；B 容易做到使用者不要的東西</li>
<li><strong>B 才合理的情境</strong>：純內部工具、執行者就是使用者；或時間極緊、優先求動</li>
</ul>
<h3 id="c全部確認">C：全部確認</h3>
<ul>
<li><strong>機制</strong>：每個決定都先問</li>
<li><strong>跟 A 的取捨</strong>：C 重做風險 0、A 適度；C 對話成本爆炸、使用者疲勞</li>
<li><strong>C 才合理的情境</strong>：完全不熟悉的領域、執行者沒有判斷能力（罕見、應透過學習脫離此狀態）</li>
</ul>
<h3 id="d開放問題不給選項">D：開放問題、不給選項</h3>
<ul>
<li><strong>機制</strong>：直接問「breakpoint 應該設多少」</li>
<li><strong>跟 A 的取捨</strong>：D 把分析負擔丟給使用者、A 執行者先做分析給選項</li>
<li><strong>D 才合理的情境</strong>：使用者已經有明確答案、只需要傳達 — 否則 A 的「給選項 + 推薦」更有效率</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>應該的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>即將寫死一個 visible 數字（padding、margin、breakpoint）</td>
          <td>列選項確認、不要自決</td>
      </tr>
      <tr>
          <td>即將決定一個 visible 順序（filter、選單）</td>
          <td>列選項確認</td>
      </tr>
      <tr>
          <td>即將寫使用者會看到的文字（label、訊息）</td>
          <td>確認措辭</td>
      </tr>
      <tr>
          <td>即將選擇技術實作（grid / flex / observer）</td>
          <td>自決</td>
      </tr>
      <tr>
          <td>即將命名內部 helper / 變數</td>
          <td>自決</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：能影響使用者體驗的決定屬於使用者、能影響執行者效率的決定屬於執行者。分清楚就不會把該確認的事自決、也不會把該自決的事拿去煩使用者。</p>
<p>第三輪指令類型現有五類：空間（#16）/ 相對位置（#17）/ 隔離（#18）/ 決定權（本卡 #21）/ 篩選（<a href="../filter-instruction-clarification/">#58</a>）。前四類缺幾何 / 邊界 / 拍板資訊、第 5 類缺操作層級資訊。</p>
]]></content:encoded></item><item><title>「先還原」「先重來」類退出指令的處理</title><link>https://tarrragon.github.io/blog/report/revert-instruction-handling/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/revert-instruction-handling/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>退出指令（「先還原」「先重來」「先放著」）的執行前要先確認兩件事：還原到哪個狀態、要不要先存 checkpoint。&lt;/strong> 直接刪掉當前進度、未來想比較沒得比、想恢復也找不到。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼退出指令需要-protocol">為什麼退出指令需要 protocol&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>換個方向重做&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「先重來」&lt;/td>
 &lt;td>從上一個 commit 重新試&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;hr>
&lt;h2 id="這次任務的實際情境">這次任務的實際情境&lt;/h2>
&lt;h3 id="觀察">觀察&lt;/h3>
&lt;p>使用者說：「如果要做到這麼大的複寫原設計、我們先還原回去、先不要做這個變更」。&lt;/p>
&lt;p>我立刻刪掉那段 CSS、繼續往下做其他事。沒問「還原到哪」、沒先 commit checkpoint。&lt;/p>
&lt;h3 id="判讀">判讀&lt;/h3>
&lt;p>後來想比較「複雜覆寫版本」與「接受原設計版本」的差異 — 沒得比。「複雜覆寫版本」已經不存在於 git 歷史。&lt;/p>
&lt;p>正確流程應該是：&lt;/p>
&lt;ol>
&lt;li>收到「還原」指令時、先回應「我會先 commit 當前進度（即使未採用）作為 checkpoint，再還原到 X 狀態。OK 嗎？」&lt;/li>
&lt;li>確認後、commit 當前狀態（不 push）、commit message 標明「探索版本、未採用」&lt;/li>
&lt;li>還原到 X 狀態&lt;/li>
&lt;li>繼續做後續事&lt;/li>
&lt;/ol>
&lt;p>未來想比較或恢復、checkpoint 都還在。&lt;/p>
&lt;h3 id="執行退出指令的-protocol">執行：退出指令的 protocol&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>1&lt;/td>
 &lt;td>暫停執行、不要立刻刪&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2&lt;/td>
 &lt;td>確認「還原到哪個狀態」（上個 commit / 特定 commit / 完全乾淨）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3&lt;/td>
 &lt;td>評估「當前進度有保留價值嗎」 — 探索成果、未採用方案、可能未來重用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>4&lt;/td>
 &lt;td>有保留價值 → 先 commit checkpoint、message 標明「探索、未採用」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>5&lt;/td>
 &lt;td>執行還原（reset / checkout / revert）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>6&lt;/td>
 &lt;td>確認還原後狀態符合使用者意圖&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="checkpoint-的命名與-commit-message">Checkpoint 的命名與 commit message&lt;/h2>
&lt;p>當前進度作為 checkpoint commit、message 應該包含：&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">chore(explore): N+1 attempts to remove disclosure marker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">探索方向：用 ::-webkit-details-marker / ::marker / display: block 三層
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">覆寫移除 disclosure 三角圖示。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">寫了 5 條 CSS 跨 3 種瀏覽器、覆寫成本過高。
&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>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">此 commit 保留探索成果、未來若評估值得做時可參考。&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵元素：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>chore(explore):&lt;/code>&lt;/strong> prefix — 標明非正式採用&lt;/li>
&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;/ul>
&lt;p>未來人看到這個 commit、知道「這是探索、不是當前實作」、不會誤用。&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;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;code>git reset --hard&lt;/code>（未 commit 直接丟）&lt;/td>
 &lt;td>低 — git reflog 短期還在&lt;/td>
 &lt;td>困難&lt;/td>
 &lt;td>確定不要&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>git stash&lt;/code>（暫存到 stash）&lt;/td>
 &lt;td>中 — stash 可隨時恢復&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>短期暫停&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>git commit&lt;/code> checkpoint 後 reset / revert&lt;/td>
 &lt;td>高 — commit 永久存在&lt;/td>
 &lt;td>容易&lt;/td>
 &lt;td>探索性嘗試、未採用方案&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>優先選 checkpoint 方式 — 為未來保留比較與恢復的可能性。&lt;/p>
&lt;hr>
&lt;h2 id="退出意圖的辨識">退出意圖的辨識&lt;/h2>
&lt;h3 id="從語氣判斷">從語氣判斷&lt;/h3>
&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>Checkpoint + 還原&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「先還原、不要做了」&lt;/td>
 &lt;td>確定放棄&lt;/td>
 &lt;td>Checkpoint（小機率重看） + 還原&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>「重來」&lt;/td>
 &lt;td>換個方向&lt;/td>
 &lt;td>Checkpoint + 還原到起點&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;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>退出指令（「先還原」「先重來」「先放著」）的執行前要先確認兩件事：還原到哪個狀態、要不要先存 checkpoint。</strong> 直接刪掉當前進度、未來想比較沒得比、想恢復也找不到。</p>
<hr>
<h2 id="為什麼退出指令需要-protocol">為什麼退出指令需要 protocol</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>換個方向重做</td>
      </tr>
      <tr>
          <td>「先重來」</td>
          <td>從上一個 commit 重新試</td>
      </tr>
      <tr>
          <td>「先重來」</td>
          <td>從更早的點重新試</td>
      </tr>
  </tbody>
</table>
<p>執行者不確認意圖、直接刪 = 把使用者的選項收窄成「沒有了」。事先確認 = 為使用者保留可能性。</p>
<hr>
<h2 id="這次任務的實際情境">這次任務的實際情境</h2>
<h3 id="觀察">觀察</h3>
<p>使用者說：「如果要做到這麼大的複寫原設計、我們先還原回去、先不要做這個變更」。</p>
<p>我立刻刪掉那段 CSS、繼續往下做其他事。沒問「還原到哪」、沒先 commit checkpoint。</p>
<h3 id="判讀">判讀</h3>
<p>後來想比較「複雜覆寫版本」與「接受原設計版本」的差異 — 沒得比。「複雜覆寫版本」已經不存在於 git 歷史。</p>
<p>正確流程應該是：</p>
<ol>
<li>收到「還原」指令時、先回應「我會先 commit 當前進度（即使未採用）作為 checkpoint，再還原到 X 狀態。OK 嗎？」</li>
<li>確認後、commit 當前狀態（不 push）、commit message 標明「探索版本、未採用」</li>
<li>還原到 X 狀態</li>
<li>繼續做後續事</li>
</ol>
<p>未來想比較或恢復、checkpoint 都還在。</p>
<h3 id="執行退出指令的-protocol">執行：退出指令的 protocol</h3>
<p>收到退出指令時、依序處理：</p>
<table>
  <thead>
      <tr>
          <th>步驟</th>
          <th>動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>暫停執行、不要立刻刪</td>
      </tr>
      <tr>
          <td>2</td>
          <td>確認「還原到哪個狀態」（上個 commit / 特定 commit / 完全乾淨）</td>
      </tr>
      <tr>
          <td>3</td>
          <td>評估「當前進度有保留價值嗎」 — 探索成果、未採用方案、可能未來重用</td>
      </tr>
      <tr>
          <td>4</td>
          <td>有保留價值 → 先 commit checkpoint、message 標明「探索、未採用」</td>
      </tr>
      <tr>
          <td>5</td>
          <td>執行還原（reset / checkout / revert）</td>
      </tr>
      <tr>
          <td>6</td>
          <td>確認還原後狀態符合使用者意圖</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="checkpoint-的命名與-commit-message">Checkpoint 的命名與 commit message</h2>
<p>當前進度作為 checkpoint commit、message 應該包含：</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">chore(explore): N+1 attempts to remove disclosure marker
</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">探索方向：用 ::-webkit-details-marker / ::marker / display: block 三層
</span></span><span class="line"><span class="ln">4</span><span class="cl">覆寫移除 disclosure 三角圖示。
</span></span><span class="line"><span class="ln">5</span><span class="cl">寫了 5 條 CSS 跨 3 種瀏覽器、覆寫成本過高。
</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">此 commit 保留探索成果、未來若評估值得做時可參考。</span></span></code></pre></div><p>關鍵元素：</p>
<ul>
<li><strong><code>chore(explore):</code></strong> prefix — 標明非正式採用</li>
<li><strong>探索方向</strong> — 說明做了什麼</li>
<li><strong>最終決定</strong> — 為什麼不採用</li>
<li><strong>保留理由</strong> — 未來何時可能重用</li>
</ul>
<p>未來人看到這個 commit、知道「這是探索、不是當前實作」、不會誤用。</p>
<hr>
<h2 id="內在屬性比較四種退出處理">內在屬性比較：四種退出處理</h2>
<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><code>git reset --hard</code>（未 commit 直接丟）</td>
          <td>低 — git reflog 短期還在</td>
          <td>困難</td>
          <td>確定不要</td>
      </tr>
      <tr>
          <td><code>git stash</code>（暫存到 stash）</td>
          <td>中 — stash 可隨時恢復</td>
          <td>中</td>
          <td>短期暫停</td>
      </tr>
      <tr>
          <td><code>git commit</code> checkpoint 後 reset / revert</td>
          <td>高 — commit 永久存在</td>
          <td>容易</td>
          <td>探索性嘗試、未採用方案</td>
      </tr>
  </tbody>
</table>
<p>優先選 checkpoint 方式 — 為未來保留比較與恢復的可能性。</p>
<hr>
<h2 id="退出意圖的辨識">退出意圖的辨識</h2>
<h3 id="從語氣判斷">從語氣判斷</h3>
<table>
  <thead>
      <tr>
          <th>語氣</th>
          <th>對應意圖</th>
          <th>推薦處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「先還原」</td>
          <td>暫時、可能重做</td>
          <td>Checkpoint + 還原</td>
      </tr>
      <tr>
          <td>「先還原、不要做了」</td>
          <td>確定放棄</td>
          <td>Checkpoint（小機率重看） + 還原</td>
      </tr>
      <tr>
          <td>「重來」</td>
          <td>換個方向</td>
          <td>Checkpoint + 還原到起點</td>
      </tr>
      <tr>
          <td>「不要這樣寫」</td>
          <td>局部修正、不是全還原</td>
          <td>局部改、不要全還原</td>
      </tr>
  </tbody>
</table>
<p>不確定就問。「不要這樣寫」這類指令容易被理解成「全還原」、實際只是「這段重寫」。</p>
<h3 id="確認意圖的問法">確認意圖的問法</h3>





<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">  □ 完全還原、刪掉這次的 CSS
</span></span><span class="line"><span class="ln">3</span><span class="cl">  □ 還原但保留 commit checkpoint、未來可能參考
</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">
</span></span><span class="line"><span class="ln">6</span><span class="cl">或是其他？</span></span></code></pre></div><hr>
<h2 id="設計取捨退出指令的處理策略">設計取捨：退出指令的處理策略</h2>
<p>四種做法、各自機會成本不同。這個專案選 A（Checkpoint + 確認還原範圍）當預設、其他做法在特定情境合理。</p>
<h3 id="acommit-checkpoint--確認還原範圍這個專案的預設">A：Commit checkpoint + 確認還原範圍（這個專案的預設）</h3>
<ul>
<li><strong>機制</strong>：commit 當前進度（標明「探索、未採用」）+ 問「還原到哪個 commit」+ 執行還原</li>
<li><strong>選 A 的理由</strong>：未來想比較或恢復都還在、checkpoint 成本只是多一個 commit</li>
<li><strong>適合</strong>：探索性嘗試、未採用方案的退出</li>
<li><strong>代價</strong>：多一個 commit 在歷史中（可後續 squash 或保留）</li>
</ul>
<h3 id="bgit-stash-暫存">B：<code>git stash</code> 暫存</h3>
<ul>
<li><strong>機制</strong>：把未 commit 的變更存到 stash、不污染 commit 歷史</li>
<li><strong>跟 A 的取捨</strong>：B 不留 commit、A 留 commit；B 適合「短期暫停、之後恢復」、A 適合「長期探索紀錄」</li>
<li><strong>B 比 A 好的情境</strong>：暫時切到別的工作、之後一定會回來繼續</li>
</ul>
<h3 id="cgit-reset---hard直接丟">C：<code>git reset --hard</code>（直接丟）</h3>
<ul>
<li><strong>機制</strong>：reset 到指定 commit、未 commit 的變更全失去</li>
<li><strong>跟 A 的取捨</strong>：C 完全清乾淨、A 保留紀錄；C 在 git reflog 內短期還能恢復、但之後永久消失</li>
<li><strong>C 才合理的情境</strong>：確定不要的探索、且確認不需要未來參考</li>
</ul>
<h3 id="d直接刪檔案不留-git-紀錄">D：直接刪檔案、不留 git 紀錄</h3>
<ul>
<li><strong>機制</strong>：手動刪 / 改、不 commit</li>
<li><strong>成本特別高的原因</strong>：未來想比較或恢復都做不到、使用者選項被收窄</li>
<li><strong>D 是反模式</strong>：git 是免費的紀錄工具、不用反而是浪費 — 未來想比較或恢復都做不到、使用者選項被收窄</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>應該觸發的處理</th>
          <th>第一個該做的事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「先還原」</td>
          <td>確認還原範圍 + checkpoint</td>
          <td>問「還原到哪」</td>
      </tr>
      <tr>
          <td>「重來」</td>
          <td>確認重做起點 + checkpoint</td>
          <td>問「從哪重來」</td>
      </tr>
      <tr>
          <td>「不要做了」</td>
          <td>評估保留價值</td>
          <td>探索成本高就 checkpoint、否則直接刪</td>
      </tr>
      <tr>
          <td>「先放著」</td>
          <td>Stash 或 branch 保留</td>
          <td>不要刪、要留可恢復路徑</td>
      </tr>
      <tr>
          <td>「換個方法試試」</td>
          <td>Checkpoint + 換方向</td>
          <td>保留現方法的進度</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：退出指令的執行不該收窄使用者的未來選項。Checkpoint = 給未來保留可能性、成本只是多一個 commit。</p>
]]></content:encoded></item><item><title>篩選類指令的澄清時機</title><link>https://tarrragon.github.io/blog/report/filter-instruction-clarification/</link><pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/filter-instruction-clarification/</guid><description>&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>&lt;strong>「依 X 篩選」這類指令、寫之前必須澄清三件事&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>篩選的&lt;strong>定義域&lt;/strong>是「已載入的子集」還是「全部結果」？&lt;/li>
&lt;li>資料源是&lt;strong>一次性給完整 dataset&lt;/strong> 還是&lt;strong>分批 / 限額&lt;/strong>？&lt;/li>
&lt;li>「沒命中」與「還沒抓到」要不要在 UI 上&lt;strong>區分&lt;/strong>？&lt;/li>
&lt;/ol>
&lt;p>三問沒跑完就直接寫、必然寫成視覺層 post-filter（最容易實作的版本）、撞上 #55 &lt;a href="../view-layer-filter-vs-source-layer/">Filter 與 Source 的層錯位&lt;/a>。&lt;/p>
&lt;p>這是 &lt;a href="../decide-vs-confirm-boundary/">#16-23 第三輪指令澄清&lt;/a> 的第 5 類：篩選類指令。&lt;/p>
&lt;p>跟前四類的差別：&lt;/p>
&lt;ul>
&lt;li>空間 / 位置 / 隔離類（#16-#18）— 缺的是&lt;strong>幾何資訊&lt;/strong>（數字、layout、邊界）&lt;/li>
&lt;li>決定權類（#21）— 缺的是&lt;strong>誰拍板&lt;/strong>（visible 三問）&lt;/li>
&lt;li>篩選類（本卡）— 缺的是&lt;strong>操作的層級&lt;/strong>（filter 的 stream 範圍 = 哪一層的「一筆」）&lt;/li>
&lt;/ul>
&lt;p>前四類的澄清能避免實作走錯方向、第 5 類能避免架構上錯層（#55 層錯位）。&lt;/p>
&lt;hr>
&lt;h2 id="為什麼篩選指令需要獨立的澄清協議">為什麼篩選指令需要獨立的澄清協議&lt;/h2>
&lt;p>「依 X 篩選」的指令在使用者口中是一個簡單訴求、在實作上有兩個獨立決策：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>語意決策&lt;/strong>：filter 的定義域是哪一層？&lt;/li>
&lt;li>&lt;strong>UX 決策&lt;/strong>：邊界 state（loading / empty / partial）怎麼呈現？&lt;/li>
&lt;/ul>
&lt;p>兩個決策不澄清、執行者預設選最簡單版本（view 層 + silent fail）— 但這版本對應的使用者意圖通常不是使用者真的要的。&lt;/p>
&lt;hr>
&lt;h2 id="三問模板">三問模板&lt;/h2>
&lt;h3 id="問-1定義域">問 1：定義域&lt;/h3>





&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">「依 X 篩選」是指：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">(a) 在已載入的結果裡找 X 符合的（filter 範圍 = 已抓的子集）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">(b) 在所有結果裡找 X 符合的（filter 範圍 = 完整 dataset）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">(c) 重新搜尋、把 X 當成 query 條件（filter ≡ 改 query）
&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">通常 (b) 是使用者預期、但實作成本看 (c) 是不是 source 支援的。哪一個？&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>回答決定 filter 該寫在哪一層（見 #55）。&lt;/p>
&lt;h3 id="問-2資料源型態">問 2：資料源型態&lt;/h3>





&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">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">(a) 一次性給完整 dataset（靜態陣列、一次 fetch 到底）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">(b) 分批 / 限額（pagefind、paginated API、infinite scroll）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">(c) Streaming（SSE / WebSocket、來多少看多少）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">(d) Cached + revalidate（先 cache 後 fresh）
&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">(a) 沒有層錯位風險、直接寫 view 層 filter；
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">(b)(c)(d) 必須跟 source 對齊或加自動續抓 / 誠實 UX。&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>問 1 跟問 2 的組合決定實作模式：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>&lt;/th>
 &lt;th>Source (a) 一次性&lt;/th>
 &lt;th>Source (b)(c)(d) 分批&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>定義域 (a)&lt;/td>
 &lt;td>view filter OK&lt;/td>
 &lt;td>view filter + 誠實 UX&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>定義域 (b)&lt;/td>
 &lt;td>view filter OK&lt;/td>
 &lt;td>自動續抓、或 push 到 query&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>定義域 (c)&lt;/td>
 &lt;td>改 query&lt;/td>
 &lt;td>改 query&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="問-3空狀態區分">問 3：空狀態區分&lt;/h3>





&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">當 filter 後 0 筆顯示、要不要區分：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">(a) 「沒命中」（已抓完、確定 0）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">(b) 「還沒抓到」（已載入子集裡 0、source 還有）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">(c) 「載入中」（fetch 還在跑）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">(d) 「載入失敗」
&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">通常 (a)(b)(c)(d) 都該區分（見 #57 三狀態）、但實作上能忍受多少混為一談？&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>回答決定 UX 要做到多細（見 #57 &lt;a href="../loading-empty-end-state-distinction/">Loading / Empty / End 三狀態的區分&lt;/a>）。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心原則">核心原則</h2>
<p><strong>「依 X 篩選」這類指令、寫之前必須澄清三件事</strong>：</p>
<ol>
<li>篩選的<strong>定義域</strong>是「已載入的子集」還是「全部結果」？</li>
<li>資料源是<strong>一次性給完整 dataset</strong> 還是<strong>分批 / 限額</strong>？</li>
<li>「沒命中」與「還沒抓到」要不要在 UI 上<strong>區分</strong>？</li>
</ol>
<p>三問沒跑完就直接寫、必然寫成視覺層 post-filter（最容易實作的版本）、撞上 #55 <a href="../view-layer-filter-vs-source-layer/">Filter 與 Source 的層錯位</a>。</p>
<p>這是 <a href="../decide-vs-confirm-boundary/">#16-23 第三輪指令澄清</a> 的第 5 類：篩選類指令。</p>
<p>跟前四類的差別：</p>
<ul>
<li>空間 / 位置 / 隔離類（#16-#18）— 缺的是<strong>幾何資訊</strong>（數字、layout、邊界）</li>
<li>決定權類（#21）— 缺的是<strong>誰拍板</strong>（visible 三問）</li>
<li>篩選類（本卡）— 缺的是<strong>操作的層級</strong>（filter 的 stream 範圍 = 哪一層的「一筆」）</li>
</ul>
<p>前四類的澄清能避免實作走錯方向、第 5 類能避免架構上錯層（#55 層錯位）。</p>
<hr>
<h2 id="為什麼篩選指令需要獨立的澄清協議">為什麼篩選指令需要獨立的澄清協議</h2>
<p>「依 X 篩選」的指令在使用者口中是一個簡單訴求、在實作上有兩個獨立決策：</p>
<ul>
<li><strong>語意決策</strong>：filter 的定義域是哪一層？</li>
<li><strong>UX 決策</strong>：邊界 state（loading / empty / partial）怎麼呈現？</li>
</ul>
<p>兩個決策不澄清、執行者預設選最簡單版本（view 層 + silent fail）— 但這版本對應的使用者意圖通常不是使用者真的要的。</p>
<hr>
<h2 id="三問模板">三問模板</h2>
<h3 id="問-1定義域">問 1：定義域</h3>





<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">「依 X 篩選」是指：
</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">(a) 在已載入的結果裡找 X 符合的（filter 範圍 = 已抓的子集）
</span></span><span class="line"><span class="ln">4</span><span class="cl">(b) 在所有結果裡找 X 符合的（filter 範圍 = 完整 dataset）
</span></span><span class="line"><span class="ln">5</span><span class="cl">(c) 重新搜尋、把 X 當成 query 條件（filter ≡ 改 query）
</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">通常 (b) 是使用者預期、但實作成本看 (c) 是不是 source 支援的。哪一個？</span></span></code></pre></div><p>回答決定 filter 該寫在哪一層（見 #55）。</p>
<h3 id="問-2資料源型態">問 2：資料源型態</h3>





<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">(a) 一次性給完整 dataset（靜態陣列、一次 fetch 到底）
</span></span><span class="line"><span class="ln">4</span><span class="cl">(b) 分批 / 限額（pagefind、paginated API、infinite scroll）
</span></span><span class="line"><span class="ln">5</span><span class="cl">(c) Streaming（SSE / WebSocket、來多少看多少）
</span></span><span class="line"><span class="ln">6</span><span class="cl">(d) Cached + revalidate（先 cache 後 fresh）
</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">(a) 沒有層錯位風險、直接寫 view 層 filter；
</span></span><span class="line"><span class="ln">9</span><span class="cl">(b)(c)(d) 必須跟 source 對齊或加自動續抓 / 誠實 UX。</span></span></code></pre></div><p>問 1 跟問 2 的組合決定實作模式：</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>Source (a) 一次性</th>
          <th>Source (b)(c)(d) 分批</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>定義域 (a)</td>
          <td>view filter OK</td>
          <td>view filter + 誠實 UX</td>
      </tr>
      <tr>
          <td>定義域 (b)</td>
          <td>view filter OK</td>
          <td>自動續抓、或 push 到 query</td>
      </tr>
      <tr>
          <td>定義域 (c)</td>
          <td>改 query</td>
          <td>改 query</td>
      </tr>
  </tbody>
</table>
<h3 id="問-3空狀態區分">問 3：空狀態區分</h3>





<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">當 filter 後 0 筆顯示、要不要區分：
</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">(a) 「沒命中」（已抓完、確定 0）
</span></span><span class="line"><span class="ln">4</span><span class="cl">(b) 「還沒抓到」（已載入子集裡 0、source 還有）
</span></span><span class="line"><span class="ln">5</span><span class="cl">(c) 「載入中」（fetch 還在跑）
</span></span><span class="line"><span class="ln">6</span><span class="cl">(d) 「載入失敗」
</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">通常 (a)(b)(c)(d) 都該區分（見 #57 三狀態）、但實作上能忍受多少混為一談？</span></span></code></pre></div><p>回答決定 UX 要做到多細（見 #57 <a href="../loading-empty-end-state-distinction/">Loading / Empty / End 三狀態的區分</a>）。</p>
<hr>
<h2 id="多面向篩選指令的不同形式">多面向：篩選指令的不同形式</h2>
<h3 id="形式-1boolean-篩選">形式 1：Boolean 篩選</h3>
<p>「只看標記為 favorite 的」「只看 type = post」 — 屬性匹配、二元。</p>
<p>通常推到 query 層（formula: <code>type = post</code>）、不在 view 層 hide。</p>
<h3 id="形式-2substring--regex-篩選">形式 2：Substring / regex 篩選</h3>
<p>「title 含 X」「內文匹配某 pattern」 — 字串搜尋、可能跨欄位。</p>
<p>如果 source 有 full-text index、推到 query；沒有 → 自動續抓 + 應用 regex。</p>
<h3 id="形式-3範圍篩選">形式 3：範圍篩選</h3>
<p>「日期在 X-Y 之間」「分數 &gt; 80」 — 連續值區間。</p>
<p>通常 source 支援（SQL <code>BETWEEN</code>、API 的 ?from=&amp;to=）、推到 query。</p>
<h3 id="形式-4facet多選交集">形式 4：Facet（多選交集）</h3>
<p>「type=post AND tag=js AND date&gt;2024」 — 多條件組合。</p>
<p>實作通常是 source 支援多 filter 參數、UI 提供 facet 介面。每個 facet 獨立澄清三問。</p>
<h3 id="形式-5客製計算後篩選">形式 5：客製計算後篩選</h3>
<p>「閱讀時間 &gt; 5 分鐘」「distance &lt; 1 km」 — 需要計算、source 通常不會直接支援。</p>
<p>要嘛預先計算後存到 source（推到 query）、要嘛接受「在已載入子集裡計算」的語意縮小。</p>
<hr>
<h2 id="設計取捨澄清的時機與形式">設計取捨：澄清的時機與形式</h2>
<h3 id="a寫第一行-code-前澄清三問">A：寫第一行 code 前澄清三問</h3>
<ul>
<li><strong>機制</strong>：使用者下指令、執行者立刻列三問、給三問的選項、讓使用者選</li>
<li><strong>選 A 的理由</strong>：避免錯實作、避免層錯位</li>
<li><strong>代價</strong>：對話成本中（三問 + 選項）</li>
</ul>
<h3 id="b邊寫邊發現邊問">B：邊寫邊發現邊問</h3>
<ul>
<li><strong>機制</strong>：先寫 view 層、發現邊界 case 不對再回問</li>
<li><strong>跟 A 的取捨</strong>：B 對話成本看起來低、但累積的重做成本高（架構已選錯方向）</li>
<li><strong>B 才合理的情境</strong>：原型 / 探索期、選錯架構成本低</li>
</ul>
<h3 id="c執行者自己選一個版本commit看使用者驗收">C：執行者自己選一個版本、commit、看使用者驗收</h3>
<ul>
<li><strong>跟 A 的取捨</strong>：C 把分析丟給使用者驗收、把使用者意圖跟實作不匹配的成本後置</li>
<li><strong>C 才合理的情境</strong>：執行者跟使用者是同一人、或預期會多輪迭代</li>
</ul>
<h3 id="d忽略澄清直接寫-view-層-silent-post-filter反模式">D：忽略澄清、直接寫 view 層 silent post-filter（反模式）</h3>
<ul>
<li><strong>為什麼是反模式</strong>：寫出的版本對應的不是使用者意圖、撞上 <a href="../view-layer-filter-vs-source-layer/">#55 層錯位</a>、ship 後 silent 失敗</li>
<li><strong>看起來吸引人的原因</strong>：對話成本看起來最低（不用問三問）、5 行 forEach 解決</li>
<li><strong>實際發生的代價</strong>：使用者誤以為「沒命中」、放棄使用、得不到回報（silent 失敗最隱蔽）</li>
</ul>
<hr>
<h2 id="判讀徵兆">判讀徵兆</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>收到「依 X 篩選」「只看 X」「過濾 Y」這類指令</td>
          <td>跑三問、列選項</td>
      </tr>
      <tr>
          <td>即將寫 <code>elements.forEach(el =&gt; el.hidden = !matches(el))</code></td>
          <td>三問先跑</td>
      </tr>
      <tr>
          <td>Source 是分批的、且使用者沒明示「filter 範圍」</td>
          <td>必問問 1 — 定義域</td>
      </tr>
      <tr>
          <td>Filter 後可能 0 筆、且使用者沒明示「沒命中 vs 還沒抓到」要不要區分</td>
          <td>必問問 3 — 空狀態</td>
      </tr>
      <tr>
          <td>內心 OS：「先做 view 層、晚點補資料層」</td>
          <td>停 — 跑完三問、確認方向再寫</td>
      </tr>
  </tbody>
</table>
<p><strong>核心原則</strong>：篩選指令的「簡單表面」掩蓋了三個獨立決策。澄清三問是必要、不是過度溝通 — 跳過任一問就會寫成「能用但跟意圖有縫」的版本。</p>
]]></content:encoded></item><item><title>跨專業溝通用情境遞進、不用比喻堆疊</title><link>https://tarrragon.github.io/blog/report/cross-expertise-communication-scenario-not-analogy/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/cross-expertise-communication-scenario-not-analogy/</guid><description>&lt;h2 id="論述基礎與限制">論述基礎與限制&lt;/h2>
&lt;p>本卡抽自 infra 教學模組的溝通層文章重寫。原稿用辦公大樓比喻解釋 VPC / IAM / IaC 等概念給非工程決策者，經作者 review 判定比喻程度過重、反而阻礙溝通。重寫後改為管理視角的情境遞進。限制：evidence 來自單一模組的一次重寫，跨領域（醫療→管理、法律→工程等）的適用性未驗證。&lt;/p>
&lt;h2 id="核心原則">核心原則&lt;/h2>
&lt;p>向非本領域的專業人士解釋技術議題時，有效的做法是減少術語、讓情境從簡單到複雜遞進。堆疊比喻（「VPC 像辦公大樓」「IAM 像門禁卡」「state 像資產清冊」）看似降低門檻，但有三個結構性問題。&lt;/p>
&lt;p>第一，比喻傳遞形狀但不傳遞嚴重性。「VPC 像辦公大樓的圍牆」讓人理解隔離這個概念，但不讓人理解隔離失敗時一個被入侵的服務能橫向存取所有資料庫的商業代價。決策者需要的是後者。&lt;/p>
&lt;p>第二，比喻在細節處崩解。辦公大樓沒有 CIDR 地址空間、沒有 peering、沒有跨區冗餘。當討論深入到需要判斷「CIDR 該切多大」或「要不要跨帳號」時，比喻不但幫不上忙，還會成為錯誤直覺的來源 — 讀者開始用辦公大樓的邏輯推斷網路架構。&lt;/p>
&lt;p>第三，過度比喻隱含「對方聽不懂」的預設。專業決策者能聽懂「環境描述檔讓系統可以在故障後重建」，不需要先繞到「就像建築藍圖」才能理解。多一層比喻是多一層認知負擔，不是少一層。&lt;/p>
&lt;h2 id="情境">情境&lt;/h2>
&lt;p>infra 教材的溝通層文章原稿用延伸比喻架構整篇文章：&lt;/p>
&lt;ul>
&lt;li>VPC = 辦公大樓，有自己的地址範圍&lt;/li>
&lt;li>Subnet = 樓層分區（public = 大廳，private = 辦公區）&lt;/li>
&lt;li>Security group = 每個房間的門禁卡設定&lt;/li>
&lt;li>IAM = 員工證與權限&lt;/li>
&lt;li>IaC = 建築藍圖&lt;/li>
&lt;li>State = 資產清冊&lt;/li>
&lt;/ul>
&lt;p>每個比喻單獨看都成立，但串在一起時文章變成了一個辦公室管理指南，讀者要在「比喻世界」和「技術世界」之間反覆切換。決策者讀完後記住的是比喻、不是操作風險。&lt;/p>
&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>對應的 infra 能力&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>1&lt;/td>
 &lt;td>服務掛了，沒人知道怎麼重建&lt;/td>
 &lt;td>環境描述檔（IaC）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2&lt;/td>
 &lt;td>重建了，但不確定跟之前一樣&lt;/td>
 &lt;td>state 追蹤&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3&lt;/td>
 &lt;td>測試時的操作打到了正式客戶&lt;/td>
 &lt;td>環境分離&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>4&lt;/td>
 &lt;td>不知道誰有權限存取什麼&lt;/td>
 &lt;td>身分與權限管控&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>5&lt;/td>
 &lt;td>出事了，查不到是誰在什麼時候改了什麼&lt;/td>
 &lt;td>變更紀錄&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>每一行用決策者熟悉的語言：影響範圍（幾個客戶）、恢復時間（幾小時 vs 幾天）、成本（工程師時間 + 停機損失）。這些維度是決策者日常在處理的，不需要翻譯。&lt;/p>
&lt;p>情境遞進的優勢是它讓對方在自己的認知框架裡接收新資訊 — 管理者懂「服務掛了要能重建」，從這個已知出發、往「怎麼確保重建結果一致」「怎麼避免測試影響正式」遞進，每一步都建立在前一步的理解上。&lt;/p>
&lt;h2 id="沒這樣做的麻煩">沒這樣做的麻煩&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>記住比喻、忘記風險&lt;/strong>：決策者開會時說「那個門禁卡的東西做了嗎」，但說不出它解決什麼問題、不做會怎樣。比喻成了一個替代理解的標籤。&lt;/li>
&lt;li>&lt;strong>比喻限制討論深度&lt;/strong>：當需要討論「要不要把 production 拆到獨立帳號」時，辦公大樓比喻沒有對應物。討論被迫回到技術語言，之前的比喻投資歸零。&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>為每個技術概念都找一個日常比喻（「X 就像 Y」超過三個）&lt;/li>
&lt;li>比喻之間需要互相引用才能成立（「記得剛才說的大樓嗎？這個是大樓裡的…」）&lt;/li>
&lt;li>比喻崩解後要補救（「辦公大樓的比喻在這裡不完全適用，但大致上…」）&lt;/li>
&lt;li>文章的主要結構是比喻而非情境（H2 標題是比喻物、不是管理問題）&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/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/reference-by-semantic-title-not-number/" data-link-title="引用章節用語意標題、不用位置編號：編號是結構排列的 derivation、會隨版本漂移" data-link-desc="跨段落、跨檔引用結構單位（章節 / 階段 / 條列項）時、引用語意標題（副標題）、不引用位置編號（Stage 3、第 5 章、第 3 點）。編號是「目前結構排列」的 derivation、不是 fact；結構重排時編號全部位移、引用點不會報錯、而是 silent 指向錯的內容 — 比 broken link 更難偵測。標題的存在意義就是承載可被引用的語意。是 #44 SSoT 在結構引用維度的實例、#93 identifier-as-fact 家族的 sibling、#84 命名承載語意的引用面延伸。">#155 用語意標題引用、不用位置編號&lt;/a>：情境遞進跟語意引用同源 — 都是用內容本身（情境描述 / 語意標題）承載意義，不靠外部代理物（比喻 / 編號）&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/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 停止訊號&lt;/a>：溝通層文章的 review 停止訊號之一是「比喻已經從輔助變成主體」— 這個 frame 在 Round 3 steelman 可以 catch&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<h2 id="論述基礎與限制">論述基礎與限制</h2>
<p>本卡抽自 infra 教學模組的溝通層文章重寫。原稿用辦公大樓比喻解釋 VPC / IAM / IaC 等概念給非工程決策者，經作者 review 判定比喻程度過重、反而阻礙溝通。重寫後改為管理視角的情境遞進。限制：evidence 來自單一模組的一次重寫，跨領域（醫療→管理、法律→工程等）的適用性未驗證。</p>
<h2 id="核心原則">核心原則</h2>
<p>向非本領域的專業人士解釋技術議題時，有效的做法是減少術語、讓情境從簡單到複雜遞進。堆疊比喻（「VPC 像辦公大樓」「IAM 像門禁卡」「state 像資產清冊」）看似降低門檻，但有三個結構性問題。</p>
<p>第一，比喻傳遞形狀但不傳遞嚴重性。「VPC 像辦公大樓的圍牆」讓人理解隔離這個概念，但不讓人理解隔離失敗時一個被入侵的服務能橫向存取所有資料庫的商業代價。決策者需要的是後者。</p>
<p>第二，比喻在細節處崩解。辦公大樓沒有 CIDR 地址空間、沒有 peering、沒有跨區冗餘。當討論深入到需要判斷「CIDR 該切多大」或「要不要跨帳號」時，比喻不但幫不上忙，還會成為錯誤直覺的來源 — 讀者開始用辦公大樓的邏輯推斷網路架構。</p>
<p>第三，過度比喻隱含「對方聽不懂」的預設。專業決策者能聽懂「環境描述檔讓系統可以在故障後重建」，不需要先繞到「就像建築藍圖」才能理解。多一層比喻是多一層認知負擔，不是少一層。</p>
<h2 id="情境">情境</h2>
<p>infra 教材的溝通層文章原稿用延伸比喻架構整篇文章：</p>
<ul>
<li>VPC = 辦公大樓，有自己的地址範圍</li>
<li>Subnet = 樓層分區（public = 大廳，private = 辦公區）</li>
<li>Security group = 每個房間的門禁卡設定</li>
<li>IAM = 員工證與權限</li>
<li>IaC = 建築藍圖</li>
<li>State = 資產清冊</li>
</ul>
<p>每個比喻單獨看都成立，但串在一起時文章變成了一個辦公室管理指南，讀者要在「比喻世界」和「技術世界」之間反覆切換。決策者讀完後記住的是比喻、不是操作風險。</p>
<h2 id="理想做法">理想做法</h2>
<p>用情境遞進替代比喻堆疊。每個技術概念對應到它解決的管理問題，然後從最簡單的情境開始、逐步加入複雜度：</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>情境</th>
          <th>對應的 infra 能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>服務掛了，沒人知道怎麼重建</td>
          <td>環境描述檔（IaC）</td>
      </tr>
      <tr>
          <td>2</td>
          <td>重建了，但不確定跟之前一樣</td>
          <td>state 追蹤</td>
      </tr>
      <tr>
          <td>3</td>
          <td>測試時的操作打到了正式客戶</td>
          <td>環境分離</td>
      </tr>
      <tr>
          <td>4</td>
          <td>不知道誰有權限存取什麼</td>
          <td>身分與權限管控</td>
      </tr>
      <tr>
          <td>5</td>
          <td>出事了，查不到是誰在什麼時候改了什麼</td>
          <td>變更紀錄</td>
      </tr>
  </tbody>
</table>
<p>每一行用決策者熟悉的語言：影響範圍（幾個客戶）、恢復時間（幾小時 vs 幾天）、成本（工程師時間 + 停機損失）。這些維度是決策者日常在處理的，不需要翻譯。</p>
<p>情境遞進的優勢是它讓對方在自己的認知框架裡接收新資訊 — 管理者懂「服務掛了要能重建」，從這個已知出發、往「怎麼確保重建結果一致」「怎麼避免測試影響正式」遞進，每一步都建立在前一步的理解上。</p>
<h2 id="沒這樣做的麻煩">沒這樣做的麻煩</h2>
<ul>
<li><strong>記住比喻、忘記風險</strong>：決策者開會時說「那個門禁卡的東西做了嗎」，但說不出它解決什麼問題、不做會怎樣。比喻成了一個替代理解的標籤。</li>
<li><strong>比喻限制討論深度</strong>：當需要討論「要不要把 production 拆到獨立帳號」時，辦公大樓比喻沒有對應物。討論被迫回到技術語言，之前的比喻投資歸零。</li>
<li><strong>溝通問題被錯誤歸因</strong>：推不動 infra 時，團隊以為是「沒解釋清楚」，於是加更多比喻。但問題其實是提案語言跟決策語言的框架不對，不是理解力不足。結果越比喻越偏離決策者的關注點。</li>
</ul>
<h2 id="判讀徵兆">判讀徵兆</h2>
<p>寫跨專業溝通文件時，如果發現自己在做以下事情，代表可能掉進了比喻堆疊：</p>
<ul>
<li>為每個技術概念都找一個日常比喻（「X 就像 Y」超過三個）</li>
<li>比喻之間需要互相引用才能成立（「記得剛才說的大樓嗎？這個是大樓裡的…」）</li>
<li>比喻崩解後要補救（「辦公大樓的比喻在這裡不完全適用，但大致上…」）</li>
<li>文章的主要結構是比喻而非情境（H2 標題是比喻物、不是管理問題）</li>
</ul>
<p>替代方式：每個概念用「它解什麼管理問題 + 不做的後果量級」一句話帶入，需要深入時用情境遞進展開。</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/reference-by-semantic-title-not-number/" data-link-title="引用章節用語意標題、不用位置編號：編號是結構排列的 derivation、會隨版本漂移" data-link-desc="跨段落、跨檔引用結構單位（章節 / 階段 / 條列項）時、引用語意標題（副標題）、不引用位置編號（Stage 3、第 5 章、第 3 點）。編號是「目前結構排列」的 derivation、不是 fact；結構重排時編號全部位移、引用點不會報錯、而是 silent 指向錯的內容 — 比 broken link 更難偵測。標題的存在意義就是承載可被引用的語意。是 #44 SSoT 在結構引用維度的實例、#93 identifier-as-fact 家族的 sibling、#84 命名承載語意的引用面延伸。">#155 用語意標題引用、不用位置編號</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>：溝通層文章的 review 停止訊號之一是「比喻已經從輔助變成主體」— 這個 frame 在 Round 3 steelman 可以 catch</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></channel></rss>