<?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/%E9%9C%80%E6%B1%82%E6%BE%84%E6%B8%85/</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>Sun, 26 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E9%9C%80%E6%B1%82%E6%BE%84%E6%B8%85/index.xml" rel="self" type="application/rss+xml"/><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>Clarifying Ambiguous Instructions — 模糊指令澄清協議</title><link>https://tarrragon.github.io/blog/skills/requirement-protocol/clarifying-ambiguous-instructions/</link><pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/skills/requirement-protocol/clarifying-ambiguous-instructions/</guid><description>&lt;p>收到含模糊形容詞或缺數字的指令時 — 把指令翻譯成可驗證的具體輸入、給選項讓使用者點頭、再開始實作。&lt;/p>
&lt;p>適用：空間 / 尺寸（「padding 加大」「對齊」）、相對位置（「在 X 旁邊」「靠近 Y」）、隔離（「不要動 X」「跟 Y 分開」）、決定權（「breakpoint 設多少」）、篩選（「依 X 篩選」「只看 Y」）。
不適用：內部技術選擇（grid / flex、observer 種類）— 那些自決即可、見「可決定 vs 該確認」段落。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>自包含聲明&lt;/strong>：閱讀本文件不需要先讀其他 reference。本文件涵蓋五類模糊指令的澄清模板與「自決 vs 確認」的判準。&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="何時參閱本文件">何時參閱本文件&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>該做的第一件事&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>指令含「加大 / 縮小 / 對齊 / 靠近」但沒給數字&lt;/td>
 &lt;td>列計算過程、給三個選項&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>指令含「在 X 旁 / 上 / 下 / 之間」&lt;/td>
 &lt;td>用文字畫 ASCII layout 草圖、確認佈局&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>指令含「不要動 X」「跟 Y 分開」「隔離 Z」&lt;/td>
 &lt;td>確認邊界類型（DOM / layout / state）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>即將寫死一個 breakpoint / 預設值 / 順序 / UI 文字&lt;/td>
 &lt;td>列選項 + 推薦、不要自決&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>指令含「依 X 篩選」「只看 X」「過濾 Y」&lt;/td>
 &lt;td>跑篩選三問（定義域 / 資料源型態 / 空狀態）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>不確定某個決定該自決還是攤給使用者&lt;/td>
 &lt;td>跑「visible 三問」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="為什麼模糊指令需要獨立的澄清協議">為什麼模糊指令需要獨立的澄清協議&lt;/h2>
&lt;p>模糊指令的核心問題是&lt;strong>指令的資訊量不足以唯一決定實作&lt;/strong>。執行者若直接寫死、結果可能跟使用者預期不符；使用者只能在看到結果後才能說「不對」、然後重做。&lt;/p>
&lt;p>把澄清拉到實作前 = 用對話成本（給選項 + 推薦）換掉重做成本。但所有事都確認 = 對話爆炸。協議的價值在於分辨「該攤的」與「該自決的」。&lt;/p>
&lt;hr>
&lt;h2 id="visible-三問自決還是確認">「visible 三問」：自決還是確認&lt;/h2>
&lt;p>任一個答「是」 → 該確認；全「否」 → 可自決。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>問題&lt;/th>
 &lt;th>範例 → 該確認&lt;/th>
 &lt;th>範例 → 可自決&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Q1：這個決定在 UI 上會產生使用者感知的差異嗎？&lt;/td>
 &lt;td>breakpoint、預設尺寸、初始視覺&lt;/td>
 &lt;td>用 grid 還是 flex 排兩欄&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Q2：選不同會不會影響使用者體驗？&lt;/td>
 &lt;td>filter 排序、選單順序&lt;/td>
 &lt;td>ResizeObserver 還是 setInterval&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Q3：寫進 commit 後改動成本高嗎？&lt;/td>
 &lt;td>section 名稱、URL 結構、檔案命名&lt;/td>
 &lt;td>內部 helper function 名稱&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>確認時的格式&lt;/strong>：給選項 + 推薦 + 開放修改。&lt;/p>
&lt;blockquote>
&lt;p>較差：「Breakpoint 應該設多少？」（開放問題、把分析丟給使用者）&lt;/p>
&lt;p>較好：「Breakpoint 我預估三個選項：1280px / 1400px / 1564px。我會選 1400px、有 120px 餘裕、平衡安全與緊湊。OK 嗎？或要其他？」&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="四類模糊指令的澄清模板">四類模糊指令的澄清模板&lt;/h2>
&lt;h3 id="類型-1空間--尺寸類缺數字">類型 1：空間 / 尺寸類（缺數字）&lt;/h3>
&lt;p>&lt;strong>徵兆&lt;/strong>：「padding 加大」「對齊」「靠近一點」「再窄一些」&lt;/p>
&lt;p>&lt;strong>協議&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>列計算過程：「Filter sidebar 寬 = main padding + sidebar 寬度 + gap = 16 + 320 + 24 = 360px」&lt;/li>
&lt;li>列假設來源：「H1 高度從 design token 讀（48px）；form 高度量測（72px）；gap 16px 取自 base unit」&lt;/li>
&lt;li>給三檔選項（緊 / 中 / 鬆）+ 推薦&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>反例&lt;/strong>：直接寫 &lt;code>padding: 24px&lt;/code>、沒交代為什麼是 24。使用者只能視覺驗收、不對就重做。&lt;/p></description><content:encoded><![CDATA[<p>收到含模糊形容詞或缺數字的指令時 — 把指令翻譯成可驗證的具體輸入、給選項讓使用者點頭、再開始實作。</p>
<p>適用：空間 / 尺寸（「padding 加大」「對齊」）、相對位置（「在 X 旁邊」「靠近 Y」）、隔離（「不要動 X」「跟 Y 分開」）、決定權（「breakpoint 設多少」）、篩選（「依 X 篩選」「只看 Y」）。
不適用：內部技術選擇（grid / flex、observer 種類）— 那些自決即可、見「可決定 vs 該確認」段落。</p>
<blockquote>
<p><strong>自包含聲明</strong>：閱讀本文件不需要先讀其他 reference。本文件涵蓋五類模糊指令的澄清模板與「自決 vs 確認」的判準。</p></blockquote>
<hr>
<h2 id="何時參閱本文件">何時參閱本文件</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>該做的第一件事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>指令含「加大 / 縮小 / 對齊 / 靠近」但沒給數字</td>
          <td>列計算過程、給三個選項</td>
      </tr>
      <tr>
          <td>指令含「在 X 旁 / 上 / 下 / 之間」</td>
          <td>用文字畫 ASCII layout 草圖、確認佈局</td>
      </tr>
      <tr>
          <td>指令含「不要動 X」「跟 Y 分開」「隔離 Z」</td>
          <td>確認邊界類型（DOM / layout / state）</td>
      </tr>
      <tr>
          <td>即將寫死一個 breakpoint / 預設值 / 順序 / UI 文字</td>
          <td>列選項 + 推薦、不要自決</td>
      </tr>
      <tr>
          <td>指令含「依 X 篩選」「只看 X」「過濾 Y」</td>
          <td>跑篩選三問（定義域 / 資料源型態 / 空狀態）</td>
      </tr>
      <tr>
          <td>不確定某個決定該自決還是攤給使用者</td>
          <td>跑「visible 三問」</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="為什麼模糊指令需要獨立的澄清協議">為什麼模糊指令需要獨立的澄清協議</h2>
<p>模糊指令的核心問題是<strong>指令的資訊量不足以唯一決定實作</strong>。執行者若直接寫死、結果可能跟使用者預期不符；使用者只能在看到結果後才能說「不對」、然後重做。</p>
<p>把澄清拉到實作前 = 用對話成本（給選項 + 推薦）換掉重做成本。但所有事都確認 = 對話爆炸。協議的價值在於分辨「該攤的」與「該自決的」。</p>
<hr>
<h2 id="visible-三問自決還是確認">「visible 三問」：自決還是確認</h2>
<p>任一個答「是」 → 該確認；全「否」 → 可自決。</p>
<table>
  <thead>
      <tr>
          <th>問題</th>
          <th>範例 → 該確認</th>
          <th>範例 → 可自決</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Q1：這個決定在 UI 上會產生使用者感知的差異嗎？</td>
          <td>breakpoint、預設尺寸、初始視覺</td>
          <td>用 grid 還是 flex 排兩欄</td>
      </tr>
      <tr>
          <td>Q2：選不同會不會影響使用者體驗？</td>
          <td>filter 排序、選單順序</td>
          <td>ResizeObserver 還是 setInterval</td>
      </tr>
      <tr>
          <td>Q3：寫進 commit 後改動成本高嗎？</td>
          <td>section 名稱、URL 結構、檔案命名</td>
          <td>內部 helper function 名稱</td>
      </tr>
  </tbody>
</table>
<p><strong>確認時的格式</strong>：給選項 + 推薦 + 開放修改。</p>
<blockquote>
<p>較差：「Breakpoint 應該設多少？」（開放問題、把分析丟給使用者）</p>
<p>較好：「Breakpoint 我預估三個選項：1280px / 1400px / 1564px。我會選 1400px、有 120px 餘裕、平衡安全與緊湊。OK 嗎？或要其他？」</p></blockquote>
<hr>
<h2 id="四類模糊指令的澄清模板">四類模糊指令的澄清模板</h2>
<h3 id="類型-1空間--尺寸類缺數字">類型 1：空間 / 尺寸類（缺數字）</h3>
<p><strong>徵兆</strong>：「padding 加大」「對齊」「靠近一點」「再窄一些」</p>
<p><strong>協議</strong>：</p>
<ol>
<li>列計算過程：「Filter sidebar 寬 = main padding + sidebar 寬度 + gap = 16 + 320 + 24 = 360px」</li>
<li>列假設來源：「H1 高度從 design token 讀（48px）；form 高度量測（72px）；gap 16px 取自 base unit」</li>
<li>給三檔選項（緊 / 中 / 鬆）+ 推薦</li>
</ol>
<p><strong>反例</strong>：直接寫 <code>padding: 24px</code>、沒交代為什麼是 24。使用者只能視覺驗收、不對就重做。</p>
<h3 id="類型-2相對位置類在-x-旁--上--下--之間">類型 2：相對位置類（「在 X 旁 / 上 / 下 / 之間」）</h3>
<p><strong>徵兆</strong>：「scope 放在搜尋框跟結果之間」「filter 在 sidebar」「按鈕靠右」</p>
<p><strong>協議</strong>：</p>
<ol>
<li>用文字 ASCII 畫 layout 草圖、列出 stacking 與 viewport 行為</li>
<li>標出錨點是誰（誰決定其他元素的位置）</li>
<li>給選項對應「不同 layout 邏輯」、不只是位置</li>
</ol>
<p><strong>範例草圖</strong>：</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">方案 A：grid 縱向排
</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         │
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│  Form       │
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│  Scope      │  ← 在 form 與 results 之間
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│  Results    │
</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">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">方案 B：absolute 疊在 form 下方
</span></span><span class="line"><span class="ln">10</span><span class="cl">┌─────────────┐
</span></span><span class="line"><span class="ln">11</span><span class="cl">│  H1         │
</span></span><span class="line"><span class="ln">12</span><span class="cl">│  Form ──┐   │
</span></span><span class="line"><span class="ln">13</span><span class="cl">│  [scope abs]│  ← 跳出 flow、Form 給 margin-bottom
</span></span><span class="line"><span class="ln">14</span><span class="cl">│  Results    │
</span></span><span class="line"><span class="ln">15</span><span class="cl">└─────────────┘</span></span></code></pre></div><p>兩個方案 layout 邏輯不同、後續維護成本不同 — 給使用者選、不替使用者選。</p>
<h3 id="類型-3隔離類不要動分開">類型 3：隔離類（「不要動」「分開」）</h3>
<p><strong>徵兆</strong>：「不要動 framework 的 DOM」「跟 X 分開」「隔離 Y」</p>
<p><strong>協議</strong>：先確認「隔離」的邊界類型 — 同一句話可能是四種不同意思：</p>
<table>
  <thead>
      <tr>
          <th>邊界類型</th>
          <th>意思</th>
          <th>實作方式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>DOM 結構</td>
          <td>不要新增 / 移除 / reparent 節點</td>
          <td>只用 CSS、不用 JS 動 DOM</td>
      </tr>
      <tr>
          <td>Layout flow</td>
          <td>不要影響其他元素的位置</td>
          <td>absolute / fixed 跳出 flow</td>
      </tr>
      <tr>
          <td>State</td>
          <td>不要共用 state、互不影響</td>
          <td>獨立 store / 獨立 component</td>
      </tr>
      <tr>
          <td>Framework 管轄</td>
          <td>不要進入框架重新渲染的子樹</td>
          <td>把客製 UI 注入到框架邊界外</td>
      </tr>
  </tbody>
</table>
<p>確認模板：「您說的『不要動』是哪一層？是不能動 DOM 結構、不能影響 layout、還是不能進 framework 子樹？」</p>
<h3 id="類型-4決定權類應該設多少">類型 4：決定權類（「應該設多少」）</h3>
<p><strong>徵兆</strong>：使用者用問句回拋、或留下沒明說的數值</p>
<p><strong>協議</strong>：使用者沒明示 → 你先給三個選項 + 推薦、再讓使用者選。<strong>使用者已明示數值</strong> → 直接用、不要再問。</p>
<p>差別判斷：訊息裡有數字（即使粗略）→ 已明示；訊息裡只有概念形容（「再大一點」）→ 沒明示。</p>
<h3 id="類型-5篩選類依-x-篩選只看-y">類型 5：篩選類（「依 X 篩選」「只看 Y」）</h3>
<p><strong>徵兆</strong>：「依 X 篩選」「只看 type=post 的」「過濾掉 Y」「title-only 搜尋」</p>
<p>跟前四類的差別：前四類缺幾何 / 邊界 / 拍板資訊（單一維度）、篩選類<strong>缺操作的層級</strong>（filter 該在 view / 渲染 / 資料 / source 哪一層）。沒澄清就寫 = 必然寫成最便利的 view 層 post-filter、撞上資料層分批時的層錯位。</p>
<p><strong>協議</strong>：跑篩選三問。</p>
<h4 id="問-1定義域">問 1：定義域</h4>





<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><h4 id="問-2資料源型態">問 2：資料源型態</h4>





<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><h4 id="問-3空狀態區分">問 3：空狀態區分</h4>





<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">通常都該區分、但實作上能忍受多少混為一談？</span></span></code></pre></div><p>三問的詳細展開（含 5 種篩選形式 / 跨情境範例 / 後端 + 演算法）見 <a href="/blog/report/filter-instruction-clarification/" data-link-title="篩選類指令的澄清時機" data-link-desc="「依 X 篩選」這類指令必須先澄清三件事才能寫：定義域（已載入 / 全部 / 子集）、資料分批方式、空狀態的語意。三問跑完才寫、否則必然寫成視覺層 post-filter、撞上 #55 層錯位。">#58 篩選類指令的澄清時機</a>；解法策略見 <a href="/blog/report/filter-source-composition-strategies/" data-link-title="Filter × Source 的合成策略五選一" data-link-desc="Filter 跟 paginated / streaming source 合成的五種策略、各自機會成本不同：A 推進 query / B 自動續抓 / C 預先 index / D 誠實 UX / E 接受語意縮小。沒有絕對最佳、看 source capabilities、match 密度、UX 容忍度而定。">#59 Filter × Source 合成策略五選一</a>。</p>
<hr>
<h2 id="wrong-vs-right-對照">Wrong vs Right 對照</h2>
<h3 id="範例-1缺數字的指令">範例 1：缺數字的指令</h3>
<blockquote>
<p>使用者：「filter sidebar 太窄了、加寬一些」</p></blockquote>
<p><strong>錯</strong>：直接改 <code>width: 400px</code>、commit、等使用者驗收。</p>
<p><strong>對</strong>：</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">目前 sidebar 是 320px、main padding 是 16px。我列三個選項：
</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">- 360px：+40、適合多 1 個 facet column
</span></span><span class="line"><span class="ln">4</span><span class="cl">- 400px：+80、舒展、跟 main 1:2.5 比例
</span></span><span class="line"><span class="ln">5</span><span class="cl">- 440px：+120、最寬、main 會被擠到 580px 以下
</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">推薦 400px。OK 嗎？或要其他寬度？</span></span></code></pre></div><h3 id="範例-2相對位置">範例 2：相對位置</h3>
<blockquote>
<p>使用者：「scope 放在搜尋框旁邊」</p></blockquote>
<p><strong>錯</strong>：腦補「旁邊 = 右邊」、用 flex row 排出來。</p>
<p><strong>對</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">「旁邊」我想到三種佈局：
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl">A. Form 右側、跟 input 同一列   → flex row、會擠壓 input 寬度
</span></span><span class="line"><span class="ln">4</span><span class="cl">B. Form 上方                     → absolute、不影響 input
</span></span><span class="line"><span class="ln">5</span><span class="cl">C. Form 下方、結果之上           → grid row 排序、跟 results 共生
</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">推薦 C。或您想的是哪一種？</span></span></code></pre></div><h3 id="範例-3隔離指令">範例 3：隔離指令</h3>
<blockquote>
<p>使用者：「客製 UI 不要動到 pagefind 的 DOM」</p></blockquote>
<p><strong>錯</strong>：理解成「不要 querySelector 它」、結果 inject 到 framework 子樹。</p>
<p><strong>對</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">確認一下「不要動」的邊界 — 是：
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl">(a) 不能 querySelector 也不能 mutate？
</span></span><span class="line"><span class="ln">4</span><span class="cl">(b) 可以查、不能改 attribute / textContent？
</span></span><span class="line"><span class="ln">5</span><span class="cl">(c) 整節點 reparent 也不行？
</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) 是底線（reparent 安全、attribute 改容易被 reconcile 清掉）。
</span></span><span class="line"><span class="ln">8</span><span class="cl">您的需求是哪一層？</span></span></code></pre></div><hr>
<h2 id="自檢清單dogfooding清單本身遵守它教的規則">自檢清單（dogfooding：清單本身遵守它教的規則）</h2>
<p>寫完澄清訊息、回頭檢查：</p>
<ul>
<li><input disabled="" type="checkbox"> 訊息含數字或具體 layout 結構、不只有形容詞</li>
<li><input disabled="" type="checkbox"> 給了 ≥ 2 個選項、含推薦</li>
<li><input disabled="" type="checkbox"> 選項之間的差異是「使用者體驗 / 維護成本」、不只是「實作細節」</li>
<li><input disabled="" type="checkbox"> 沒有把分析負擔丟回給使用者（沒寫「您覺得呢？」這種開放問）</li>
<li><input disabled="" type="checkbox"> 純技術細節沒攤給使用者煩（grid / flex、selector 寫法）</li>
</ul>
<p>如果 ≥ 2 項打勾失敗、訊息回到草稿重寫。</p>
<hr>
<h2 id="延伸閱讀">延伸閱讀</h2>
<p>對應的事後檢討（在 <code>content/report/</code> 目錄下）：</p>
<ul>
<li><a href="/blog/report/spatial-instruction-clarification/" data-link-title="空間 / 尺寸類指令的澄清時機" data-link-desc="聽到「對齊 X」「擺在 Y 旁邊」但沒給數字時，先列計算過程讓使用者確認、不直接寫死。本文展開這類指令的處理 protocol。">spatial-instruction-clarification</a> — 空間 / 尺寸類</li>
<li><a href="/blog/report/relative-position-instruction-clarification/" data-link-title="元件相對位置類指令的澄清時機" data-link-desc="聽到「X 在 Y 旁邊」時、先用文字畫個 layout 草圖讓使用者確認、不憑直覺擺。本文展開這類指令的處理 protocol。">relative-position-instruction-clarification</a> — 相對位置類</li>
<li><a href="/blog/report/isolation-instruction-clarification/" data-link-title="隔離程度類指令的澄清時機" data-link-desc="聽到「隔離」「不要動 X」時、先確認邊界是 DOM 結構、layout flow、state、還是 framework 管轄區。本文展開隔離邊界的四種類型與澄清方式。">isolation-instruction-clarification</a> — 隔離類</li>
<li><a href="/blog/report/decide-vs-confirm-boundary/" data-link-title="「可決定」與「該先確認」的邊界" data-link-desc="寫死任何使用者會看到的數字 / 順序 / 文字之前、先給選項讓使用者點頭。技術實作細節可以自決。本文展開兩者的區分原則。">decide-vs-confirm-boundary</a> — 可決定 vs 該確認的完整判準</li>
</ul>
<hr>
<p><strong>Last Updated</strong>: 2026-04-26
<strong>Version</strong>: 0.1.0</p>
]]></content:encoded></item><item><title>Requirement Protocol — 需求確認到實作的對話協議</title><link>https://tarrragon.github.io/blog/skills/requirement-protocol/</link><pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/skills/requirement-protocol/</guid><description>&lt;h2 id="這個資料夾是什麼">這個資料夾是什麼&lt;/h2>
&lt;p>&lt;code>requirement-protocol&lt;/code> 是一套對話協議 skill，原生位置在 &lt;a href="https://github.com/tarrragon/blog/tree/main/.claude/skills/requirement-protocol">&lt;code>.claude/skills/requirement-protocol/&lt;/code>&lt;/a> 供 Claude runtime 呼叫；這份是&lt;strong>同內容的文章版本&lt;/strong>，讓人類讀者也能直接在 blog 閱讀。&lt;/p>
&lt;p>把「使用者下指令 → 執行者實作」之間的溝通流程結構化、避免反覆失敗、避免做出使用者沒要的東西、避免在錯誤方向上累積沉沒成本。源頭是 &lt;a href="https://tarrragon.github.io/blog/report/" data-link-title="Report — 開發過程的事後檢討" data-link-desc="blog 開發過程中、把實際遇到的版型 / 整合 / 框架共處等情境、整理成『應該怎麼做、沒這樣做會有什麼麻煩』的事後檢討。每篇皆為正向指引、幫助下一輪同類任務跳過反覆試錯。">&lt;code>content/report/&lt;/code>&lt;/a> 累積的 50+ 篇事後檢討、由本 skill 的五份 reference 萃取對應五個情境的協議步驟。&lt;/p>
&lt;h2 id="閱讀順序">閱讀順序&lt;/h2>
&lt;h3 id="場景-1第一次接觸">場景 1：第一次接觸&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>1&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/skill/" data-link-title="Requirement Protocol — SKILL 入口" data-link-desc="從需求確認到實作的對話協議 SKILL 入口：四大支柱（含 multi-pass refinement）、七大原則速查、六份情境 reference（含篩選類指令、決策呈現五維度）的觸發路由 &amp;#43; 抽象層原則網路。">SKILL.md&lt;/a>&lt;/td>
 &lt;td>三大支柱 + 六大原則速查、觸發路由表&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2&lt;/td>
 &lt;td>依情境挑一份 reference（見下表）&lt;/td>
 &lt;td>把原則翻譯成可套用的協議步驟、模板與範例&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3&lt;/td>
 &lt;td>該 reference 結尾的 self-check checklist&lt;/td>
 &lt;td>自評有沒有按協議走&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="場景-2已熟悉協議想直接解決當前任務">場景 2：已熟悉協議、想直接解決當前任務&lt;/h3>
&lt;p>直接依觸發情境跳對應 reference：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>觸發情境&lt;/th>
 &lt;th>reference&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>收到模糊指令（含「對齊」「靠近」「隔離」「不要動」「分開」等）&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/clarifying-ambiguous-instructions/" data-link-title="Clarifying Ambiguous Instructions — 模糊指令澄清協議" data-link-desc="requirement-protocol reference：空間 / 相對位置 / 隔離 / 決定權 / 篩選五類模糊指令的澄清模板 &amp;#43; visible 三問判準 &amp;#43; 篩選三問。">clarifying-ambiguous-instructions&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>不確定某個決定該自決還是該先問使用者&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/clarifying-ambiguous-instructions/" data-link-title="Clarifying Ambiguous Instructions — 模糊指令澄清協議" data-link-desc="requirement-protocol reference：空間 / 相對位置 / 隔離 / 決定權 / 篩選五類模糊指令的澄清模板 &amp;#43; visible 三問判準 &amp;#43; 篩選三問。">clarifying-ambiguous-instructions&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>同方向失敗 ≥ 2 次、想再試一次更小心&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/failure-pivot-protocol/" data-link-title="Failure Pivot Protocol — 失敗 2 次的轉折協議" data-link-desc="requirement-protocol reference：同方向失敗 2 次的轉折協議 — 停下、驗證底層假設、換方向、對外回報模板。">failure-pivot-protocol&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推理 + 視覺截圖溝通迴圈卡住、不知道該不該換工具&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/tool-switching-timing/" data-link-title="Tool Switching Timing — 推理 / DevTools / Playwright 的切換時機" data-link-desc="requirement-protocol reference：四種 debug 工具的 ROI 對照、切換訊號、playwright 三個位置（假設 / 行為 / 互動驗證）。">tool-switching-timing&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>客製需求要對抗多層（vendor CSS、framework、browser default）&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/cost-and-checkpoint/" data-link-title="Cost &amp;amp; Checkpoint — 覆寫成本告知與 revert checkpoint" data-link-desc="requirement-protocol reference：對抗多層的覆寫成本告知 &amp;#43; 「先還原 / 先重來」類退出指令的 checkpoint commit 處理。">cost-and-checkpoint&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>收到「先還原 / 先重來 / 換個方向」類指令&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/cost-and-checkpoint/" data-link-title="Cost &amp;amp; Checkpoint — 覆寫成本告知與 revert checkpoint" data-link-desc="requirement-protocol reference：對抗多層的覆寫成本告知 &amp;#43; 「先還原 / 先重來」類退出指令的 checkpoint commit 處理。">cost-and-checkpoint&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>開始 UI layout debug、不知道從哪一步起&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/progressive-verification/" data-link-title="Progressive Verification — 漸進驗證與最小必要範圍" data-link-desc="requirement-protocol reference：placeholder 漸進除錯 &amp;#43; measurement 完整性 &amp;#43; minimum necessary scope 三原則。">progressive-verification&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>設計 selector / MutationObserver root / JS 操作範圍&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/skills/requirement-protocol/progressive-verification/" data-link-title="Progressive Verification — 漸進驗證與最小必要範圍" data-link-desc="requirement-protocol reference：placeholder 漸進除錯 &amp;#43; measurement 完整性 &amp;#43; minimum necessary scope 三原則。">progressive-verification&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>每份 reference 自包含：讀任一份不需要回頭讀其他 reference。&lt;/p></description><content:encoded><![CDATA[<h2 id="這個資料夾是什麼">這個資料夾是什麼</h2>
<p><code>requirement-protocol</code> 是一套對話協議 skill，原生位置在 <a href="https://github.com/tarrragon/blog/tree/main/.claude/skills/requirement-protocol"><code>.claude/skills/requirement-protocol/</code></a> 供 Claude runtime 呼叫；這份是<strong>同內容的文章版本</strong>，讓人類讀者也能直接在 blog 閱讀。</p>
<p>把「使用者下指令 → 執行者實作」之間的溝通流程結構化、避免反覆失敗、避免做出使用者沒要的東西、避免在錯誤方向上累積沉沒成本。源頭是 <a href="/blog/report/" data-link-title="Report — 開發過程的事後檢討" data-link-desc="blog 開發過程中、把實際遇到的版型 / 整合 / 框架共處等情境、整理成『應該怎麼做、沒這樣做會有什麼麻煩』的事後檢討。每篇皆為正向指引、幫助下一輪同類任務跳過反覆試錯。"><code>content/report/</code></a> 累積的 50+ 篇事後檢討、由本 skill 的五份 reference 萃取對應五個情境的協議步驟。</p>
<h2 id="閱讀順序">閱讀順序</h2>
<h3 id="場景-1第一次接觸">場景 1：第一次接觸</h3>
<table>
  <thead>
      <tr>
          <th>順序</th>
          <th>檔案</th>
          <th>目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td><a href="/blog/skills/requirement-protocol/skill/" data-link-title="Requirement Protocol — SKILL 入口" data-link-desc="從需求確認到實作的對話協議 SKILL 入口：四大支柱（含 multi-pass refinement）、七大原則速查、六份情境 reference（含篩選類指令、決策呈現五維度）的觸發路由 &#43; 抽象層原則網路。">SKILL.md</a></td>
          <td>三大支柱 + 六大原則速查、觸發路由表</td>
      </tr>
      <tr>
          <td>2</td>
          <td>依情境挑一份 reference（見下表）</td>
          <td>把原則翻譯成可套用的協議步驟、模板與範例</td>
      </tr>
      <tr>
          <td>3</td>
          <td>該 reference 結尾的 self-check checklist</td>
          <td>自評有沒有按協議走</td>
      </tr>
  </tbody>
</table>
<h3 id="場景-2已熟悉協議想直接解決當前任務">場景 2：已熟悉協議、想直接解決當前任務</h3>
<p>直接依觸發情境跳對應 reference：</p>
<table>
  <thead>
      <tr>
          <th>觸發情境</th>
          <th>reference</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>收到模糊指令（含「對齊」「靠近」「隔離」「不要動」「分開」等）</td>
          <td><a href="/blog/skills/requirement-protocol/clarifying-ambiguous-instructions/" data-link-title="Clarifying Ambiguous Instructions — 模糊指令澄清協議" data-link-desc="requirement-protocol reference：空間 / 相對位置 / 隔離 / 決定權 / 篩選五類模糊指令的澄清模板 &#43; visible 三問判準 &#43; 篩選三問。">clarifying-ambiguous-instructions</a></td>
      </tr>
      <tr>
          <td>不確定某個決定該自決還是該先問使用者</td>
          <td><a href="/blog/skills/requirement-protocol/clarifying-ambiguous-instructions/" data-link-title="Clarifying Ambiguous Instructions — 模糊指令澄清協議" data-link-desc="requirement-protocol reference：空間 / 相對位置 / 隔離 / 決定權 / 篩選五類模糊指令的澄清模板 &#43; visible 三問判準 &#43; 篩選三問。">clarifying-ambiguous-instructions</a></td>
      </tr>
      <tr>
          <td>同方向失敗 ≥ 2 次、想再試一次更小心</td>
          <td><a href="/blog/skills/requirement-protocol/failure-pivot-protocol/" data-link-title="Failure Pivot Protocol — 失敗 2 次的轉折協議" data-link-desc="requirement-protocol reference：同方向失敗 2 次的轉折協議 — 停下、驗證底層假設、換方向、對外回報模板。">failure-pivot-protocol</a></td>
      </tr>
      <tr>
          <td>推理 + 視覺截圖溝通迴圈卡住、不知道該不該換工具</td>
          <td><a href="/blog/skills/requirement-protocol/tool-switching-timing/" data-link-title="Tool Switching Timing — 推理 / DevTools / Playwright 的切換時機" data-link-desc="requirement-protocol reference：四種 debug 工具的 ROI 對照、切換訊號、playwright 三個位置（假設 / 行為 / 互動驗證）。">tool-switching-timing</a></td>
      </tr>
      <tr>
          <td>客製需求要對抗多層（vendor CSS、framework、browser default）</td>
          <td><a href="/blog/skills/requirement-protocol/cost-and-checkpoint/" data-link-title="Cost &amp; Checkpoint — 覆寫成本告知與 revert checkpoint" data-link-desc="requirement-protocol reference：對抗多層的覆寫成本告知 &#43; 「先還原 / 先重來」類退出指令的 checkpoint commit 處理。">cost-and-checkpoint</a></td>
      </tr>
      <tr>
          <td>收到「先還原 / 先重來 / 換個方向」類指令</td>
          <td><a href="/blog/skills/requirement-protocol/cost-and-checkpoint/" data-link-title="Cost &amp; Checkpoint — 覆寫成本告知與 revert checkpoint" data-link-desc="requirement-protocol reference：對抗多層的覆寫成本告知 &#43; 「先還原 / 先重來」類退出指令的 checkpoint commit 處理。">cost-and-checkpoint</a></td>
      </tr>
      <tr>
          <td>開始 UI layout debug、不知道從哪一步起</td>
          <td><a href="/blog/skills/requirement-protocol/progressive-verification/" data-link-title="Progressive Verification — 漸進驗證與最小必要範圍" data-link-desc="requirement-protocol reference：placeholder 漸進除錯 &#43; measurement 完整性 &#43; minimum necessary scope 三原則。">progressive-verification</a></td>
      </tr>
      <tr>
          <td>設計 selector / MutationObserver root / JS 操作範圍</td>
          <td><a href="/blog/skills/requirement-protocol/progressive-verification/" data-link-title="Progressive Verification — 漸進驗證與最小必要範圍" data-link-desc="requirement-protocol reference：placeholder 漸進除錯 &#43; measurement 完整性 &#43; minimum necessary scope 三原則。">progressive-verification</a></td>
      </tr>
  </tbody>
</table>
<p>每份 reference 自包含：讀任一份不需要回頭讀其他 reference。</p>
<h2 id="與-blog-專案其他資料的關係">與 blog 專案其他資料的關係</h2>
<table>
  <thead>
      <tr>
          <th>位置</th>
          <th>角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>.claude/skills/requirement-protocol/</code></td>
          <td>實際 skill — Claude runtime 呼叫的檔案來源</td>
      </tr>
      <tr>
          <td><code>content/skills/requirement-protocol/</code>（本處）</td>
          <td>文章版本 — 人類讀者在 blog 閱讀</td>
      </tr>
      <tr>
          <td><a href="/blog/report/" data-link-title="Report — 開發過程的事後檢討" data-link-desc="blog 開發過程中、把實際遇到的版型 / 整合 / 框架共處等情境、整理成『應該怎麼做、沒這樣做會有什麼麻煩』的事後檢討。每篇皆為正向指引、幫助下一輪同類任務跳過反覆試錯。"><code>content/report/</code></a></td>
          <td>50+ 篇事後檢討、本 skill 的素材來源；reference 結尾連回對應篇</td>
      </tr>
      <tr>
          <td><code>.claude/skills/compositional-writing/</code></td>
          <td>寫作方法論 skill — 本 skill 的 references 撰寫品質依此規範</td>
      </tr>
  </tbody>
</table>
<h2 id="last-updated">Last Updated</h2>
<p>2026-04-26 — 初版：v0.1.0 同步、五份 references 對應「模糊指令 / 失敗轉折 / 成本與 checkpoint / 漸進驗證 / 工具切換」五個情境。</p>
]]></content:encoded></item></channel></rss>